commons-io-2.16.1-src/CONTRIBUTING.md0100644 0000000 0000000 00000014704 14603604450 017246 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). This is not essential, but makes providing patches much easier. + 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. If you don't have a GitHub account, you can still clone the Commons repository. Making Changes -------------- + Create a _topic branch_ for your isolated work. * Usually you should base your branch on the `master` 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) [cla]:https://www.apache.org/licenses/#clas [jira]:https://issues.apache.org/jira/browse/IO commons-io-2.16.1-src/LICENSE.txt0100644 0000000 0000000 00000026137 14603604450 016643 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.16.1-src/NOTICE.txt0100644 0000000 0000000 00000000254 14603604450 016532 0ustar00rootroot0000000 0000000 Apache Commons IO Copyright 2002-2024 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (https://www.apache.org/). commons-io-2.16.1-src/PROPOSAL.html0100644 0000000 0000000 00000005753 14603604450 017146 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.16.1-src/README.md0100644 0000000 0000000 00000014517 14603604450 016276 0ustar00rootroot0000000 0000000 Apache Commons IO =================== [![Java CI](https://github.com/apache/commons-io/actions/workflows/maven.yml/badge.svg)](https://github.com/apache/commons-io/actions/workflows/maven.yml) [![Coverage Status](https://codecov.io/gh/apache/commons-io/branch/master/graph/badge.svg)](https://app.codecov.io/gh/apache/commons-io) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/commons-io/commons-io/badge.svg?gav=true)](https://maven-badges.herokuapp.com/maven-central/commons-io/commons-io/?gav=true) [![Javadocs](https://javadoc.io/badge/commons-io/commons-io/2.16.1.svg)](https://javadoc.io/doc/commons-io/commons-io/2.16.1) [![CodeQL](https://github.com/apache/commons-io/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/apache/commons-io/actions/workflows/codeql-analysis.yml) [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/apache/commons-io/badge)](https://api.securityscorecards.dev/projects/github.com/apache/commons-io) 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](https://commons.apache.org/mail-lists.html). Getting 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.16.1 ``` Building -------- Building requires a Java JDK and [Apache Maven](https://maven.apache.org/). The required Java version is found in the `pom.xml` as the `maven.compiler.source` property. From a command shell, run `mvn` without arguments to invoke the default Maven goal to run all tests and checks. Contributing ------------ We accept Pull Requests via GitHub. The [developer mailing list](https://commons.apache.org/mail-lists.html) 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 existing code style for each file. + 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```. 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 licensed under the [Apache License v2](https://www.apache.org/licenses/LICENSE-2.0). See the `NOTICE.txt` file for required notices and attributions. Donating -------- You like Apache Commons IO? Then [donate back to the ASF](https://www.apache.org/foundation/contributing.html) to support development. Additional Resources -------------------- + [Apache Commons Homepage](https://commons.apache.org/) + [Apache Issue Tracker (JIRA)](https://issues.apache.org/jira/browse/IO) + [Apache Commons Slack Channel](https://the-asf.slack.com/archives/C60NVB8AD) + [Apache Commons Twitter Account](https://twitter.com/ApacheCommons) Apache Commons Components ------------------------- Please see the [list of components](https://commons.apache.org/components.html) commons-io-2.16.1-src/RELEASE-NOTES.txt0100644 0000000 0000000 00000347107 14603604450 017532 0ustar00rootroot0000000 0000000 Apache Commons IO 2.16.1 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. Java 8 is required. Fixed Bugs ---------- o Reimplement FileSystemUtils using NIO. Thanks to Gary Gregory. o IO-851: FileSystemUtils no longer throws IllegalStateException. Thanks to Sebb, Gary Gregory. o Avoid possible NullPointerException in FileUtils.listAccumulate(File, IOFileFilter, IOFileFilter, FileVisitOption...). Thanks to Gary Gregory. o IO-853: BoundedInputStream.reset() not updating count. Thanks to Mike Drob, Gary Gregory. o ThresholdingOutputStream: a negative threshold should behave like a zero threshold and trigger the event on the first write #609. Thanks to rproserpio, Gary Gregory. Changes ------- o Bump commons.bytebuddy.version from 1.14.12 to 1.14.13 #605. Thanks to Gary Gregory. o Bump org.apache.commons:commons-parent from 67 to 69 #608. Thanks to Gary Gregory, Dependabot. Commons IO 2.7 and up requires Java 8 or above. Commons IO 2.6 requires Java 7 or above. Commons IO 2.3 through 2.5 requires Java 6 or above. Commons IO 2.2 requires Java 5 or above. Commons IO 1.4 requires Java 1.3 or above. 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 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 2.16.1 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. Java 8 is required. Fixed Bugs ---------- o Reimplement FileSystemUtils using NIO. Thanks to Gary Gregory. o IO-851: FileSystemUtils no longer throws IllegalStateException. Thanks to Sebb, Gary Gregory. o Avoid possible NullPointerException in FileUtils.listAccumulate(File, IOFileFilter, IOFileFilter, FileVisitOption...). Thanks to Gary Gregory. o IO-853: BoundedInputStream.reset() not updating count. Thanks to Mike Drob, Gary Gregory. Changes ------- o Bump commons.bytebuddy.version from 1.14.12 to 1.14.13 #605. Thanks to Gary Gregory. o Bump org.apache.commons:commons-parent from 67 to 69 #608. Thanks to Gary Gregory, Dependabot. Commons IO 2.7 and up requires Java 8 or above. Commons IO 2.6 requires Java 7 or above. Commons IO 2.3 through 2.5 requires Java 6 or above. Commons IO 2.2 requires Java 5 or above. Commons IO 1.4 requires Java 1.3 or above. 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 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 2.16.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. Java 8 is required. New features ------------ o Add and use PathUtils.getFileName(Path, Function). Thanks to Gary Gregory. o Add and use PathUtils.getFileNameString(). Thanks to Gary Gregory. o Make public Erase.rethrow(Throwable). Thanks to Gary Gregory. o IO-826: Add BrokenInputStream.BrokenInputStream(Throwable). Thanks to markslater, Gary Gregory. o IO-826: Add BrokenReader.BrokenReader(Throwable). Thanks to markslater, Gary Gregory. o IO-826: Add BrokenOutputStream.BrokenOutputStream(Throwable). Thanks to markslater, Gary Gregory. o IO-826: Add BrokenWriter.BrokenWriter(Throwable). Thanks to markslater, Gary Gregory. o Add BoundedInputStream.getRemaining(). Thanks to Gary Gregory. o Add FileTimes.toNtfsTime(long). Thanks to Gary Gregory. o Add FileTimes.fromUnixTime(long). Thanks to Gary Gregory. o Add FileTimes.isUnixTime(FileTime). Thanks to Gary Gregory. o Add FileTimes.isUnixTime(long). Thanks to Gary Gregory. o Add FileTimes.toUnixTime(FileTime). Thanks to Gary Gregory. o Add BrokenInputStream.Builder. Thanks to Gary Gregory. o Add PathUtils.getExtension(Path). Thanks to Gary Gregory. o Add PathUtils.getBaseName(Path). Thanks to Gary Gregory. o Add ThrottledInputStream. Thanks to Gary Gregory. o Add IORunnable.noop(). Thanks to Gary Gregory. o Add ChecksumInputStream and test #548. Thanks to Gary Gregory. o Add AbstractStreamBuilder.getReader(). Thanks to Gary Gregory. o Add Maven property project.build.outputTimestamp for build reproducibility. Thanks to Gary Gregory. o Add ProxyInputStream.unwrap(). Thanks to Gary Gregory. o Add a running count and builder to BoundedInputStream. Thanks to Gary Gregory. Fixed Bugs ---------- o Fix and re-enable testSkip_RequiredCharsets #518. Thanks to Elliotte Rusty Harold. o IO-824: SymbolicLineFileFilter documentation fixes. Thanks to Miguel Munoz, Gary Gregory. o IO-795: CharSequenceInputStream.reset() only works once #520. Thanks to Miguel Munoz, Gary Gregory. o IO-795: Finish TODO on CharSequenceInputStream #540. Thanks to Elliotte Rusty Harold. o IO-825: Add byte array size validation for methods in EndianUtils #521. Thanks to Arthur Chan, Gary Gregory. o IO-825: Add missing test case CircularByteBufferTest. Thanks to dkdal, Gary Gregory. o IO-781: Make CharSequenceInputStream.available() more correct in the face of multibyte encodings #525. Thanks to Elliotte Rusty Harold. o IO-781: Remove unreachable code in AbstractIOFileFilterTest #526. Thanks to Elliotte Rusty Harold. o IO-808: Rationalize and unify checking for existence of files and directories #529. Thanks to Elliotte Rusty Harold. o Avoid NullPointerException in IOCase.checkEquals(String, String) on null input. Thanks to Gary Gregory. o Avoid NullPointerException in CanExecuteFileFilter.accept(File) on null input. Thanks to Gary Gregory. o Avoid NullPointerException in CanExecuteFileFilter.accept(Path, BasicFileAttributes) on null input. Thanks to Gary Gregory. o Avoid NullPointerException in CanReadFileFilter.accept(File) on null input. Thanks to Gary Gregory. o Avoid NullPointerException in CanReadFileFilter.accept(Path, BasicFileAttributes) on null input. Thanks to Gary Gregory. o Avoid NullPointerException in CanWriteFileFilter.accept(File) on null input. Thanks to Gary Gregory. o Avoid NullPointerException in CanWriteFileFilter.accept(Path, BasicFileAttributes) on null input. Thanks to Gary Gregory. o Avoid NullPointerException in DirectoryFileFilter.accept(File) on null input. Thanks to Gary Gregory. o Avoid NullPointerException in DirectoryFileFilter.accept(Path, BasicFileAttributes) on null input. Thanks to Gary Gregory. o Avoid NullPointerException in EmptyFileFilter.accept(File) on null input. Thanks to Gary Gregory. o Avoid NullPointerException in EmptyFileFilter.accept(Path, BasicFileAttributes) on null input. Thanks to Gary Gregory. o Avoid NullPointerException in FileFileFilter.accept(File) on null input. Thanks to Gary Gregory. o Avoid NullPointerException in FileFileFilter.accept(Path, BasicFileAttributes) on null input. Thanks to Gary Gregory. o Avoid NullPointerException in HiddenFileFilter.accept(File) on null input. Thanks to Gary Gregory. o Avoid NullPointerException in HiddenFileFilter.accept(Path, BasicFileAttributes) on null input. Thanks to Gary Gregory. o Avoid NullPointerException in IOCase.checkIndexOf(String, int, String) on null input. Thanks to Gary Gregory. o Avoid NullPointerException in IOCase.checkRegionMatches(String, int, String) on null input. Thanks to Gary Gregory. o BoundedInputStream.getCount() should not count EOF. Thanks to Gary Gregory. o Modernize temporary file creation and deletion in DeferredFileOutputStreamTest #535. Thanks to Elliotte Rusty Harold, Gary Gregory. o Add PathMatcher to IOFileFilter class Javadoc #536. Thanks to Elliotte Rusty Harold. o IO-781: Fix CharSequenceInputStream coding exception handling #537. Thanks to Marcono1234. o IO-781: Deprecate int CountingInputStream#getCount() in favor of long CountingInputStream#getByteCount(). Thanks to Marcono1234. o IO-828: Deprecate CountingInputStream.resetCount() in favor of resetByteCount(). Thanks to Elliotte Rusty Harold, Gary Gregory. o IO-828: Deprecate CountingInputStream.getMaxLength() in favor of getMaxCount()). Thanks to Gary Gregory. o IO-818: NullInputStream breaks InputStream's read method contract. Thanks to Gary Gregory. o Javadoc shouldn't reference 1.x behavior #539. Thanks to Elliotte Rusty Harold. o IO-829: Don't decode and reencode characters in a potentially different charset in AbstractOrigin.CharSequenceOrigin.getReader(Charset). Thanks to Elliotte Rusty Harold, Gary Gregory. o Let subclasses of CountingInputStream.afterRead(int) throw IOException. Thanks to Gary Gregory. o IO-807: Characterization test for broken symlinks when copying directories #547. Thanks to Elliotte Rusty Harold, Gary Gregory. o ClosedInputStream.read(byte[], int, int) does not always return -1. Thanks to Gary Gregory. o ClosedOutputStream.write(byte[], int, int) does not always throw IOException. Thanks to Gary Gregory. o XmlStreamReader can't parse an XML document with a multi-line prolog #550. Thanks to Sylwester Lachiewicz, Gary Gregory. o XmlStreamReader can't parse XML an document with an external parsed entity prolog. Thanks to Andreas Hubold, Gary Gregory. o IO-836: Update FileNameUtils Javadoc #554. Thanks to Elliotte Rusty Harold. o IO-807: Copy symlinks, not the files the symlinks point to #558. Thanks to Jordi Sola, Elliotte Rusty Harold. o Pickup apache-rat-plugin version from parent POM. Thanks to Gary Gregory. o Add test for copying a symlink FileUtilsTest#testCopyFile_symLink() #564. Thanks to Elliotte Rusty Harold. o Make copyFile copy symbolic links by value rather than reference #565. Thanks to Elliotte Rusty Harold. o Deprecate CopyUtils 0-argument constructor. Thanks to Gary Gregory. o IO-843: Deprecate EndianUtils 0-argument constructor. Thanks to Gary Gregory, Elliotte Rusty Harold. o Deprecate FileSystemUtils 0-argument constructor. Thanks to Gary Gregory. o Deprecate FilenameUtils 0-argument constructor. Thanks to Gary Gregory. o Deprecate RandomAccessFiles 0-argument constructor. Thanks to Gary Gregory. o Clarify and correct EndianUtils and SwappedDataInputStream API doc #566. Thanks to Elliotte Rusty Harold, Gary Gregory. o Add characterization test for copying a symlinked directory #570. Thanks to Elliotte Rusty Harold. o RandomAccessFileInputStream.builder().get() now throws ISE instead of NPE. Thanks to Gary Gregory. o IO-845: Test links to targets outside the source directory #571. Thanks to Elliotte Rusty Harold. o Focus Javadoc on current version rather than past versions #573, #574. Thanks to Elliotte Rusty Harold. o IO-469: "Self-suppression not permitted" while using BrokenOutput and BrokenInput streams with try-with-resources. Thanks to Grigory Fadeev, Kristian Rosenvold, Elliotte Rusty Harold. o IO-405: Handle zero and negative thresholds #587. Thanks to Elliotte Rusty Harold. o Deprecate CountingInputStream in favor of BoundedInputStream. Thanks to Gary Gregory. o PathUtils.setPosixPermissions(...) only sets permissions if needed. Thanks to Gary Gregory. o PathUtils.setReadOnly(...) only sets permissions if needed. Thanks to Gary Gregory. o PathUtils.deleteFile(..., DeleteOption...) only sets permissions if needed. Thanks to Gary Gregory. o CleaningPathVisitor only sets permissions if needed. Thanks to Gary Gregory. o DeletingPathVisitor only sets permissions if needed. Thanks to Gary Gregory. Changes ------- o Bump commons.bytebuddy.version from 1.14.10 to 1.14.12 #534, #592. Thanks to Gary Gregory. o Bump org.apache.commons:commons-parent from 65 to 67. Thanks to Gary Gregory. o Bump commons-codec:commons-codec from 1.16.0 to 1.16.1 #583. Thanks to Dependabot. o Bump org.codehaus.mojo:exec-maven-plugin from 3.1.1 to 3.2.0 #593. Thanks to Dependabot. Commons IO 2.7 and up requires Java 8 or above. Commons IO 2.6 requires Java 7 or above. Commons IO 2.3 through 2.5 requires Java 6 or above. Commons IO 2.2 requires Java 5 or above. Commons IO 1.4 requires Java 1.3 or above. 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 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.15.1 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. Java 8 is required. Fixed Bugs ---------- * Fix wrong issue id in change log #503. Thanks to Gregor Dschung. * Add test for FileChannels.contentEquals() #509. Thanks to Stephan Markwalder, Gary Gregory. * Fix FileChannels.contentEquals(). Thanks to Gary Gregory. * Fix some Javadoc issues in LineIterator and IOUtils. Thanks to Gary Gregory. * Simplify FileAlterationObserver internal processing. Thanks to Gary Gregory. * Avoid NullPointerException in RegexFileFilter.RegexFileFilter(Pattern). Thanks to Gary Gregory. * Avoid NullPointerException in RegexFileFilter.accept(Path, BasicFileAttributes). Thanks to Gary Gregory. * Fix SpotBugs error: Class org.apache.commons.io.filefilter.RegexFileFilter defines non-transient non-serializable instance field pathToString [org.apache.commons.io.filefilter.RegexFileFilter] In RegexFileFilter.java SE_BAD_FIELD. Thanks to Gary Gregory. * Fix SpotBugs error: Class org.apache.commons.io.filefilter.DelegateFileFilter defines non-transient non-serializable instance field fileFilter [org.apache.commons.io.filefilter.DelegateFileFilter] In DelegateFileFilter.java SE_BAD_FIELD. Thanks to Gary Gregory. * Fix SpotBugs error: Class org.apache.commons.io.filefilter.DelegateFileFilter defines non-transient non-serializable instance field fileNameFilter [org.apache.commons.io.filefilter.DelegateFileFilter] In DelegateFileFilter.java SE_BAD_FIELD. Thanks to Gary Gregory. * Fix SpotBugs error: org.apache.commons.io.function.IOStream$1.next() cannot throw NoSuchElementException [org.apache.commons.io.function.IOStream$1] At IOStream.java:[line 98] IT_NO_SUCH_ELEMENT. Thanks to Gary Gregory. * Fix SpotBugs error: org.apache.commons.io.monitor.FileAlterationMonitor.getObservers() may expose internal representation by returning FileAlterationMonitor.observers [org.apache.commons.io.monitor.FileAlterationMonitor] At FileAlterationMonitor.java:[line 124] EI_EXPOSE_REP. Thanks to Gary Gregory. * Fix SpotBugs error: Class org.apache.commons.io.monitor.FileAlterationObserver defines non-transient non-serializable instance field fileFilter [org.apache.commons.io.monitor.FileAlterationObserver] In FileAlterationObserver.java SE_BAD_FIELD. Thanks to Gary Gregory. * Fix SpotBugs error: Class org.apache.commons.io.monitor.FileAlterationObserver defines non-transient non-serializable instance field listeners [org.apache.commons.io.monitor.FileAlterationObserver] In FileAlterationObserver.java SE_BAD_FIELD. Thanks to Gary Gregory. * Fix SpotBugs error: org.apache.commons.io.FileCleaningTracker.getDeleteFailures() may expose internal representation by returning FileCleaningTracker.deleteFailures [org.apache.commons.io.FileCleaningTracker] At FileCleaningTracker.java:[line 218] EI_EXPOSE_REP. Thanks to Gary Gregory. * Fix SpotBugs error: org.apache.commons.io.IOExceptionList.getCauseList() may expose internal representation by returning IOExceptionList.causeList [org.apache.commons.io.IOExceptionList] At IOExceptionList.java:[line 118] EI_EXPOSE_REP. Thanks to Gary Gregory. * Fix SpotBugs error: org.apache.commons.io.IOExceptionList.getCauseList(Class) may expose internal representation by returning IOExceptionList.causeList [org.apache.commons.io.IOExceptionList] At IOExceptionList.java:[line 129] EI_EXPOSE_REP. Thanks to Gary Gregory. * Fix SpotBugs error: org.apache.commons.io.file.AccumulatorPathVisitor.getDirList() may expose internal representation by returning AccumulatorPathVisitor.dirList [org.apache.commons.io.file.AccumulatorPathVisitor] At AccumulatorPathVisitor.java:[line 179] EI_EXPOSE_REP. Thanks to Gary Gregory. * Fix SpotBugs error: org.apache.commons.io.file.AccumulatorPathVisitor.getFileList() may expose internal representation by returning AccumulatorPathVisitor.fileList [org.apache.commons.io.file.AccumulatorPathVisitor] At AccumulatorPathVisitor.java:[line 188] EI_EXPOSE_REP. Thanks to Gary Gregory. * Fix SpotBugs error: org.apache.commons.io.input.ObservableInputStream.getObservers() may expose internal representation by returning ObservableInputStream.observers [org.apache.commons.io.input.ObservableInputStream] At ObservableInputStream.java:[line 187] EI_EXPOSE_REP. Thanks to Gary Gregory. * Fix SpotBugs error: Exception thrown in class org.apache.commons.io.input.UnsynchronizedByteArrayInputStream at new org.apache.commons.io.input.UnsynchronizedByteArrayInputStream(byte[], int) will leave the constructor. The object under construction remains partially initialized and may be vulnerable to Finalizer attacks. [org.apache.commons.io.input.UnsynchronizedByteArrayInputStream, org.apache.commons.io.input.UnsynchronizedByteArrayInputStream] At UnsynchronizedByteArrayInputStream.java:[line 202]At UnsynchronizedByteArrayInputStream.java:[line 202] CT_CONSTRUCTOR_THROW. Thanks to Gary Gregory. * Fix SpotBugs error: Exception thrown in class org.apache.commons.io.input.UnsynchronizedByteArrayInputStream at new org.apache.commons.io.input.UnsynchronizedByteArrayInputStream(byte[], int, int) will leave the constructor. The object under construction remains partially initialized and may be vulnerable to Finalizer attacks. [org.apache.commons.io.input.UnsynchronizedByteArrayInputStream, org.apache.commons.io.input.UnsynchronizedByteArrayInputStream] At UnsynchronizedByteArrayInputStream.java:[line 223]At UnsynchronizedByteArrayInputStream.java:[line 223] CT_CONSTRUCTOR_THROW. Thanks to Gary Gregory. Changes ------- * Bump org.codehaus.mojo:exec-maven-plugin from 3.1.0 to 3.1.1 #512. Thanks to Gary Gregory. * Bump commons-lang3 from 3.13.0 to 3.14.0. Thanks to Gary Gregory. * Bump commons.bytebuddy.version from 1.14.9 to 1.14.10 #516. Thanks to Dependabot. * Bump commons-parent from 64 to 65. Thanks to Dependabot. Compatibility with 2.6: Binary compatible: Yes. Source compatible: Yes. Semantic compatible: Yes. Commons IO 2.7 and up requires Java 8 or above. Commons IO 2.6 requires Java 7 or above. Commons IO 2.3 through 2.5 requires Java 6 or above. Commons IO 2.2 requires Java 5 or above. Commons IO 1.4 requires Java 1.3 or above. 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 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.15.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. Java 8 is required. New features ------------ * Add org.apache.commons.io.channels.FileChannels. Thanks to Gary Gregory. * Add RandomAccessFiles#contentEquals(RandomAccessFile, RandomAccessFile). Thanks to Gary Gregory. * Add RandomAccessFiles#reset(RandomAccessFile). Thanks to Gary Gregory. * Add PathUtilsContentEqualsBenchmark. Thanks to Gary Gregory. * Add org.apache.commons.io.StreamIterator. Thanks to Gary Gregory. * Add MessageDigestInputStream and deprecate MessageDigestCalculatingInputStream. Thanks to Gary Gregory. Fixed Bugs ---------- * IO-815: XmlStreamReader encoding match RE is too strict. Thanks to Laurence Gonsalves. * IO-810: Javadoc in FileUtils does not reflect code for thrown exceptions. Thanks to Gregor Dschung, Gary Gregory. * IO-812: Javadoc should mention closing Streams based on file resources. Thanks to Adam Rauch, Gary Gregory. * IO-811: In tests, Files.walk() direct and indirect callers fail to close the returned Stream. Thanks to Adam Rauch, Gary Gregory. * IO-811: FileUtils.listFiles(File, String[], boolean) fails to close its internal Stream. Thanks to Adam Rauch, Gary Gregory. * IO-811: FileUtils.iterateFiles(File, String[], boolean) fails to close its internal Stream. Thanks to Adam Rauch, Gary Gregory. * IO-811: StreamIterator fails to close its internal Stream. Thanks to Adam Rauch, Gary Gregory. * IO-814: Don't throw UncheckedIOException #491. Thanks to Elliotte Rusty Harold, Gary Gregory. * IO-414: Don't write a BOM on every (or any) line #492. Thanks to Elliotte Rusty Harold, Gary Gregory. * IO-814: RandomAccessFileMode.create(Path) provides a better NullPointerException message. Thanks to Gary Gregory. * Improve performance of PathUtils.fileContentEquals(Path, Path, LinkOption[], OpenOption[]) by about 60%, see PathUtilsContentEqualsBenchmark. Thanks to Gary Gregory. * Improve performance of PathUtils.fileContentEquals(Path, Path) by about 60%, see PathUtilsContentEqualsBenchmark. Thanks to Gary Gregory. * Improve performance of FileUtils.contentEquals(File, File) by about 60%, see PathUtilsContentEqualsBenchmark. Thanks to Gary Gregory. * Remove unused test code #494. Thanks to Elliotte Rusty Harold. * [Javadoc] IOUtils#contentEquals does not throw NullPointerException #496. Thanks to sebbASF. * Fix CodeQL warnings in UnsynchronizedBufferedInputStream: Implicit narrowing conversion in compound assignment. Thanks to Gary Gregory. * MessageDigestCalculatingInputStream.MessageDigestMaintainingObserver.MessageDigestMaintainingObserver(MessageDigest) now throws a NullPointerException if the MessageDigest is null. Thanks to Gary Gregory. * MessageDigestCalculatingInputStream.MessageDigestCalculatingInputStream(InputStream, MessageDigest) now throws a NullPointerException if the MessageDigest is null. Thanks to Gary Gregory. * IO-816: UnsynchronizedBufferedInputStream.read(byte[], int, int) does not use buffer. Thanks to Andreas Loth, Gary Gregory. Changes ------- * Bump org.apache.commons:commons-parent from 62 to 64. Thanks to Gary Gregory. Compatibility with 2.6: Binary compatible: Yes. Source compatible: Yes. Semantic compatible: Yes. Commons IO 2.7 and up requires Java 8 or above. Commons IO 2.6 requires Java 7 or above. Commons IO 2.3 through 2.5 requires Java 6 or above. Commons IO 2.2 requires Java 5 or above. Commons IO 1.4 requires Java 1.3 or above. 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 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.14.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. Java 8 required. New features ------------ * Add DeferredFileOutputStream.getPath(). Thanks to Gary Gregory. * Add FileCleaningTracker.track(Path, Object[, FileDeleteStrategy]). Thanks to Gary Gregory. * Add IOUtils.skip[Fully](InputStream, long, Supplier). Thanks to Gary Gregory. * Add FilesUncheck.find(Path, int, BiPredicate%lt;Path, BasicFileAttributes>, FileVisitOption...) Thanks to Gary Gregory. * Add IOIntSupplier. Thanks to Gary Gregory. * Add IOLongSupplier. Thanks to Gary Gregory. * Add Uncheck.getAsInt(IOIntSupplier [, Supplier]). Thanks to Gary Gregory. * Add Uncheck.getAsLong(IOLongSupplier [, Supplier]). Thanks to Gary Gregory. * Add Uncheck.run(IORunnable, Supplier) Thanks to Gary Gregory. * Add Uncheck.get(IOSupplier, Supplier) Thanks to Gary Gregory. * IOFileFilter now also extends java.nio.file.PathMatcher. Thanks to Gary Gregory. * Add PathMatcherFileFilter to adapt java.nio.file.PathMatcher. Thanks to Gary Gregory. * Add ThresholdingOutputStream.getOutputStream() and deprecate getStream(). Thanks to Gary Gregory. * Add DeferredFileOutputStream.Builder.setOutputFile(Path). Thanks to Gary Gregory. * Add DeferredFileOutputStream.Builder.setDirectory(Path). Thanks to Gary Gregory. * Add AbstractStreamBuilder.setBufferSizeChecker(IntToIntFunction). Thanks to Gary Gregory. * Add AbstractStreamBuilder.setBufferSizeMax(int). Thanks to Gary Gregory. Fixed Bugs ---------- * IO-799: ReaderInputStream.read() throws an exception instead of returning -1 when called again after returning -1. Thanks to Jeroen van der Vegt, Gary Gregory. * IO-804: FileUtils.forceMkdirParent() Javadoc is incorrect. Thanks to Elliotte Rusty Harold, Gary Gregory. * [StepSecurity] ci: Harden GitHub Actions #461. Thanks to step-security-bot, Gary Gregory. * MagicNumberFileFilter.accept(Path, BasicFileAttributes) doesn't its byteOffset before reading. Thanks to Gary Gregory. * Javadoc improvements. Thanks to Gary Gregory. * Spelling #468. Thanks to Josh Soref, Gary Gregory. * Use assertThrows #475. Thanks to Jakub Kupczyk. Changes ------- * Bump jimfs from 1.2 to 1.3.0 #465 (tests). Thanks to Dependabot. * Bump commons-parent from 58 to 62. Thanks to Gary Gregory. * Bump commons-lang3 from 3.12 to 3.13.0. Thanks to Gary Gregory. Compatibility with 2.6: Binary compatible: Yes. Source compatible: Yes. Semantic compatible: Yes. Commons IO 2.7 and up requires Java 8 or above. Commons IO 2.6 requires Java 7 or above. Commons IO 2.3 through 2.5 requires Java 6 or above. Commons IO 2.2 requires Java 5 or above. Commons IO 1.4 requires Java 1.3 or above. 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 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.13.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. Java 8 required. New features ------------ * Add CharSequenceInputStream.Builder. Thanks to Gary Gregory. * Add ChunkedOutputStream.Builder. Thanks to Gary Gregory. * Add AbstractStreamBuilder.setOpenOptions(OpenOption...). Thanks to Gary Gregory. * Add some missing conversions to AbstractOrigin subclasses. Thanks to Gary Gregory. * Add AbstractOrigin.getByteArray(long, int). Thanks to Gary Gregory. * Add and use RandomAccessFiles. Thanks to Gary Gregory. * Add AbstractOrigin.size(). Thanks to Gary Gregory. * Add PathUtils.EMPTY_FILE_ATTRIBUTE_ARRAY. Thanks to Gary Gregory. * Add CharSequenceInputStream.Builder.setCharsetEncoder(CharsetEncoder). Thanks to Gary Gregory. * Add CharsetEncoders.toCharsetEncoder(CharsetEncoder, Supplier). Thanks to Gary Gregory. Fixed Bugs ---------- * IO-791: Regression in FileUtils.touch() - no longer creates parent directories. Thanks to Chad Wilson, Gary Gregory. * ByteArrayOrigin should be able convert a byte[] to a ByteArrayInputStream. Thanks to Gary Gregory. * AbstractOriginSupplier.checkOrigin() now throws IllegalStateException instead of NullPointerException. Thanks to Gary Gregory. * IO-796: FileAlreadyExistsException in PathUtils.createParentDirectories(Path, LinkOption, FileAttribute...). Thanks to Giacomo Boccardo, Gary Gregory. * Only read the relevant portion of a file in AbstractOrigin.FileOrigin.getByteArray(long, int) Thanks to Gary Gregory. * Only read the relevant portion of a file in AbstractOrigin.PathOrigin.getByteArray(long, int) Thanks to Gary Gregory. * IO-798: DeferredFileOutputStream throws exception when system temp dir is a symlink. Thanks to Shai Shapira, Gary Gregory. * ReaderInputStream.Builder.setCharsetEncoder(null) should reset to a default object, not throw an NPE. Thanks to Gary Gregory. * ReaderInputStream.Builder.setCharset(null) should reset to a default object, not throw an NPE. Thanks to Gary Gregory. Changes ------- * Bump commons-parent from 57 to 58. Thanks to Gary Gregory, Dependabot. Compatibility with 2.6: Binary compatible: Yes. Source compatible: Yes. Semantic compatible: Yes. Commons IO 2.7 and up requires Java 8 or above. Commons IO 2.6 requires Java 7 or above. Commons IO 2.3 through 2.5 requires Java 6 or above. Commons IO 2.2 requires Java 5 or above. Commons IO 1.4 requires Java 1.3 or above. 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 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.12.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. Java 8 required. New features ------------ * IO-746: Drop unnecessary casts and conversions #267. Thanks to Davide Angelocola. * Add GitHub coverage.yml. Thanks to Gary Gregory. * Add BrokenReader.INSTANCE. Thanks to Gary Gregory. * Add UncheckedBufferedReader. Thanks to Gary Gregory. * Add UncheckedFilterReader. Thanks to Gary Gregory. * Add UncheckedFilterWriter. Thanks to Gary Gregory. * Add StringInputStream. Thanks to Gary Gregory. * Add UncheckedFilterInputStream. Thanks to Gary Gregory. * Add UncheckedFilterOutputStream. Thanks to Gary Gregory. * Add BrokenInputStream.INSTANCE. Thanks to Gary Gregory. * Add ClosedInputStream.INSTANCE and deprecate CLOSED_INPUT_STREAM. Thanks to Gary Gregory. * Add ClosedReader.INSTANCE and deprecate CLOSED_READER. Thanks to Gary Gregory. * Add BrokenWriter.INSTANCE. Thanks to Gary Gregory. * Add ClosedOutputStream.INSTANCE and deprecate CLOSED_OUTPUT_STREAM. Thanks to Gary Gregory. * Add ClosedWriter.INSTANCE and deprecate CLOSED_WRITER. Thanks to Gary Gregory. * Add NullOutputStream.INSTANCE and deprecate NULL_OUTPUT_STREAM. Thanks to Gary Gregory. * Add NullPrintStream.INSTANCE and deprecate NULL_PRINT_STREAM. Thanks to Gary Gregory. * Add NullWriter.INSTANCE and deprecate NULL_WRITER. Thanks to Gary Gregory. * Add NullInputStream.INSTANCE. Thanks to Gary Gregory. * Add NullReader.INSTANCE. Thanks to Gary Gregory. * Add PathUtils.readString(Path, Charset). Thanks to Gary Gregory. * Add FileUtils.newOutputStream(File, boolean). Thanks to Gary Gregory. * Add PathUtils.newOutputStream(Path, boolean). Thanks to Gary Gregory. * Add UncheckedAppendable. Thanks to Gary Gregory. * Add and reuse UncheckedIOExceptions. Thanks to Gary Gregory. * Add PathUtils.getTempDirectory(). Thanks to Gary Gregory. * Add FileSystem.getNameSeparator(). Thanks to Gary Gregory. * Add FileSystem.normalizeSeparators(). Thanks to Gary Gregory. * Add PathUtils.isNewer(Path, FileTime, LinkOption...). Thanks to Gary Gregory. * Add PathUtils.isNewer(Path, Instant, LinkOption...). Thanks to Gary Gregory. * Add AgeFileFilter.AgeFileFilter(Instant). Add AgeFileFilter.AgeFileFilter(Instant, boolean). Thanks to Gary Gregory. * Add FileUtils.lastModifiedFileTime(File). Thanks to Gary Gregory. * Add FileTimes. Thanks to Gary Gregory. * Add PathUtils.waitFor(Path, Duration, LinkOption...). Thanks to Gary Gregory. * Add org.apache.commons.io.input.Tailer.getDelayDuration(). Thanks to Gary Gregory. * Add FileUtils.current(). Thanks to Gary Gregory. * Add and use PathUtils.setLastModifiedTime(Path) for more precision. Add and use PathUtils.setLastModifiedTime(Path, Path) for more precision. Thanks to Gary Gregory. * Add and use PathUtils.isNewer(Path, ChronoZonedDateTime, LinkOption...) for more precision. Add and use PathUtils.isNewer(Path, Path) for more precision. Add and use FileUtils.isNewer(File, FileTime) for more precision. Thanks to Gary Gregory. * Add and use PathUtils.isOlder(Path, FileTime, LinkOption...). Add and use PathUtils.isOlder(Path, Instant, LinkOption...). Add and use PathUtils.isOlder(Path, long, LinkOption...). Add and use PathUtils.isOlder(Path, Path). Thanks to Gary Gregory. * Add and use PathUtils.sizeOf(Path). Add and use PathUtils.sizeOfAsBigInteger(Path). Add and use PathUtils.sizeOfDirectory(Path). Add and use PathUtils.sizeOfDirectoryAsBigInteger(Path). Thanks to Gary Gregory. * Add and use IOCase.value(IOCase, IOCase). Thanks to Gary Gregory. * Add Tailer.Tailable interface to allow tailing of remote files for example using jCIFS. Thanks to Jon Freedman, Gary Gregory. * Add and use RandomAccessFileMode. Thanks to Gary Gregory. * Add PathUtils.writeString(Path, CharSequence, Charset, OpenOption...). Thanks to Gary Gregory. * Add PathUtiFiles.getFileAttributeView() shorthands: - PathUtils.getAclFileAttributeView(Path, LinkOption...) - PathUtils.getDosFileAttributeView(Path, LinkOption...) - PathUtils.getPosixFileAttributeView(Path, LinkOption...) Thanks to Gary Gregory. * IO-747: Make commons-io a JPMS module by adding module-info.class. * IO-753: Add IOUtils method to copy output stream to input stream #281. Thanks to SebastianDietrich, Gary Gregory. * Add PathUtils.isPosix(Path, LinkOption...). #290 Thanks to Gary Gregory. * Add PathUtils.readAttributes(Path, Class, LinkOption...). #290 Thanks to Gary Gregory. * Add IOExceptionList.checkEmpty(List, Object). Thanks to Gary Gregory. * Add IOBiConsumer, IOTriConsumer, IOComparator, IOUnaryOperator, IOBinaryOperator. Thanks to Gary Gregory. * Add and reuse IOConsumer forAll(*), forEach(*), and forEachIndexed(*). Thanks to Gary Gregory. * Add CharsetEncoders. Thanks to Gary Gregory. * Add CharsetDecoders. Thanks to Gary Gregory. * Add PathUtils.createParentDirectories(Path, LinkOption, FileAttribute...). Thanks to Gary Gregory. * Update FileEntry to use FileTime instead of long for file time stamps. Thanks to Gary Gregory. * IO-680: Add more tests for IOUtils.contentEqualsIgnoreEOL #137. Thanks to XenoAmess, sebbASF, Gary Gregory. * Reduce boilerplate through new UncheckedIO class and friends in org.apache.commons.io.function. Thanks to Gary Gregory. * Add PathUtils.touch(Path). Thanks to Gary Gregory. * Add FileSystem.getIllegalFileNameCodePoints(). Thanks to Gary Gregory. * Add FileUtils.isFileNewer(File, ChronoLocalDate, OffsetTime). Add FileUtils.isFileNewer(File, OffsetDateTime). Add FileUtils.isFileOlder(File, ChronoLocalDate, OffsetTime). Add FileUtils.isFileOlder(File, OffsetDateTime). Thanks to Isira Seneviratne, Gary Gregory. * Add IOBiConsumer.noop(). Thanks to Gary Gregory. * Add IOUtils.closeQuietly(Iterable). Add IOUtils.closeQuietly(Stream). Thanks to Gary Gregory. * Add Charsets.toCharset(Charset, Charset). Add Charsets.toCharset(String, Charset). Thanks to Gary Gregory. * Add XmlStreamWriter(OutputStream, Charset). Thanks to Gary Gregory. * Add PathUtils.getLastModifiedFileTime(*). Thanks to Gary Gregory. * Add IOBiFunction, IOTriFunction, IOQuadFunction, IOPredicate, IOIterator, IOSpliterator, IOBaseStream, IOStream, FilesUncheck. Thanks to Gary Gregory. * Add IOUtils.consume(Reader). Thanks to Gary Gregory. * Add IOSupplier.asSupplier(). Thanks to Gary Gregory. * Add IOFunction.asFunction(). Thanks to Gary Gregory. * Add IOConsumer.asConsumer(). Thanks to Gary Gregory. * Add TimestampedObserver.isClosed(). Thanks to Gary Gregory. * IOExceptionList implements Iterable. Thanks to Gary Gregory. * IO-784: Add support for Appendable to HexDump #418. Thanks to Fredrik Kjellberg, Gary Gregory. * Add and use ThreadUtils. Thanks to DaGeRe, Gary Gregory. * IO-786: Add UnsynchronizedFilterInputStream. Thanks to Gary Gregory. * IO-786: Add UnsynchronizedBufferedInputStream. Thanks to Gary Gregory, Benoit Tellier. * Add FileSystem.getBlockSize(). Thanks to Gary Gregory. * Add builders and avoid creating more constructors for all permutations of current options. Thanks to Gary Gregory. * Refactor using new Supplier API IOUtils.toString(IOSupplier, Charset[, IOSupplier]). Thanks to Gary Gregory, maxxedev. * Refactor using new Supplier API org.apache.commons.io.file.PathUtils.copy(IOSupplier, Path, CopyOption...). Thanks to Gary Gregory, maxxedev. Fixed Bugs ---------- * IO-697: IOUtils.toByteArray size validation does not match documentation. Thanks to otter606. * Fix Javadoc links to the JRE Javadoc 8. Thanks to Gary Gregory. * IO-744: FileWriterWithEncoding for an existing file no longer truncates the file. #251. Thanks to RBRi, Gary Gregory. * A null Charset or Charset name in FileWriterWithEncoding constructors uses the default Charset. Thanks to Gary Gregory. * Fix usage of assertNotNull #269. Thanks to Davide Angelocola. * IO-727: FilenameUtils directoryContains() should handle files with the same prefix #217. Thanks to trungPa, Gary Gregory. * IO-748: FileUtils.moveToDirectory() exception documentation and exception message error. Thanks to Dirk Heinrichs, Gary Gregory, Elango Ravi. * ThreadMonitor.sleep(Duration) ignores nanoseconds. Thanks to Gary Gregory. * Fix Javadoc in ThreadMonitor#run() method. #273. Thanks to Arturo Bernal. * IO-749: FileUtils.listFiles() does not list matching files if File parameter is a symbolic link. Thanks to haihuiyang, Gary Gregory. * Fix typo in Javadocs for FileUtils#convertFileCollectionToFileArray() #276. Thanks to niranjanghule, Gary Gregory. * Avoid Code Duplication: Reuse Sleep from ThreadMonitor #66. Thanks to DaGeRe, Gary Gregory. * IO-750: FileUtils.iterateFiles also lists directories. Thanks to Sita Gener, Sebastian Peters, Gary Gregory. * IO-721: Wrong exception message in FileUtils.setLastModified(File, File). Thanks to Dirk Heinrichs, Gary Gregory. * IO-717: Infinite loop in ReaderInputStream instead of throwing exception for CodingErrorAction.REPORT. Thanks to Marcono1234, Gary Gregory. * IO-716: ReaderInputStream enter infinite loop for too small buffer sizes. Thanks to Marcono1234, Gary Gregory. * IO-638: Infinite loop in CharSequenceInputStream.read for 4-byte characters with UTF-8 and 3-byte buffer. Thanks to Thayne McCombs, Gary Gregory. * IO-638: PathUtils.setReadOnly(Path, boolean, LinkOption...) should add READ_* file attributes when using POSIX. Thanks to Gary Gregory. * IO-638: PathUtils.setReadOnly(Path, boolean, LinkOption...) readOnly argument is always assumed true on POSIX. Thanks to Gary Gregory. * IO-729: Prevent IllegalArgumentExceptions in BrokenInputStream/Reader/OutputStream/Writer #278. Thanks to Rob Spoor, Gary Gregory. * FileUtils.copyURLToFile(URL, File, int, int) leaks its URLConnection. Called by FileUtils.copyURLToFile(URL, File). Thanks to Gary Gregory. * IO-714: Fixed ReaderInputStream not calling CharsetEncoder.flush issue #283. Thanks to kevinwang1975, Gary Gregory. * Minor changes #287. Thanks to Arturo Bernal. * IO-756: Update FileWriterWithEncoding to extend ProxyWriter #296. Thanks to wodencafe, Gary Gregory, Bruno P. Kinoshita. * Initialize the message of an IOExceptionList to a default if null. Thanks to Gary Gregory. * IO-751: When deleting symlinks, File/PathUtils.deleteDirectory() changes file permissions of the target. Thanks to Gary Gregory, Richard Cyganiak. * ReaderInputStream maps null Charset, Charset name, and CharsetEncoder to the platform default instead of throwing a NullPointerException. Thanks to Gary Gregory. * CharSequenceInputStream maps null Charset and Charset name to the platform default instead of throwing a NullPointerException. Thanks to Gary Gregory. * WriterOutputStream maps null Charset, Charset name, and CharsetEncoder name to the platform default instead of throwing a NullPointerException. Thanks to Gary Gregory. * FileUtils.copyURLToFile should create target parent directories and overwrite target file #319. Thanks to Chad Wilson, Gary Gregory. * IO-484: Fix incorrect FilenameUtils Javadoc for null bytes #310. Thanks to Marcono1234, Gary Gregory. * IO-484: Change to uppercase variable constant. #323. Thanks to Arturo Bernal. * IO-484: IOCase.isCaseSensitive(IOCase) result is backward #325. Thanks to David Huang, Gary Gregory. * IO-758: Deprecate PathUtils.NOFOLLOW_LINK_OPTION_ARRAY in favor of noFollowLinkOptionArray(). Thanks to Marcono1234, Gary Gregory. * Improve ReaderInputStream documentation #291. Thanks to Marcono1234, Gary Gregory. * Fix misleading comments in FileFilterTest #334. Thanks to richarda23. * Add missing Javadoc for exceptions thrown for invalid arguments #339. Thanks to Diego Marcilio. * FileFilterTest minor fixes #340. Thanks to richarda23. * IO-764: IOUtils.write() throws OutOfMemoryError/NegativeArraySizeException while writing big strings #343. Thanks to DaGeRe, Gary Gregory. * IO-768: Add reserved Windows file names CONIN$ and CONOUT$ to FileSystem #355. Thanks to Marcono1234, Michael Osipov. * IO-773: RegexFileFilter is no longer Serializable. Thanks to Dominik Reinarz, Gary Gregory. * IO-763: [Javadoc] FileFilterUtils doc does not match impl: missing some file filters. Thanks to Richard Adams, Gary Gregory. * IO-762: FileSystem.WINDOWS.isReservedFileName doesn't check for file extension. Thanks to Leonidas Chiron, Gary Gregory. * IO-772: Confusing Javadoc on IOUtils#resourceToURL() and other resource* methods. Thanks to Dan Ziemba, Gary Gregory. * IO-443: FileUtils.copyFile methods throw an unnecessary "Failed to copy full contents from" exception. Thanks to Dan Ziemba, Gary Gregory. * IO-564: Pick up Javadoc from super for override write() methods in AbstractByteArrayOutputStream and ByteArrayOutputStream. Thanks to Hao Zhong, Bernd Eckenfels, Pascal Schumacher, Gary Gregory. * Fix minor typos #367. Thanks to Marc Wrobel. * IO-776: Fix parameters to requireNonNull call in DeferredOutputSteam #368. Thanks to Chris Povirk. * Fix PathUtils.copyFileToDirectory(URL,Path,CopyOption[]). Thanks to Gary Gregory. * IO-386: FileUtils.doCopyFile uses different methods to check the file sizes. Thanks to Sebb, Bernd Eckenfels, zhipengxu, Gary Gregory. * Fix typos #375. Thanks to Michael Ernst. * IO-611: FilenameUtils.normalize javadoc and tests #383. Thanks to Fedor Urvanov. * IO-611: Better docs in IOUtils and IOUtils.byteArray(int size) #374. Thanks to ArdenL-Liu, Bruno P. Kinoshita, Gary Gregory. * IO-782: SequenceReader should close readers when its close method is called #391. Thanks to Matteo Di Giovinazzo, Gary Gregory. * IO-790: Fix symbolic link file filter #450. Thanks to Miguel Muoz, Gary Gregory. * IO-790: Apply nanoseconds precision for QueueInputStream timeout duration. #453. Thanks to maxxedev, Gary Gregory, Bruno P. Kinoshita. * Fix overflow for FileUtilsTest constants #456. Thanks to Marcono1234. * Serialization is deprecated and will be removed in 3.0. Thanks to Gary Gregory. * FileSystemUtils.performCommand(String[], int, Duration): Use Locale.getDefault() instead of ENGLISH. Thanks to Gary Gregory. * IO-726: Add MemoryMappedFileInputStream #215. Thanks to shollander, Gary Gregory. Changes ------- * Bump actions/cache from 2.1.6 to 3.0.10 #307, #337, #393. Thanks to Dependabot, Gary Gregory. * Bump actions/checkout from 2.3.4 to 3.1.0 #286, #298, #330, #392. Thanks to Dependabot, Gary Gregory. * Bump actions/setup-java from 2 to 3.6.0 #346, #397. Thanks to Dependabot. * Bump github/codeql-action from 1 to 2 #353. Thanks to Dependabot. * Bump Maven Javadoc plugin from 3.2.0 to 3.4.1. Thanks to Dependabot, Gary Gregory. * Bump spotbugs-maven-plugin from 4.2.3 to 4.7.3.0 #250, #259, #272, #274, #285, #288, #289, #305, #315, #326, #338, #360, #366, #370, #380, #395, #403. Thanks to Dependabot. * Bump spotbugs from 4.5.2 to 4.7.3 #313, #317, #357, #382, #398. Thanks to Gary Gregory, Dependabot. * Bump JUnit from 5.7.2 to 5.8.2. Thanks to Gary Gregory. * Bump maven-enforcer-plugin from 3.0.0-M3 to 3.3.0 #255, #363, #431, #446. Thanks to Dependabot. * Bump checkstyle from 8.44 to 9.3 #256, #257, #266, #279, #292. #308. Thanks to Dependabot, Gary Gregory. * Bump junit-bom from 5.8.0-M1 to 5.9.1 #260, #271, #275, #309, #386. Thanks to Dependabot. * Bump mockito-inline from 3.11.2 to 4.11.0 #262, #264, #282, #306, #314, #331, #348, #359, #381, #399, #405, #414, #420. Thanks to Dependabot, Gary Gregory. * Bump jmh.version from 1.32 to 1.36 #258, #316, #342, #404. Thanks to Dependabot. * Bump moditect-maven-plugin from 1.0.0.RC1 to 1.0.0.Final #280, #439, #445. Thanks to Dependabot. * Bump junit-pioneer from 1.4.2 to 1.9.1 #304. #335, #362, #402, #406, #409. Thanks to Dependabot, Gary Gregory. * Bump japicmp-maven-plugin from 0.15.3 to 0.16.0. Thanks to Gary Gregory. * Bump commons-parent from 52 to 57 #388, #415, #421, #184. Thanks to Gary Gregory, Dependabot. * Bump jacoco-maven-plugin from 0.8.7 to 0.8.8. Thanks to Gary Gregory. * Bump maven-antrun-plugin from 3.0.0 to 3.1.0 #354. Thanks to Dependabot. * Bump commons.surefire.version 3.0.0-M5 to 3.0.0-M7. Thanks to Gary Gregory. * Bump PMD from 6.44.0 to 6.52.0. Thanks to Gary Gregory. * Bump maven-pmd-plugin from 3.16.0 to 3.19.0. Thanks to Gary Gregory. * Bump apache-rat from 0.13 to 0.14. Thanks to Gary Gregory. * Bump exec-maven-plugin from 3.0.0 to 3.1.0 #369. Thanks to Dependabot. * Bump maven-checkstyle-plugin from 3.1.2 to 3.2.0 #376. Thanks to Dependabot. * Bump apache-rat-plugin from 0.14 to 0.15 #387. Thanks to Dependabot. * Bump default buffer size for CharSequenceInputStream to IOUtils#DEFAULT_BUFFER_SIZE. Thanks to Gary Gregory. * Bump default buffer size for ChunkedOutputStream to IOUtils#DEFAULT_BUFFER_SIZE. Thanks to Gary Gregory. * Bump default buffer size for ChunkedWriter to IOUtils#DEFAULT_BUFFER_SIZE. Thanks to Gary Gregory. * Bump default buffer size for ReaderInputStream to IOUtils#DEFAULT_BUFFER_SIZE. Thanks to Gary Gregory. * Bump default buffer size for WriterOutputStream to IOUtils#DEFAULT_BUFFER_SIZE. Thanks to Gary Gregory. Compatibility with 2.6: Binary compatible: Yes. Source compatible: Yes. Semantic compatible: Yes. Commons IO 2.7 and up requires Java 8 or above. Commons IO 2.6 requires Java 7 or above. Commons IO 2.3 through 2.5 requires Java 6 or above. Commons IO 2.2 requires Java 5 or above. Commons IO 1.4 requires Java 1.3 or above. 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 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.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. Java 8 required. Fixed Bugs ---------- * IO-741: FileUtils.listFiles does not list matching files if File parameter is a symbolic link. Thanks to Zach Sherman. * IO-724: FileUtils#deleteDirectory(File) exception Javadoc inaccurate update #245. Thanks to liran2000. * Minor changes #243. Thanks to Arturo Bernal. * Replace construction of FileInputStream and FileOutputStream objects with Files NIO APIs. #221. Thanks to Arturo Bernal. * Fix IndexOutOfBoundsException in IOExceptionList constructors. Thanks to Gary Gregory. * 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 ------- * Add SymbolicLinkFileFilter. Thanks to Gary Gregory. * Add test to make sure the setter of AndFileFilter works correctly #244. Thanks to trncate. * Add XmlStreamReader(Path). Thanks to Gary Gregory. * Bump mockito-inline from 3.11.0 to 3.11.2 #247. Thanks to Dependabot. * Bump jmh.version from 1.27 to 1.32 #237. Thanks to Dependabot. * 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.7 and up requires Java 8 or above. Commons IO 2.6 requires Java 7 or above. Commons IO 2.3 through 2.5 requires Java 6 or above. Commons IO 2.2 requires Java 5 or above. Commons IO 1.4 requires Java 1.3 or above. 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 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. Java 8 required. New features ------------ * Add and use RegexFileFilter.toString(). Thanks to Gary Gregory. * Add and use RegexFileFilter.RegexFileFilter(Pattern, Function, String>) Thanks to Gary Gregory. * Add and use IOCase.isCaseSensitive(IOCase). Thanks to Gary Gregory. Fixed Bugs ---------- * IO-733: RegexFileFilter uses the path and file name instead of just the file name. Thanks to Jim Sellers, Gary Gregory. * IO-734: The OSGi manifest now contains sun.* import packages #239. Thanks to Eric Norman. * IO-585: Sanitize double slash after prefix #79. Thanks to Adam McClenaghan. Changes ------- * Bump actions/cache from 2.1.5 to 2.1.6 #238. Thanks to Dependabot. * Bump junit-pioneer from 1.4.1 to 1.4.2 #240. Thanks to Dependabot. * Bump checkstyle from 8.42 to 8.43 #241. Thanks to Dependabot. * 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.7 and up requires Java 8 or above. Commons IO 2.6 requires Java 7 or above. Commons IO 2.3 through 2.5 requires Java 6 or above. Commons IO 2.2 requires Java 5 or above. Commons IO 1.4 requires Java 1.3 or above. 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 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. Java 8 required. New features ------------ * Add org.apache.commons.io.input.CircularInputStream. Thanks to Gary Gregory. * Add org.apache.commons.io.file.PathUtils.cleanDirectory(Path, FileVisitOption...). Thanks to Gary Gregory. * Add org.apache.commons.io.file.PathUtils.deleteDirectory(Path, FileVisitOption...). Thanks to Gary Gregory. * Add NullAppendable. Thanks to Gary Gregory. * Add PathUtils.getAclEntryList(Path). Thanks to Gary Gregory. * Null-guard IOUtils.close(Closeable, IOConsumer). Thanks to Gary Gregory. * Add ReversedLinesFileReader.readLines(int). Thanks to Gary Gregory. * Add ReversedLinesFileReader.toString(int). Thanks to Gary Gregory. * 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. * Add RandomAccessFileInputStream. Thanks to Gary Gregory. * IO-681: IOUtils.close(Closeable) should allow a list of closeables. * Add IOUtils.consume(InputStream). Thanks to Gary Gregory. * IO-676: Add isFileNewer() and isFileOlder() methods that support the Java 8 Date/Time API. #124. Thanks to Isira Seneviratne, Gary Gregory. * Add a MarkShieldInputStream #119. Thanks to Adam Retter, Gary Gregory. * Deprecate IOUtils.LINE_SEPARATOR in favor of Java 7's System.lineSeparator(). Thanks to Gary Gregory. Fixed Bugs ---------- * CharSequenceReader.skip should return 0 instead of EOF on stream end #123. Thanks to Rob Spoor, Jochen Wiedmann. * Implement CharSequenceReader.ready() #122. Thanks to Rob Spoor. * IO-669: Fix code smells; fix typos #115. Thanks to XenoAmess, Gary Gregory. * Add caching for required charsets #120. Thanks to Jerome Wolff, Gary Gregory. * IO-673: Make some simplifications #121. Thanks to Jerome Wolff. * IO-674: InfiniteCircularInputStream is not infinite if its input buffer contains -1. Thanks to Gary Gregory. * IO-675: InfiniteCircularInputStream throws a divide-by-zero exception when reading if its input buffer is size 0. Thanks to Gary Gregory. * IO-677: FileSystem.getCurrent() does not return the correct enum. Thanks to Gary Gregory. * IO-679: input.AbstractCharacterFilterReader passes count of chars read #132. Thanks to proneel. * IO-683: CircularBufferInputStream.read() fails to convert byte to unsigned int * Fix SpotBugs issues in org.apache.commons.io.FileUtils. Thanks to Gary Gregory. * IO-672: Copying a File sets last modified date to 01 January 1970. * IO-676: Prevent NullPointerException in ReversedLinesFileReader constructors #117. Thanks to Michael Ernst, Gary Gregory. Changes ------- * Replace FindBugs with SpotBugs. Thanks to Gary Gregory. * maven-checkstyle-plugin 3.1.0 -> 3.1.1. Thanks to Gary Gregory. * Update tests from org.apache.commons:commons-lang3 3.10 to 3.11. Thanks to Gary Gregory. * Update commons-parent from 50 to 51 #129. Thanks to Gary Gregory. * Update actions/checkout from v1 to v2.3.1 #126. Thanks to Gary Gregory. * Update junit-pioneer from 0.6.0 to 0.8.0, #127, #135. Thanks to Gary Gregory. * Update mockito-core from 3.3.3 to 3.5.9 #128, #133, #145, #149, #151. Thanks to Gary Gregory. * Update spotbugs from 4.0.6 to 4.1.1 #134. Thanks to Dependabot. * Update junit-pioneer from 0.8.0 to 0.9.0 #138. Thanks to Dependabot. * Update actions/checkout from v2.3.1 to v2.3.2 #140. Thanks to Dependabot. * 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 and up requires Java 8 or above. Commons IO 2.6 requires Java 7 or above. Commons IO 2.3 through 2.5 requires Java 6 or above. Commons IO 2.2 requires Java 5 or above. Commons IO 1.4 requires Java 1.3 or above. 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 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. Java 8 required. New features ------------ * Adding the CircularBufferInputStream, and the PeekableInputStream. * IO-553: Add org.apache.commons.io.FilenameUtils.isIllegalWindowsFileName(char). * IO-577: Add readers to filter out given characters: CharacterSetFilterReader and CharacterFilterReader. Thanks to Gary Gregory. * IO-594: Add IOUtils copy methods with java.lang.Appendable as the target. Thanks to Gary Gregory. * IO-605: Add class CanExecuteFileFilter. Thanks to Gary Gregory. * IO-578: Support java.nio.Path and non-default file systems for ReversedLinesFileReader (#62). Thanks to Mark Chesney. * IO-608: Add a convenience NullPrintStream. Thanks to Gary Gregory. * IO-612: Add class TeeReader. Thanks to Rob Spoor, Gary Gregory. * IO-613: Add classes ClosedReader and CloseShieldReader. #84. Thanks to Rob Spoor, Gary Gregory. * IO-614: Add classes TaggedWriter, ClosedWriter and BrokenWriter. #86. Thanks to Rob Spoor. * IO-615: Add classes TeeWriter, FilterCollectionWriter, ProxyCollectionWriter, IOExceptionList, IOIndexedException. Thanks to Gary Gregory, Rob Spoor. * IO-616: Add class AppendableWriter. #87. Thanks to Rob Spoor. * IO-617: Add class CloseShieldWriter. #83. Thanks to Rob Spoor, Gary Gregory. * IO-618: Add classes Added TaggedReader, ClosedReader and BrokenReader. #85. Thanks to Rob Spoor. * IO-619: Support sub sequences in CharSequenceReader. #91. Thanks to Rob Spoor. * IO-631: Add a CountingFileVisitor (as the basis for a forthcoming DeletingFileVisitor). Thanks to Gary Gregory. * IO-632: Add PathUtils for operations on NIO Path. Thanks to Gary Gregory. * IO-633: Add DeletingFileVisitor. Thanks to Gary Gregory. * IO-635: Add org.apache.commons.io.IOUtils.close(Closeable). Thanks to Gary Gregory. * 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. * IO-645: Add org.apache.commons.io.file.PathUtils.fileContentEquals(Path, Path, OpenOption...). Thanks to Gary Gregory. * IO-458: Add a SequenceReader similar to java.io.SequenceInputStream. Thanks to Gary Gregory, Joshua Gitlin. * IO-648: Implement directory content equality. 100#. Thanks to Gary Gregory. * IO-648: Refactor ByteArrayOutputStream into synchronized and unsynchronized versions #108. Thanks to Adam Retter, Alex Herbert, Gary Gregory. * IO-662: Refactor ByteArrayOutputStream into synchronized and unsynchronized versions #108. Thanks to Adam Retter, Gary Gregory. Fixed Bugs ---------- * IO-589: Some tests fail if the base path contains a space. * IO-582: Make methods in ObservableInputStream.Observer public. Thanks to Bruno Palos. * IO-535: Thread bug in FileAlterationMonitor.stop(int). Thanks to Svetlin Zarev, Anthony Raymond. * IO-557: Perform locale independent upper case conversions. Thanks to luccioman. * IO-570: Missing Javadoc in FilenameUtils causing Travis-CI build to fail. Thanks to Pranet Verma. * IO-571: Remove redundant isDirectory() check in org.apache.commons.io.FileUtils.listFilesAndDirs(File, IOFileFilter, IOFileFilter). Thanks to pranet. * IO-559: FilenameUtils.normalize now verifies hostname syntax in UNC path. * IO-554: FileUtils.copyToFile(InputStream source, File destination) should not close input stream. Thanks to Michele Mariotti. * IO-604: FileUtils.doCopyFile(File, File, boolean) can throw ClosedByInterruptException. Thanks to Gary Gregory. * IO-625: Corrected misleading exception message for FileUtils.copyDirectoryToDirectory. Thanks to Mikko Maunu. * IO-626: A mistake in the FilenameUtils.concat()'s Javadoc about an absolute path. Thanks to Yuji Konishi. * IO-640: NPE in org.apache.commons.io.IOUtils.contentEquals(InputStream, InputStream) when only one input is null. Thanks to Gary Gregory. * IO-641: NPE in org.apache.commons.io.IOUtils.contentEquals(Reader, Reader) when only one input is null. Thanks to Gary Gregory. * IO-643: NPE in org.apache.commons.io.IOUtils.contentEqualsIgnoreEOL(Reader, Reader) when only one input is null. Thanks to Gary Gregory. * IO-644: NPE in org.apache.commons.io.FileUtils.contentEqualsIgnoreEOL(File, File) when only one input is null. Thanks to Gary Gregory. * IO-664: org.apache.commons.io.FileUtils.copyURLToFile(*) open but do not close streams. Thanks to Gary Gregory. Changes ------- * IO-572: Refactor duplicate code in org.apache.commons.io.FileUtils. Thanks to Pranet Verma. * IO-580: Update org.apache.commons.io.FilenameUtils.isExtension(String, String[]) to use var args. * IO-701: Make array declaration in ThresholdingOutputStream consistent with other array declarations in the library #77. Thanks to Raymond Tan. * IO-607: Update from Java 7 to Java 8. Thanks to Gary Gregory. * IO-610: Remove throws IOException in method isSymlink() #80. Thanks to Sebastian. * IO-628: Migration to JUnit Jupiter #97. Thanks to Allon Mureinik. * 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. * 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. * IO-634: Make getCause synchronized and use a Deque instead of a Stack #64. Thanks to Vclav Haisman, Bruno P. Kinoshita, Gary Gregory. * Update tests from Apache Commons Lang 3.9 to 3.10. Thanks to Gary Gregory. * Update tests org.junit-pioneer:junit-pioneer 0.3.0 -> 0.6.0. Thanks to Gary Gregory. * Update tests org.junit.jupiter:junit-jupiter 5.5.2 -> 5.6.2. Thanks to Gary Gregory. * Update tests org.mockito:mockito-core 3.0.0 -> 3.3.3. Thanks to Gary Gregory. * IO-666: Normalize internal buffers to 8192 bytes. Thanks to Gary Gregory. * IO-665: Ensure that passing a null InputStream results in NPE with tests #112. Thanks to Otto Fowler, Gary Gregory. * commons.jacoco.version 0.8.4 -> 0.8.5. Thanks to Gary Gregory. * com.github.siom79.japicmp:japicmp-maven-plugin 0.14.1 -> 0.14.3. Thanks to Gary Gregory. * IO-667: Add functional interfaces IOFunction and IOSupplier #110. Thanks to Adam Retter, Gary Gregory. * Support sub sequences in CharSequenceReader #91. Thanks to Rob Spoor, Gary Gregory. * 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 and up requires Java 8 or above. Commons IO 2.6 requires Java 7 or above. Commons IO 2.3 through 2.5 requires Java 6 or above. Commons IO 2.2 requires Java 5 or above. Commons IO 1.4 requires Java 1.3 or above. 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 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 ============ * IO-551: Add Automatic-Module-Name MANIFEST entry for Java 9 compatibility. * IO-367: Add convenience methods for copyToDirectory. Thanks to James Sawle. * IO-493: Add infinite circular input stream. Thanks to Piotr Turski. * IO-507: Add a ByteOrderUtils class. * IO-518: Add ObservableInputStream. * IO-519: Add MessageDigestCalculatingInputStream. * IO-513: Add convenience methods for reading class path resources. Thanks to Behrang Saeedzadeh. FIXED BUGS ========== * IO-546: ClosedOutputStream#flush should throw. Thanks to Tomas Celaya. * IO-550: Documentation issue, fix 404 Javadoc issues in the description page. Thanks to Jimi Adrian. * IO-442: Javadoc contradictory for FileFilterUtils.ageFileFilter(cutoff) and the filter it constructs: AgeFileFilter(cutoff). Thanks to Simon Robinson. * IO-534: FileUtilTestCase.testForceDeleteDir() should not delete testDirectory parent. * IO-528: Fix Tailer.run race condition runaway logging. Thanks to Dave Moten. * IO-483: getPrefixLength return -1 if Unix file contains colon. Thanks to Marko Vasic. * IO-520: FileUtilsTestCase#testContentEqualsIgnoreEOL fails on Windows. * IO-516: .gitattributes not correctly applied. Thanks to Jason Pyeron. * IO-515: Allow Specifying Initial Buffer Size of DeferredFileOutputStream. Thanks to Brett Lounsbury, Gary Gregory. * IO-512: ThresholdingOutputStream.thresholdReached() results in FileNotFoundException. Thanks to Ralf Hauser. * IO-511: After a few unit tests, a few newly created directories not cleaned completely. Thanks to Ahmet Celik. * IO-502: Exceptions are suppressed incorrectly when copying files. Thanks to Christian Schulte. * IO-503: Update platform requirement to Java 7. * IO-537: BOMInputStream shouldn't sort array of BOMs in-place. Thanks to Borys Zibrov. CHANGES ======= * IO-553: Make code style of hasBOM() consistent with getBOMCharsetName(). Thanks to Michael Ernst. * IO-542: FileUtils#readFileToByteArray: optimize reading of files with known size. Thanks to Ilmars Poikans. * IO-547: Throw a IllegalArgumentException instead of NullPointerException in FileSystemUtils.freeSpaceWindows(). Thanks to Nikhil Shinde, Michael Ernst, Gary Greory. * IO-506: Deprecate methods FileSystemUtils.freeSpaceKb(). Thanks to Christian Schulte. * IO-505: Make LineIterator implement Closeable to support try-with-resources statements. Thanks to Christian Schulte. * IO-504: Deprecated of all IOUtils.closeQuietly() methods and use try-with-resources internally. Thanks to Christian Schulte. REMOVED ======= * 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.7 and up requires Java 8 or above. Commons IO 2.6 requires Java 7 or above. Commons IO 2.3 through 2.5 requires Java 6 or above. Commons IO 2.2 requires Java 5 or above. Commons IO 1.4 requires Java 1.3 or above. ------------------------------------------------------------------------------ Apache Commons IO Version 2.5 New features and bug fixes. New features ------------ * IO-487: Add ValidatingObjectInputStream for controlled deserialization * IO-471: Support for additional encodings in ReversedLinesFileReader Thanks to Leandro Reis. * IO-425: Setter method for threshold on ThresholdingOutputStream Thanks to Craig Swank. * IO-406: Introduce new class AppendableOutputStream Thanks to Niall Pemberton. * IO-459: Add WindowsLineEndingInputStream and UnixLineEndingInputStream. Thanks to Kristian Rosenvold. * 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. * IO-426: Add API IOUtils.closeQuietly(Closeable...) * IO-410: Readfully() That Returns A Byte Array Thanks to Beluga Behr. * IO-395: Overload IOUtils buffer methods to accept buffer size Thanks to Beluga Behr. * IO-382: Chunked IO for large arrays. Added writeChunked(byte[], OutputStream) and writeChunked(char[] Writer) Added ChunkedOutputStream, ChunkedWriter * IO-233: Add Methods for Buffering Streams/Writers To IOUtils Added overloaded buffer() methods - see also IO-330 * IO-330: IOUtils#toBufferedOutputStream/toBufferedWriter to conditionally wrap the output Added overloaded buffer() methods - see also IO-233 * IO-381: Add FileUtils.copyInputStreamToFile API with option to leave the source open. See copyInputStreamToFile(final InputStream source, final File destination, boolean closeSource) * IO-379: CharSequenceInputStream - add tests for available() Fix code so it really does reflect a minimum available. * IO-346: Add ByteArrayOutputStream.toInputStream() * IO-341: A constant for holding the BOM character (U+FEFF) * IO-361: Add API FileUtils.forceMkdirsParent(). * IO-360: Add API Charsets.requiredCharsets(). * IO-359: Add IOUtils.skip and skipFully(ReadableByteChannel, long). Thanks to yukoba. * IO-358: Add IOUtils.read and readFully(ReadableByteChannel, ByteBuffer buffer). Thanks to yukoba. * IO-353: Add API IOUtils.copy(InputStream, OutputStream, int) Thanks to ggregory. * IO-349: Add API with array offset and length argument to FileUtils.writeByteArrayToFile. Thanks to scop. * IO-348: Missing information in IllegalArgumentException thrown by org.apache.commons.io.FileUtils#validateListFilesParameters. Thanks to plcstpierre. * IO-345: Supply a hook method allowing Tailer actively determining stop condition. Thanks to mkresse. * IO-437: Make IOUtils.EOF public and reuse it in various classes. Fixed Bugs ---------- * IO-446: adds an endOfFileReached method to the TailerListener Thanks to Jeffrey Barrus. * IO-484: FilenameUtils should handle embedded null bytes Thanks to Philippe Arteau. * IO-481: Changed/Corrected algorithm for waitFor * IO-428: BOMInputStream.skip returns wrong count if stream contains no BOM Thanks to Stefan Gmeiner. * IO-488: FileUtils.waitFor(...) swallows thread interrupted status Thanks to Bjrn Buchner. * IO-452: Support for symlinks with missing target. Added support for JDK7 symlink features when present Thanks to David Standish. * IO-453: Regression in FileUtils.readFileToString from 2.0.1 Thanks to Steven Christou. * IO-451: ant test fails - resources missing from test classpath Thanks to David Standish. * 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. * IO-424: Javadoc fixes, mostly to appease 1.8.0 Thanks to Ville Skytt. * IO-389: FileUtils.sizeOfDirectory can throw IllegalArgumentException Thanks to Austin Doupnik. * IO-390: FileUtils.sizeOfDirectoryAsBigInteger can overflow. Ensure that recursive calls all use BigInteger * IO-385: FileUtils.doCopyFile can potentially loop for ever Exit loop if no data to copy * IO-383: FileUtils.doCopyFile caches the file size; needs to be documented Added Javadoc; show file lengths in exception message * IO-380: FileUtils.copyInputStreamToFile should document it closes the input source Thanks to claudio_ch. * IO-279: Tailer erroneously considers file as new. Fix to use file.lastModified() rather than System.currentTimeMillis() * 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 * IO-368: ClassLoaderObjectInputStream does not handle primitive typed members * IO-314: Deprecate all methods that use the default encoding * IO-338: When a file is rotated, finish reading previous file prior to starting new one * IO-354: Commons IO Tailer does not respect UTF-8 Charset. * IO-323: What should happen in FileUtils.sizeOf[Directory] when an overflow takes place? Added Javadoc. * IO-372: FileUtils.moveDirectory can produce misleading error message on failure * IO-362: IOUtils.contentEquals* methods returns false if input1 == input2, should return true. Thanks to mmadson, ggregory. * IO-357: [Tailer] InterruptedException while the thread is sleeping is silently ignored Thanks to mortenh. * IO-352: Spelling fixes. Thanks to scop. * IO-436: Improper Javadoc comment for FilenameUtils.indexOfExtension. Thanks to christoph.schneegans. Changes ------- * IO-433: Converted all testcases to JUnit 4 * IO-466: Added testcase to show this was fixed with IO-423 * IO-479: Correct exception message in FileUtils.getFile(File, String...) Thanks to Zhouce Chen. * IO-465: Update to JUnit 4.12 Thanks to based2. * IO-462: IOExceptionWithCause no longer needed * IO-422: Deprecate Charsets Charset constants in favor of Java 7's java.nio.charset.StandardCharsets * IO-239: Convert IOCase to a Java 1.5+ Enumeration [N.B. this is binary compatible] * IO-328: getPrefixLength returns null if filename has leading slashes Javadoc: add examples to show correct behavior; add unit tests * 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 * IO-375: FilenameUtils.splitOnTokens(String text) check for '**' could be simplified * 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.7 and up requires Java 8 or above. Commons IO 2.6 requires Java 7 or above. Commons IO 2.3 through 2.5 requires Java 6 or above. Commons IO 2.2 requires Java 5 or above. Commons IO 1.4 requires Java 1.3 or above. ------------------------------------------------------------------------------ Apache Commons IO Version 2.4 New features ------------ * IO-269: Tailer locks file from deletion/rename on Windows. Thanks to sebb. * IO-333: Export OSGi packages at version 1.x in addition to 2.x. Thanks to fmeschbe. * IO-320: Add XmlStreamReader support for UTF-32. Thanks to ggregory. * IO-331: BOMInputStream wrongly detects UTF-32LE_BOM files as UTF-16LE_BOM files in method getBOM(). Thanks to ggregory. * IO-327: Add byteCountToDisplaySize(BigInteger). Thanks to ggregory. * IO-326: Add new FileUtils.sizeOf[Directory] APIs to return BigInteger. Thanks to ggregory. * IO-325: Add IOUtils.toByteArray methods to work with URL and URI. Thanks to raviprak. * IO-324: Add missing Charset sister APIs to method that take a String charset name. Thanks to raviprak. Fixed Bugs ---------- * IO-336: Yottabyte (YB) incorrectly defined in FileUtils. Thanks to rleavelle. * IO-279: Tailer erroneously considers file as new. Thanks to Sergio Bossa, Chris Baron. * IO-335: Tailer#readLines - incorrect CR handling. * IO-334: FileUtils.toURLs throws NPE for null parameter; document the behavior. * IO-332: Improve tailer's reading performance. Thanks to liangly. * IO-279: Improve Tailer performance with buffered reads (see IO-332). * IO-329: FileUtils.writeLines uses unbuffered IO. Thanks to tivv. * 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.7 and up requires Java 8 or above. Commons IO 2.6 requires Java 7 or above. Commons IO 2.3 through 2.5 requires Java 6 or above. Commons IO 2.2 requires Java 5 or above. Commons IO 1.4 requires Java 1.3 or above. ------------------------------------------------------------------------------ Apache Commons IO Version 2.3 New features ------------ * IO-322: Add and use class Charsets. Thanks to ggregory. * IO-321: ByteOrderMark UTF_32LE is incorrect. Thanks to ggregory. * 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.7 and up requires Java 8 or above. Commons IO 2.6 requires Java 7 or above. Commons IO 2.3 through 2.5 requires Java 6 or above. Commons IO 2.2 requires Java 5 or above. Commons IO 1.4 requires Java 1.3 or above. ------------------------------------------------------------------------------ Apache Commons IO Version 2.2 New features ------------ * Add IOUtils.toBufferedReader(Reader) Issue: IO-313. Thanks to ggregory. * Allow applications to provide buffer (or size) for copyLarge methods. Issue: IO-308. Thanks to Manoj Mokashi. * New copyLarge() method in IOUtils that takes additional offset, length arguments Issue: IO-305. Thanks to Manoj Mokashi. * Use terabyte (TB), petabyte (PB) and exabyte (EB) in FileUtils.byteCountToDisplaySize(long size) Issue: IO-287. Thanks to Ron Kuris, Gary Gregory. * FileUtils.listFiles() doesn't return directories Issue: IO-173. Thanks to Marcos Vincius da Silva. * CharSequenceInputStream to efficiently stream content of a CharSequence Issue: IO-297. Thanks to Oleg Kalnichevski. * The second constructor of Tailer class does not pass 'delay' to the third one Issue: IO-304. Thanks to liangly. * TeeOutputStream does not call branch.close() when main.close() throws an exception Issue: IO-303. Thanks to fabian.barney. * ArrayIndexOutOfBoundsException in BOMInputStream when reading a file without BOM multiple times Issue: IO-302. Thanks to jsteuerwald, detinho. * Add IOUtils.closeQuietly(Selector) necessary Issue: IO-301. Thanks to kaykay.unique. * IOUtils.closeQuietly() should take a ServerSocket as a parameter Issue: IO-292. Thanks to sebb. * Add read/readFully methods to IOUtils Issue: IO-290. Thanks to sebb. * Supply a ReversedLinesFileReader Issue: IO-288. Thanks to Georg Henzler. * Add new function FileUtils.directoryContains. Issue: IO-291. Thanks to ggregory. * 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 ---------- * IOUtils.read(InputStream/Reader) ignores the offset parameter Issue: IO-311. Thanks to Robert Muir. * CharSequenceInputStream(CharSequence s, Charset charset, int bufferSize) ignores bufferSize Issue: IO-312. * FileUtils.moveDirectoryToDirectory removes source directory if destination is a subdirectory Issue: IO-300. * ReaderInputStream#read(byte[] b, int off, int len) should check for valid parameters Issue: IO-307. * ReaderInputStream#read(byte[] b, int off, int len) should always return 0 for length == 0 Issue: IO-306. * "FileUtils#deleteDirectoryOnExit(File)" does not work Issue: IO-276. Thanks to nkami. * BoundedInputStream.read() treats max differently from BoundedInputStream.read(byte[]...) Issue: IO-273. Thanks to sebb. * Various methods of class 'org.apache.commons.io.FileUtils' incorrectly suppress 'java.io.IOException' Issue: IO-298. Thanks to Christian Schulte. Changes ------- * 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.7 and up requires Java 8 or above. Commons IO 2.6 requires Java 7 or above. Commons IO 2.3 through 2.5 requires Java 6 or above. Commons IO 2.2 requires Java 5 or above. Commons IO 1.4 requires Java 1.3 or above. ------------------------------------------------------------------------------ Apache Commons IO Version 2.1 New features ------------ * Use standard Maven directory layout Issue: IO-285. Thanks to ggregory. * Add IOUtils API toString for URL and URI to get contents Issue: IO-284. Thanks to ggregory. * Add API FileUtils.copyFile(File input, OutputStream output) Issue: IO-282. Thanks to ggregory. * FileAlterationObserver has no getter for FileFilter Issue: IO-262. * Add FileUtils.getFile API with varargs parameter Issue: IO-261. * Add new APPEND parameter for writing string into files Issue: IO-182. * Add new read method "toByteArray" to handle InputStream with known size. Issue: IO-251. Thanks to Marco Albini. Fixed Bugs ---------- * Dubious use of mkdirs() return code Issue: IO-280. Thanks to sebb. * ReaderInputStream enters infinite loop when it encounters an unmappable character Issue: IO-277. * FileUtils.moveFile() Javadoc should specify FileExistsException thrown Issue: IO-264. * ClassLoaderObjectInputStream does not handle Proxy classes Issue: IO-260. * Tailer returning partial lines when reaching EOF before EOL Issue: IO-274. Thanks to Frank Grimes. * FileUtils.copyFile() throws IOException when copying large files to a shared directory (on Windows) Issue: IO-266. Thanks to Igor Smereka. * 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 ------- * 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 Java 5 or above (Commons IO 1.4 requires Java 1.3 or above) 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 Java 5 or abobe (Commons IO 1.4 requires Java 1.3 or above) 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 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 subdirectories * [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-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) - ThresholdingOutputStream [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 facility to specify case sensitivity on prefix matching - SuffixFileFilter [IO-126] - Add facility 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 inaccurate 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 callback 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 necessary 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 character 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 necessary - 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.16.1-src/SECURITY.md0100644 0000000 0000000 00000001604 14603604450 016601 0ustar00rootroot0000000 0000000 The Apache Commons security page is [https://commons.apache.org/security.html](https://commons.apache.org/security.html). commons-io-2.16.1-src/pom.xml0100644 0000000 0000000 00000046247 14603604450 016341 0ustar00rootroot0000000 0000000 org.apache.commons commons-parent 69 4.0.0 commons-io commons-io 2.16.1 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.15.1 org.junit.jupiter junit-jupiter test org.junit-pioneer junit-pioneer 1.9.1 test net.bytebuddy byte-buddy ${commons.bytebuddy.version} test net.bytebuddy byte-buddy-agent ${commons.bytebuddy.version} test org.mockito mockito-inline 4.11.0 test com.google.jimfs jimfs 1.3.0 test org.apache.commons commons-lang3 3.14.0 test commons-codec commons-codec 1.16.1 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 RC2 2.16.0 2.16.1 2.16.2 2024-04-04T20:10:16Z (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 ${commons.javadoc8.java.link} 1.37 1.14.13 false ${env.JACOCO_SKIP} true clean verify apache-rat:check japicmp:cmp checkstyle:check spotbugs:check pmd:check javadoc:javadoc org.apache.rat apache-rat-plugin src/test/resources/**/*.bin src/test/resources/dir-equals-tests/** test/** org.apache.maven.plugins maven-checkstyle-plugin ${basedir}/src/conf/checkstyle.xml ${basedir}/src/conf/checkstyle-suppressions.xml false true 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 ${basedir}/src/conf/spotbugs-exclude-filter.xml com.github.siom79.japicmp japicmp-maven-plugin org.apache.maven.plugins maven-pmd-plugin src/conf/maven-pmd-plugin.xml org.apache.maven.plugins maven-checkstyle-plugin com.github.spotbugs spotbugs-maven-plugin ${basedir}/src/conf/spotbugs-exclude-filter.xml com.github.siom79.japicmp japicmp-maven-plugin org.apache.commons.io.StreamIterator setup-checkout site-content org.apache.maven.plugins maven-antrun-plugin 3.1.0 prepare-checkout pre-site run java9-compile [9,) 8 benchmark true org.apache org.codehaus.mojo exec-maven-plugin 3.2.0 benchmark test exec test java -classpath org.openjdk.jmh.Main -rf json -rff target/jmh-result.${benchmark}.json ${benchmark} 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 Martin Grigorov mgrigorov@apache.org Arturo Bernal Miguel Muñoz commons-io-2.16.1-src/src/0040755 0000000 0000000 00000000000 14603604450 015601 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/assembly/0040755 0000000 0000000 00000000000 14603604450 017420 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/changes/0040755 0000000 0000000 00000000000 14603604450 017211 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/conf/0040755 0000000 0000000 00000000000 14603604450 016526 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/main/0040755 0000000 0000000 00000000000 14603604450 016525 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/main/java/0040755 0000000 0000000 00000000000 14603604450 017446 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/main/java/org/0040755 0000000 0000000 00000000000 14603604450 020235 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/main/java/org/apache/0040755 0000000 0000000 00000000000 14603604450 021456 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/main/java/org/apache/commons/0040755 0000000 0000000 00000000000 14603604450 023131 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/main/java/org/apache/commons/io/0040755 0000000 0000000 00000000000 14603604450 023540 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/main/java/org/apache/commons/io/build/0040755 0000000 0000000 00000000000 14603604450 024637 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/main/java/org/apache/commons/io/channels/0040755 0000000 0000000 00000000000 14603604450 025333 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/main/java/org/apache/commons/io/charset/0040755 0000000 0000000 00000000000 14603604450 025171 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/main/java/org/apache/commons/io/comparator/0040755 0000000 0000000 00000000000 14603604450 025707 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/main/java/org/apache/commons/io/file/0040755 0000000 0000000 00000000000 14603604450 024457 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/main/java/org/apache/commons/io/file/attribute/0040755 0000000 0000000 00000000000 14603604450 026462 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/main/java/org/apache/commons/io/file/spi/0040755 0000000 0000000 00000000000 14603604450 025252 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/main/java/org/apache/commons/io/filefilter/0040755 0000000 0000000 00000000000 14603604450 025665 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/main/java/org/apache/commons/io/function/0040755 0000000 0000000 00000000000 14603604450 025365 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/0040755 0000000 0000000 00000000000 14603604450 024677 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/buffer/0040755 0000000 0000000 00000000000 14603604450 026150 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/main/java/org/apache/commons/io/monitor/0040755 0000000 0000000 00000000000 14603604450 025227 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/main/java/org/apache/commons/io/output/0040755 0000000 0000000 00000000000 14603604450 025100 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/main/java/org/apache/commons/io/serialization/0040755 0000000 0000000 00000000000 14603604450 026415 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/media/0040755 0000000 0000000 00000000000 14603604450 016660 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/site/0040755 0000000 0000000 00000000000 14603604450 016545 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/site/resources/0040755 0000000 0000000 00000000000 14603604450 020557 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/site/resources/images/0040755 0000000 0000000 00000000000 14603604450 022024 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/site/xdoc/0040755 0000000 0000000 00000000000 14603604450 017502 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/test/0040755 0000000 0000000 00000000000 14603604450 016560 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/test/java/0040755 0000000 0000000 00000000000 14603604450 017501 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/test/java/org/0040755 0000000 0000000 00000000000 14603604450 020270 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/0040755 0000000 0000000 00000000000 14603604450 021511 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/0040755 0000000 0000000 00000000000 14603604450 023164 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/0040755 0000000 0000000 00000000000 14603604450 023573 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/build/0040755 0000000 0000000 00000000000 14603604450 024672 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/channels/0040755 0000000 0000000 00000000000 14603604450 025366 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/charset/0040755 0000000 0000000 00000000000 14603604450 025224 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/comparator/0040755 0000000 0000000 00000000000 14603604450 025742 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/file/0040755 0000000 0000000 00000000000 14603604450 024512 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/file/attribute/0040755 0000000 0000000 00000000000 14603604450 026515 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/file/spi/0040755 0000000 0000000 00000000000 14603604450 025305 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/filefilter/0040755 0000000 0000000 00000000000 14603604450 025720 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/function/0040755 0000000 0000000 00000000000 14603604450 025420 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/0040755 0000000 0000000 00000000000 14603604450 024732 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/buffer/0040755 0000000 0000000 00000000000 14603604450 026203 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/compatibility/0040755 0000000 0000000 00000000000 14603604450 027603 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/jmh/0040755 0000000 0000000 00000000000 14603604450 024351 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/monitor/0040755 0000000 0000000 00000000000 14603604450 025262 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/output/0040755 0000000 0000000 00000000000 14603604450 025133 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/serialization/0040755 0000000 0000000 00000000000 14603604450 026450 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/test/0040755 0000000 0000000 00000000000 14603604450 024552 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/test/resources/0040755 0000000 0000000 00000000000 14603604450 020572 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/test/resources/dir-equals-tests/0040755 0000000 0000000 00000000000 14603604450 024000 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/0040755 0000000 0000000 00000000000 14603604450 030645 5ustar00rootroot0000000 0000000 ././@LongLink0100644 0000000 0000000 00000000145 14603604450 011635 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files1/commons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files1/0040755 0000000 0000000 00000000000 14603604450 033527 5ustar00rootroot0000000 0000000 ././@LongLink0100644 0000000 0000000 00000000173 14603604450 011636 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files1/directory-files-only1/commons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files1/0040755 0000000 0000000 00000000000 14603604450 033527 5ustar00rootroot0000000 0000000 ././@LongLink0100644 0000000 0000000 00000000145 14603604450 011635 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files2/commons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files2/0040755 0000000 0000000 00000000000 14603604450 033530 5ustar00rootroot0000000 0000000 ././@LongLink0100644 0000000 0000000 00000000173 14603604450 011636 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files2/directory-files-only2/commons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files2/0040755 0000000 0000000 00000000000 14603604450 033530 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/0040755 0000000 0000000 00000000000 14603604450 031041 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/dir1/0040755 0000000 0000000 00000000000 14603604450 031700 5ustar00rootroot0000000 0000000 ././@LongLink0100644 0000000 0000000 00000000161 14603604450 011633 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/dir1/directory-files-only1/commons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/dir1/directory-0040755 0000000 0000000 00000000000 14603604450 033702 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/dir2/0040755 0000000 0000000 00000000000 14603604450 031701 5ustar00rootroot0000000 0000000 ././@LongLink0100644 0000000 0000000 00000000161 14603604450 011633 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/dir2/directory-files-only1/commons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/dir2/directory-0040755 0000000 0000000 00000000000 14603604450 033703 5ustar00rootroot0000000 0000000 ././@LongLink0100644 0000000 0000000 00000000154 14603604450 011635 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/directory-files-only1/commons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/directory-files0040755 0000000 0000000 00000000000 14603604450 034066 5ustar00rootroot0000000 0000000 ././@LongLink0100644 0000000 0000000 00000000154 14603604450 011635 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/directory-files-only2/commons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/directory-files0040755 0000000 0000000 00000000000 14603604450 034066 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-files-only/0040755 0000000 0000000 00000000000 14603604450 030125 5ustar00rootroot0000000 0000000 ././@LongLink0100644 0000000 0000000 00000000147 14603604450 011637 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-files-only/directory-files-only1/commons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-files-only/directory-files-only0040755 0000000 0000000 00000000000 14603604450 034131 5ustar00rootroot0000000 0000000 ././@LongLink0100644 0000000 0000000 00000000147 14603604450 011637 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-files-only/directory-files-only2/commons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-files-only/directory-files-only0040755 0000000 0000000 00000000000 14603604450 034131 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/test/resources/org/0040755 0000000 0000000 00000000000 14603604450 021361 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/test/resources/org/apache/0040755 0000000 0000000 00000000000 14603604450 022602 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/test/resources/org/apache/commons/0040755 0000000 0000000 00000000000 14603604450 024255 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/test/resources/org/apache/commons/io/0040755 0000000 0000000 00000000000 14603604450 024664 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/test/resources/org/apache/commons/io/dirs-1-file-size-0/0040755 0000000 0000000 00000000000 14603604450 030005 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/test/resources/org/apache/commons/io/dirs-1-file-size-1/0040755 0000000 0000000 00000000000 14603604450 030006 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/test/resources/org/apache/commons/io/dirs-2-file-size-2/0040755 0000000 0000000 00000000000 14603604450 030010 5ustar00rootroot0000000 0000000 ././@LongLink0100644 0000000 0000000 00000000146 14603604450 011636 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/resources/org/apache/commons/io/dirs-2-file-size-2/dirs-a-file-size-1/commons-io-2.16.1-src/src/test/resources/org/apache/commons/io/dirs-2-file-size-2/dirs-a-file-size-10040755 0000000 0000000 00000000000 14603604450 033133 5ustar00rootroot0000000 0000000 ././@LongLink0100644 0000000 0000000 00000000146 14603604450 011636 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/resources/org/apache/commons/io/dirs-2-file-size-2/dirs-b-file-size-1/commons-io-2.16.1-src/src/test/resources/org/apache/commons/io/dirs-2-file-size-2/dirs-b-file-size-10040755 0000000 0000000 00000000000 14603604450 033134 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/test/resources/org/apache/commons/io/dirs-2-file-size-4/0040755 0000000 0000000 00000000000 14603604450 030012 5ustar00rootroot0000000 0000000 ././@LongLink0100644 0000000 0000000 00000000146 14603604450 011636 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/resources/org/apache/commons/io/dirs-2-file-size-4/dirs-a-file-size-1/commons-io-2.16.1-src/src/test/resources/org/apache/commons/io/dirs-2-file-size-4/dirs-a-file-size-10040755 0000000 0000000 00000000000 14603604450 033135 5ustar00rootroot0000000 0000000 ././@LongLink0100644 0000000 0000000 00000000146 14603604450 011636 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/resources/org/apache/commons/io/dirs-2-file-size-4/dirs-b-file-size-1/commons-io-2.16.1-src/src/test/resources/org/apache/commons/io/dirs-2-file-size-4/dirs-b-file-size-10040755 0000000 0000000 00000000000 14603604450 033136 5ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/assembly/bin.xml0100644 0000000 0000000 00000003734 14603604450 020716 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.16.1-src/src/assembly/src.xml0100644 0000000 0000000 00000003540 14603604450 020730 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.16.1-src/src/changes/changes.xml0100644 0000000 0000000 00000366340 14603604450 021354 0ustar00rootroot0000000 0000000 Apache Commons IO Release Notes Reimplement FileSystemUtils using NIO. FileSystemUtils no longer throws IllegalStateException. Avoid possible NullPointerException in FileUtils.listAccumulate(File, IOFileFilter, IOFileFilter, FileVisitOption...). BoundedInputStream.reset() not updating count. ThresholdingOutputStream: a negative threshold should behave like a zero threshold and trigger the event on the first write #609. Bump commons.bytebuddy.version from 1.14.12 to 1.14.13 #605. Bump org.apache.commons:commons-parent from 67 to 69 #608. Fix and re-enable testSkip_RequiredCharsets #518. SymbolicLineFileFilter documentation fixes. CharSequenceInputStream.reset() only works once #520. Finish TODO on CharSequenceInputStream #540. Add byte array size validation for methods in EndianUtils #521. Add missing test case CircularByteBufferTest. Make CharSequenceInputStream.available() more correct in the face of multibyte encodings #525. Remove unreachable code in AbstractIOFileFilterTest #526. Rationalize and unify checking for existence of files and directories #529. Avoid NullPointerException in IOCase.checkEquals(String, String) on null input. Avoid NullPointerException in CanExecuteFileFilter.accept(File) on null input. Avoid NullPointerException in CanExecuteFileFilter.accept(Path, BasicFileAttributes) on null input. Avoid NullPointerException in CanReadFileFilter.accept(File) on null input. Avoid NullPointerException in CanReadFileFilter.accept(Path, BasicFileAttributes) on null input. Avoid NullPointerException in CanWriteFileFilter.accept(File) on null input. Avoid NullPointerException in CanWriteFileFilter.accept(Path, BasicFileAttributes) on null input. Avoid NullPointerException in DirectoryFileFilter.accept(File) on null input. Avoid NullPointerException in DirectoryFileFilter.accept(Path, BasicFileAttributes) on null input. Avoid NullPointerException in EmptyFileFilter.accept(File) on null input. Avoid NullPointerException in EmptyFileFilter.accept(Path, BasicFileAttributes) on null input. Avoid NullPointerException in FileFileFilter.accept(File) on null input. Avoid NullPointerException in FileFileFilter.accept(Path, BasicFileAttributes) on null input. Avoid NullPointerException in HiddenFileFilter.accept(File) on null input. Avoid NullPointerException in HiddenFileFilter.accept(Path, BasicFileAttributes) on null input. Avoid NullPointerException in IOCase.checkIndexOf(String, int, String) on null input. Avoid NullPointerException in IOCase.checkRegionMatches(String, int, String) on null input. BoundedInputStream.getCount() should not count EOF. Modernize temporary file creation and deletion in DeferredFileOutputStreamTest #535. Add PathMatcher to IOFileFilter class Javadoc #536. Fix CharSequenceInputStream coding exception handling #537. Deprecate int CountingInputStream#getCount() in favor of long CountingInputStream#getByteCount(). Deprecate CountingInputStream.resetCount() in favor of resetByteCount(). Deprecate CountingInputStream.getMaxLength() in favor of getMaxCount()). NullInputStream breaks InputStream's read method contract. Javadoc shouldn't reference 1.x behavior #539. Don't decode and reencode characters in a potentially different charset in AbstractOrigin.CharSequenceOrigin.getReader(Charset). Let subclasses of CountingInputStream.afterRead(int) throw IOException. Characterization test for broken symlinks when copying directories #547. ClosedInputStream.read(byte[], int, int) does not always return -1. ClosedOutputStream.write(byte[], int, int) does not always throw IOException. XmlStreamReader can't parse an XML document with a multi-line prolog #550. XmlStreamReader can't parse XML an document with an external parsed entity prolog. Update FileNameUtils Javadoc #554. Copy symlinks, not the files the symlinks point to #558. Pickup apache-rat-plugin version from parent POM. Add test for copying a symlink FileUtilsTest#testCopyFile_symLink() #564. Make copyFile copy symbolic links by value rather than reference #565. Deprecate CopyUtils 0-argument constructor. Deprecate EndianUtils 0-argument constructor. Deprecate FileSystemUtils 0-argument constructor. Deprecate FilenameUtils 0-argument constructor. Deprecate RandomAccessFiles 0-argument constructor. Clarify and correct EndianUtils and SwappedDataInputStream API doc #566. Add characterization test for copying a symlinked directory #570. RandomAccessFileInputStream.builder().get() now throws ISE instead of NPE. Test links to targets outside the source directory #571. Focus Javadoc on current version rather than past versions #573, #574. "Self-suppression not permitted" while using BrokenOutput and BrokenInput streams with try-with-resources. Handle zero and negative thresholds #587. Deprecate CountingInputStream in favor of BoundedInputStream. PathUtils.setPosixPermissions(...) only sets permissions if needed. PathUtils.setReadOnly(...) only sets permissions if needed. PathUtils.deleteFile(..., DeleteOption...) only sets permissions if needed. CleaningPathVisitor only sets permissions if needed. DeletingPathVisitor only sets permissions if needed. Add and use PathUtils.getFileName(Path, Function<Path, R>). Add and use PathUtils.getFileNameString(). Make public Erase.rethrow(Throwable). Add BrokenInputStream.BrokenInputStream(Throwable). Add BrokenReader.BrokenReader(Throwable). Add BrokenOutputStream.BrokenOutputStream(Throwable). Add BrokenWriter.BrokenWriter(Throwable). Add BoundedInputStream.getRemaining(). Add FileTimes.toNtfsTime(long). Add FileTimes.fromUnixTime(long). Add FileTimes.isUnixTime(FileTime). Add FileTimes.isUnixTime(long). Add FileTimes.toUnixTime(FileTime). Add BrokenInputStream.Builder. Add PathUtils.getExtension(Path). Add PathUtils.getBaseName(Path). Add ThrottledInputStream. Add IORunnable.noop(). Add ChecksumInputStream and test #548. Add AbstractStreamBuilder.getReader(). Add Maven property project.build.outputTimestamp for build reproducibility. Add ProxyInputStream.unwrap(). Add a running count and builder to BoundedInputStream. Bump commons.bytebuddy.version from 1.14.10 to 1.14.12 #534, #592. Bump org.apache.commons:commons-parent from 65 to 67. Bump commons-codec:commons-codec from 1.16.0 to 1.16.1 #583. Bump org.codehaus.mojo:exec-maven-plugin from 3.1.1 to 3.2.0 #593. Fix wrong issue id in change log #503. Add test for FileChannels.contentEquals() #509. Fix FileChannels.contentEquals(). Fix some Javadoc issues in LineIterator and IOUtils. Simplify FileAlterationObserver internal processing. Avoid NullPointerException in RegexFileFilter.RegexFileFilter(Pattern). Avoid NullPointerException in RegexFileFilter.accept(Path, BasicFileAttributes). Fix SpotBugs error: Class org.apache.commons.io.filefilter.RegexFileFilter defines non-transient non-serializable instance field pathToString [org.apache.commons.io.filefilter.RegexFileFilter] In RegexFileFilter.java SE_BAD_FIELD. Fix SpotBugs error: Class org.apache.commons.io.filefilter.DelegateFileFilter defines non-transient non-serializable instance field fileFilter [org.apache.commons.io.filefilter.DelegateFileFilter] In DelegateFileFilter.java SE_BAD_FIELD. Fix SpotBugs error: Class org.apache.commons.io.filefilter.DelegateFileFilter defines non-transient non-serializable instance field fileNameFilter [org.apache.commons.io.filefilter.DelegateFileFilter] In DelegateFileFilter.java SE_BAD_FIELD. Fix SpotBugs error: org.apache.commons.io.function.IOStream$1.next() cannot throw NoSuchElementException [org.apache.commons.io.function.IOStream$1] At IOStream.java:[line 98] IT_NO_SUCH_ELEMENT. Fix SpotBugs error: org.apache.commons.io.monitor.FileAlterationMonitor.getObservers() may expose internal representation by returning FileAlterationMonitor.observers [org.apache.commons.io.monitor.FileAlterationMonitor] At FileAlterationMonitor.java:[line 124] EI_EXPOSE_REP. Fix SpotBugs error: Class org.apache.commons.io.monitor.FileAlterationObserver defines non-transient non-serializable instance field fileFilter [org.apache.commons.io.monitor.FileAlterationObserver] In FileAlterationObserver.java SE_BAD_FIELD. Fix SpotBugs error: Class org.apache.commons.io.monitor.FileAlterationObserver defines non-transient non-serializable instance field listeners [org.apache.commons.io.monitor.FileAlterationObserver] In FileAlterationObserver.java SE_BAD_FIELD. Fix SpotBugs error: org.apache.commons.io.FileCleaningTracker.getDeleteFailures() may expose internal representation by returning FileCleaningTracker.deleteFailures [org.apache.commons.io.FileCleaningTracker] At FileCleaningTracker.java:[line 218] EI_EXPOSE_REP. Fix SpotBugs error: org.apache.commons.io.IOExceptionList.getCauseList() may expose internal representation by returning IOExceptionList.causeList [org.apache.commons.io.IOExceptionList] At IOExceptionList.java:[line 118] EI_EXPOSE_REP. Fix SpotBugs error: org.apache.commons.io.IOExceptionList.getCauseList(Class) may expose internal representation by returning IOExceptionList.causeList [org.apache.commons.io.IOExceptionList] At IOExceptionList.java:[line 129] EI_EXPOSE_REP. Fix SpotBugs error: org.apache.commons.io.file.AccumulatorPathVisitor.getDirList() may expose internal representation by returning AccumulatorPathVisitor.dirList [org.apache.commons.io.file.AccumulatorPathVisitor] At AccumulatorPathVisitor.java:[line 179] EI_EXPOSE_REP. Fix SpotBugs error: org.apache.commons.io.file.AccumulatorPathVisitor.getFileList() may expose internal representation by returning AccumulatorPathVisitor.fileList [org.apache.commons.io.file.AccumulatorPathVisitor] At AccumulatorPathVisitor.java:[line 188] EI_EXPOSE_REP. Fix SpotBugs error: org.apache.commons.io.input.ObservableInputStream.getObservers() may expose internal representation by returning ObservableInputStream.observers [org.apache.commons.io.input.ObservableInputStream] At ObservableInputStream.java:[line 187] EI_EXPOSE_REP. Fix SpotBugs error: Exception thrown in class org.apache.commons.io.input.UnsynchronizedByteArrayInputStream at new org.apache.commons.io.input.UnsynchronizedByteArrayInputStream(byte[], int) will leave the constructor. The object under construction remains partially initialized and may be vulnerable to Finalizer attacks. [org.apache.commons.io.input.UnsynchronizedByteArrayInputStream, org.apache.commons.io.input.UnsynchronizedByteArrayInputStream] At UnsynchronizedByteArrayInputStream.java:[line 202]At UnsynchronizedByteArrayInputStream.java:[line 202] CT_CONSTRUCTOR_THROW. Fix SpotBugs error: Exception thrown in class org.apache.commons.io.input.UnsynchronizedByteArrayInputStream at new org.apache.commons.io.input.UnsynchronizedByteArrayInputStream(byte[], int, int) will leave the constructor. The object under construction remains partially initialized and may be vulnerable to Finalizer attacks. [org.apache.commons.io.input.UnsynchronizedByteArrayInputStream, org.apache.commons.io.input.UnsynchronizedByteArrayInputStream] At UnsynchronizedByteArrayInputStream.java:[line 223]At UnsynchronizedByteArrayInputStream.java:[line 223] CT_CONSTRUCTOR_THROW. Bump org.codehaus.mojo:exec-maven-plugin from 3.1.0 to 3.1.1 #512. Bump commons-lang3 from 3.13.0 to 3.14.0. Bump commons.bytebuddy.version from 1.14.9 to 1.14.10 #516. Bump commons-parent from 64 to 65. XmlStreamReader encoding match RE is too strict. Javadoc in FileUtils does not reflect code for thrown exceptions. Javadoc should mention closing Streams based on file resources. In tests, Files.walk() direct and indirect callers fail to close the returned Stream. FileUtils.listFiles(File, String[], boolean) fails to close its internal Stream. FileUtils.iterateFiles(File, String[], boolean) fails to close its internal Stream. StreamIterator fails to close its internal Stream. Don't throw UncheckedIOException #491. Don't write a BOM on every (or any) line #492. RandomAccessFileMode.create(Path) provides a better NullPointerException message. Improve performance of PathUtils.fileContentEquals(Path, Path, LinkOption[], OpenOption[]) by about 60%, see PathUtilsContentEqualsBenchmark. Improve performance of PathUtils.fileContentEquals(Path, Path) by about 60%, see PathUtilsContentEqualsBenchmark. Improve performance of FileUtils.contentEquals(File, File) by about 60%, see PathUtilsContentEqualsBenchmark. Remove unused test code #494. [Javadoc] IOUtils#contentEquals does not throw NullPointerException #496. Fix CodeQL warnings in UnsynchronizedBufferedInputStream: Implicit narrowing conversion in compound assignment. MessageDigestCalculatingInputStream.MessageDigestMaintainingObserver.MessageDigestMaintainingObserver(MessageDigest) now throws a NullPointerException if the MessageDigest is null. MessageDigestCalculatingInputStream.MessageDigestCalculatingInputStream(InputStream, MessageDigest) now throws a NullPointerException if the MessageDigest is null. UnsynchronizedBufferedInputStream.read(byte[], int, int) does not use buffer. Pick up Maven Moditect plugin version from parent POM. 2.15.0 breaks backwards compatibility in PathUtils.fileContentEquals for the Zip file system. Add org.apache.commons.io.channels.FileChannels. Add RandomAccessFiles#contentEquals(RandomAccessFile, RandomAccessFile). Add RandomAccessFiles#reset(RandomAccessFile). Add PathUtilsContentEqualsBenchmark. Add org.apache.commons.io.StreamIterator. Add MessageDigestInputStream and deprecate MessageDigestCalculatingInputStream. Bump org.apache.commons:commons-parent from 62 to 64. ReaderInputStream.read() throws an exception instead of returning -1 when called again after returning -1. FileUtils.forceMkdirParent() Javadoc is incorrect. [StepSecurity] ci: Harden GitHub Actions #461. MagicNumberFileFilter.accept(Path, BasicFileAttributes) doesn't set its byteOffset before reading. Javadoc improvements. Spelling #468. Use assertThrows #475. Add DeferredFileOutputStream.getPath(). Add FileCleaningTracker.track(Path, Object[, FileDeleteStrategy]). Add IOUtils.skip[Fully](InputStream, long, Supplier<byte[]>). Add FilesUncheck.find(Path, int, BiPredicate%lt;Path, BasicFileAttributes>, FileVisitOption...) Add IOIntSupplier. Add IOLongSupplier. Add Uncheck.getAsInt(IOIntSupplier [, Supplier<String>]). Add Uncheck.getAsLong(IOLongSupplier [, Supplier<String>]). Add Uncheck.run(IORunnable, Supplier<String>) Add Uncheck.get(IOSupplier, Supplier<String>) IOFileFilter now also extends java.nio.file.PathMatcher. Add PathMatcherFileFilter to adapt java.nio.file.PathMatcher. Add ThresholdingOutputStream.getOutputStream() and deprecate getStream(). Add DeferredFileOutputStream.Builder.setOutputFile(Path). Add DeferredFileOutputStream.Builder.setDirectory(Path). Add AbstractStreamBuilder.setBufferSizeChecker(IntToIntFunction). Add AbstractStreamBuilder.setBufferSizeMax(int). Bump jimfs from 1.2 to 1.3.0 #465 (tests). Bump commons-parent from 58 to 62. Bump commons-lang3 from 3.12 to 3.13.0. Regression in FileUtils.touch() - no longer creates parent directories. ByteArrayOrigin should be able convert a byte[] to a ByteArrayInputStream. AbstractOriginSupplier.checkOrigin() now throws IllegalStateException instead of NullPointerException. FileAlreadyExistsException in PathUtils.createParentDirectories(Path, LinkOption, FileAttribute...). Only read the relevant portion of a file in AbstractOrigin.FileOrigin.getByteArray(long, int). Only read the relevant portion of a file in AbstractOrigin.PathOrigin.getByteArray(long, int). DeferredFileOutputStream throws exception when system temp dir is a symlink. ReaderInputStream.Builder.setCharsetEncoder(null) should reset to a default object, not throw an NPE. ReaderInputStream.Builder.setCharset(null) should reset to a default object, not throw an NPE. Fix back-incompatible change for PathUtils.deleteDirectory(): throw NoSuchFileException instead of IllegalArgumentException #459. Deprecation documentation gives incorrect alternative. Add CharSequenceInputStream.Builder. Add ChunkedOutputStream.Builder. Add AbstractStreamBuilder.setOpenOptions(OpenOption...). Add some missing conversions to AbstractOrigin subclasses. Add AbstractOrigin.getByteArray(long, int). Add and use RandomAccessFiles. Add AbstractOrigin.size(). Add PathUtils.EMPTY_FILE_ATTRIBUTE_ARRAY. Add CharSequenceInputStream.Builder.setCharsetEncoder(CharsetEncoder). Add CharsetEncoders.toCharsetEncoder(CharsetEncoder, Supplier<CharsetEncoder>). Bump commons-parent from 57 to 58. IOUtils.toByteArray size validation does not match documentation. Fix Javadoc links to the JRE Javadoc 8. FileWriterWithEncoding for an existing file no longer truncates the file. #251. A null Charset or Charset name in FileWriterWithEncoding constructors uses the default Charset. Fix usage of assertNotNull #269. FilenameUtils directoryContains() should handle files with the same prefix #217. Drop unnecessary casts and conversions #267. FileUtils.moveToDirectory() exception documentation and exception message error. ThreadMonitor.sleep(Duration) ignores nanoseconds. Fix Javadoc in ThreadMonitor#run() method. #273. FileUtils.listFiles() does not list matching files if File parameter is a symbolic link. Fix typo in Javadocs for FileUtils#convertFileCollectionToFileArray() #276. Avoid Code Duplication: Reuse Sleep from ThreadMonitor #66. FileUtils.iterateFiles also lists directories. Wrong exception message in FileUtils.setLastModified(File, File). Infinite loop in ReaderInputStream instead of throwing exception for CodingErrorAction.REPORT. ReaderInputStream enter infinite loop for too small buffer sizes. Infinite loop in CharSequenceInputStream.read for 4-byte characters with UTF-8 and 3-byte buffer. PathUtils.setReadOnly(Path, boolean, LinkOption...) should add READ_* file attributes when using POSIX. PathUtils.setReadOnly(Path, boolean, LinkOption...) readOnly argument is always assumed true on POSIX. Prevent IllegalArgumentExceptions in BrokenInputStream/Reader/OutputStream/Writer #278. FileUtils.copyURLToFile(URL, File, int, int) leaks its URLConnection. Called by FileUtils.copyURLToFile(URL, File). Fixed ReaderInputStream not calling CharsetEncoder.flush issue #283. Minor changes #287. Update FileWriterWithEncoding to extend ProxyWriter #296. Initialize the message of an IOExceptionList to a default if null. When deleting symlinks, File/PathUtils.deleteDirectory() changes file permissions of the target. ReaderInputStream maps null Charset, Charset name, and CharsetEncoder to the platform default instead of throwing a NullPointerException. CharSequenceInputStream maps null Charset and Charset name to the platform default instead of throwing a NullPointerException. WriterOutputStream maps null Charset, Charset name, and CharsetEncoder name to the platform default instead of throwing a NullPointerException. FileUtils.copyURLToFile should create target parent directories and overwrite target file #319. Fix incorrect FilenameUtils Javadoc for null bytes #310. Change to uppercase variable constant. #323. IOCase.isCaseSensitive(IOCase) result is backward #325. Deprecate PathUtils.NOFOLLOW_LINK_OPTION_ARRAY in favor of noFollowLinkOptionArray(). Improve ReaderInputStream documentation #291. Fix misleading comments in FileFilterTest #334. Add missing Javadoc for exceptions thrown for invalid arguments #339. FileFilterTest minor fixes #340. IOUtils.write() throws OutOfMemoryError/NegativeArraySizeException while writing big strings #343. Add reserved Windows file names CONIN$ and CONOUT$ to FileSystem #355. RegexFileFilter is no longer Serializable. [Javadoc] FileFilterUtils doc does not match impl: missing some file filters. FileSystem.WINDOWS.isReservedFileName doesn't check for file extension. Confusing Javadoc on IOUtils#resourceToURL() and other resource* methods. FileUtils.copyFile methods throw an unnecessary "Failed to copy full contents from" exception. Pick up Javadoc from super for override write() methods in AbstractByteArrayOutputStream and ByteArrayOutputStream. Fix minor typos #367. Fix parameters to requireNonNull call in DeferredOutputSteam #368. Fix PathUtils.copyFileToDirectory(URL,Path,CopyOption[]). FileUtils.doCopyFile uses different methods to check the file sizes. Fix typos #375. FilenameUtils.normalize javadoc and tests #383. Better docs in IOUtils and IOUtils.byteArray(int size) #374. SequenceReader should close readers when its close method is called #391. Fix symbolic link file filter #450. Apply nanoseconds precision for QueueInputStream timeout duration. #453. Fix overflow for FileUtilsTest constants #456. Serialization is deprecated and will be removed in 3.0. FileSystemUtils.performCommand(String[], int, Duration): Use Locale.getDefault() instead of ENGLISH. Add GitHub coverage.yml. Add MemoryMappedFileInputStream #215. Add BrokenReader.INSTANCE. Add UncheckedBufferedReader. Add UncheckedFilterReader. Add UncheckedFilterWriter. Add UncheckedFilterInputStream. Add UncheckedFilterOutputStream. Add BrokenInputStream.INSTANCE. Add ClosedInputStream.INSTANCE and deprecate CLOSED_INPUT_STREAM. Add ClosedReader.INSTANCE and deprecate CLOSED_READER. Add BrokenWriter.INSTANCE. Add ClosedOutputStream.INSTANCE and deprecate CLOSED_OUTPUT_STREAM. Add ClosedWriter.INSTANCE and deprecate CLOSED_WRITER. Add NullOutputStream.INSTANCE and deprecate NULL_OUTPUT_STREAM. Add NullPrintStream.INSTANCE and deprecate NULL_PRINT_STREAM. Add NullWriter.INSTANCE and deprecate NULL_WRITER. Add NullInputStream.INSTANCE. Add NullReader.INSTANCE. Add PathUtils.readString(Path, Charset). Add FileUtils.newOutputStream(File, boolean). Add PathUtils.newOutputStream(Path, boolean). Add UncheckedAppendable. Add and reuse UncheckedIOExceptions. Add PathUtils.getTempDirectory(). Add FileSystem.getNameSeparator(). Add FileSystem.normalizeSeparators(). Add PathUtils.isNewer(Path, FileTime, LinkOption...). Add PathUtils.isNewer(Path, Instant, LinkOption...). Add AgeFileFilter.AgeFileFilter(Instant). Add AgeFileFilter.AgeFileFilter(Instant, boolean). Add FileUtils.lastModifiedFileTime(File). Add FileTimes. Add PathUtils.waitFor(Path, Duration, LinkOption...). Add org.apache.commons.io.input.Tailer.getDelayDuration(). Add FileUtils.current(). Add and use PathUtils.setLastModifiedTime(Path) for more precision. Add and use PathUtils.setLastModifiedTime(Path, Path) for more precision. Add and use PathUtils.isNewer(Path, ChronoZonedDateTime, LinkOption...) for more precision. Add and use PathUtils.isNewer(Path, Path) for more precision. Add and use FileUtils.isNewer(File, FileTime) for more precision. Add and use PathUtils.isOlder(Path, FileTime, LinkOption...). Add and use PathUtils.isOlder(Path, Instant, LinkOption...). Add and use PathUtils.isOlder(Path, long, LinkOption...). Add and use PathUtils.isOlder(Path, Path). Add and use PathUtils.sizeOf(Path). Add and use PathUtils.sizeOfAsBigInteger(Path). Add and use PathUtils.sizeOfDirectory(Path). Add and use PathUtils.sizeOfDirectoryAsBigInteger(Path). Add and use IOCase.value(IOCase, IOCase). Add Tailer.Tailable interface to allow tailing of remote files for example using jCIFS. Add and use RandomAccessFileMode. Add PathUtils.writeString(Path, CharSequence, Charset, OpenOption...). Add PathUtiFiles.getFileAttributeView() shorthands: - PathUtils.getAclFileAttributeView(Path, LinkOption...) - PathUtils.getDosFileAttributeView(Path, LinkOption...) - PathUtils.getPosixFileAttributeView(Path, LinkOption...) Make commons-io a JPMS module by adding module-info.class. Add IOUtils method to copy output stream to input stream #281. Add PathUtils.isPosix(Path, LinkOption...). #290 Add PathUtils.readAttributes(Path, Class, LinkOption...). #290 Add IOExceptionList.checkEmpty(List, Object). Add IOBiConsumer, IOTriConsumer, IOComparator, IOUnaryOperator, IOBinaryOperator. Add and reuse IOConsumer forAll(*), forEach(*), and forEachIndexed(*). Add CharsetEncoders. Add CharsetDecoders. Add PathUtils.createParentDirectories(Path, LinkOption, FileAttribute...). Update FileEntry to use FileTime instead of long for file time stamps. Add more tests for IOUtils.contentEqualsIgnoreEOL #137. Reduce boilerplate through new UncheckedIO class and friends in org.apache.commons.io.function. Add PathUtils.touch(Path). Add FileSystem.getIllegalFileNameCodePoints(). Add FileUtils.isFileNewer(File, ChronoLocalDate, OffsetTime). Add FileUtils.isFileNewer(File, OffsetDateTime). Add FileUtils.isFileOlder(File, ChronoLocalDate, OffsetTime). Add FileUtils.isFileOlder(File, OffsetDateTime). Add IOBiConsumer.noop(). Add IOUtils.closeQuietly(Iterable<Closeable>). Add IOUtils.closeQuietly(Stream<Closeable>). Add Charsets.toCharset(Charset, Charset). Add Charsets.toCharset(String, Charset). Add XmlStreamWriter(OutputStream, Charset). Add PathUtils.getLastModifiedFileTime(*). Add IOBiFunction, IOTriFunction, IOQuadFunction, IOPredicate, IOIterator, IOSpliterator, IOBaseStream, IOStream, FilesUncheck. Add IOUtils.consume(Reader). Add IOSupplier.asSupplier(). Add IOFunction.asFunction(). Add IOConsumer.asConsumer(). Add TimestampedObserver.isClosed(). IOExceptionList implements Iterable. Add support for Appendable to HexDump #418. Add and use ThreadUtils. Add UnsynchronizedFilterInputStream. Add UnsynchronizedBufferedInputStream. Add FileSystem.getBlockSize(). Add builders and avoid creating more constructors for all permutations of current options. Refactor using new Supplier API IOUtils.toString(IOSupplier<InputStream>, Charset[, IOSupplier<String>]). Refactor using new Supplier API org.apache.commons.io.file.PathUtils.copy(IOSupplier<InputStream>, Path, CopyOption...). Bump actions/cache from 2.1.6 to 3.0.10 #307, #337, #393. Bump actions/checkout from 2.3.4 to 3.1.0 #286, #298, #330, #392. Bump actions/setup-java from 2 to 3.6.0 #346, #397. Bump github/codeql-action from 1 to 2 #353. Bump Maven Javadoc plugin from 3.2.0 to 3.4.1. Bump spotbugs-maven-plugin from 4.2.3 to 4.7.3.0 #250, #259, #272, #274, #285, #288, #289, #305, #315, #326, #338, #360, #366, #370, #380, #395, #403. Bump spotbugs from 4.5.2 to 4.7.3 #313, #317, #357, #382, #398. Bump JUnit from 5.7.2 to 5.8.2. Bump maven-enforcer-plugin from 3.0.0-M3 to 3.3.0 #255, #363, #431, #446. Bump checkstyle from 8.44 to 9.3 #256, #257, #266, #279, #292. #308. Bump junit-bom from 5.8.0-M1 to 5.9.1 #260, #271, #275, #309, #386. Bump mockito-inline from 3.11.2 to 4.11.0 #262, #264, #282, #306, #314, #331, #348, #359, #381, #399, #405, #414, #420. Bump jmh.version from 1.32 to 1.36 #258, #316, #342, #404. Bump moditect-maven-plugin from 1.0.0.RC1 to 1.0.0.Final #280, #439, #445. Bump junit-pioneer from 1.4.2 to 1.9.1 #304. #335, #362, #402, #406, #409. Bump japicmp-maven-plugin from 0.15.3 to 0.16.0. Bump commons-parent from 52 to 57 #388, #415, #421, #184. Bump jacoco-maven-plugin from 0.8.7 to 0.8.8. Bump maven-antrun-plugin from 3.0.0 to 3.1.0 #354. Bump commons.surefire.version 3.0.0-M5 to 3.0.0-M7. Bump PMD from 6.44.0 to 6.52.0. Bump maven-pmd-plugin from 3.16.0 to 3.19.0. Bump apache-rat from 0.13 to 0.14. Bump exec-maven-plugin from 3.0.0 to 3.1.0 #369. Bump maven-checkstyle-plugin from 3.1.2 to 3.2.0 #376. Bump apache-rat-plugin from 0.14 to 0.15 #387. Bump default buffer size for CharSequenceInputStream to IOUtils#DEFAULT_BUFFER_SIZE. Bump default buffer size for ChunkedOutputStream to IOUtils#DEFAULT_BUFFER_SIZE. Bump default buffer size for ChunkedWriter to IOUtils#DEFAULT_BUFFER_SIZE. Bump default buffer size for ReaderInputStream to IOUtils#DEFAULT_BUFFER_SIZE. Bump default buffer size for WriterOutputStream to IOUtils#DEFAULT_BUFFER_SIZE. 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. 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.5.0, #158, #164, #165, #180, #199, #213, #224, #302. 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.6.0 #134, #332. 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.Observer 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 forever 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 failure 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.16.1-src/src/changes/release-notes.vm0100644 0000000 0000000 00000010735 14603604450 022326 0ustar00rootroot0000000 0000000 ## Licensed to the Apache Software Foundation (ASF) under one ## or more contributor license agreements. See the NOTICE file ## distributed with this work for additional information ## regarding copyright ownership. The ASF licenses this file ## to you under the Apache License, Version 2.0 (the ## "License"); you may not use this file except in compliance ## with the License. You may obtain a copy of the License at ## ## http://www.apache.org/licenses/LICENSE-2.0 ## ## Unless required by applicable law or agreed to in writing, ## software distributed under the License is distributed on an ## "AS IS" BASIS, WITHOUT 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} 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("(? commons-io-2.16.1-src/src/conf/checkstyle.xml0100644 0000000 0000000 00000004720 14603604450 021406 0ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/conf/maven-pmd-plugin.xml0100644 0000000 0000000 00000011007 14603604450 022424 0ustar00rootroot0000000 0000000 The default ruleset used by the Maven PMD Plugin, when no other ruleset is specified. It contains the rules of the old (pre PMD 6.0.0) rulesets java-basic, java-empty, java-imports, java-unnecessary, java-unusedcode. This ruleset might be used as a starting point for an own customized ruleset [0]. [0] https://pmd.github.io/latest/pmd_userdocs_making_rulesets.html commons-io-2.16.1-src/src/conf/spotbugs-exclude-filter.xml0100644 0000000 0000000 00000006013 14603604450 024025 0ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/main/java/org/apache/commons/io/ByteOrderMark.java0100644 0000000 0000000 00000015430 14603604450 027115 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.nio.charset.StandardCharsets; import java.util.Locale; import java.util.Objects; /** * Byte Order Mark (BOM) representation. See {@link org.apache.commons.io.input.BOMInputStream}. *

* We define the follow BOM constants: *

*
    *
  • {@link #UTF_16BE}
  • *
  • {@link #UTF_16LE}
  • *
  • {@link #UTF_32BE}
  • *
  • {@link #UTF_32LE}
  • *
  • {@link #UTF_8}
  • *
*

Deprecating Serialization

*

* Serialization is deprecated and will be removed in 3.0. *

* * @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. *

* This BOM is: *

*
     * 0xEF 0xBB 0xBF
     * 
*/ public static final ByteOrderMark UTF_8 = new ByteOrderMark(StandardCharsets.UTF_8.name(), 0xEF, 0xBB, 0xBF); /** * UTF-16BE BOM (Big-Endian). *

* This BOM is: *

*
     * 0xFE 0xFF
     * 
*/ public static final ByteOrderMark UTF_16BE = new ByteOrderMark(StandardCharsets.UTF_16BE.name(), 0xFE, 0xFF); /** * UTF-16LE BOM (Little-Endian). *

* This BOM is: *

*
     * 0xFF 0xFE
     * 
*/ public static final ByteOrderMark UTF_16LE = new ByteOrderMark(StandardCharsets.UTF_16LE.name(), 0xFF, 0xFE); /** * UTF-32BE BOM (Big-Endian). *

* This BOM is: *

*
     * 0x00 0x00 0xFE 0xFF
     * 
* * @since 2.2 */ public static final ByteOrderMark UTF_32BE = new ByteOrderMark("UTF-32BE", 0x00, 0x00, 0xFE, 0xFF); /** * UTF-32LE BOM (Little-Endian). *

* This BOM is: *

*
     * 0xFF 0xFE 0x00 0x00
     * 
* * @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'; /** * Charset name. */ private final String charsetName; /** * Bytes. */ private final int[] bytes; /** * Constructs a new instance. * * @param charsetName The name of the charset the BOM represents * @param bytes The BOM's bytes * @throws IllegalArgumentException if the charsetName is zero length * @throws IllegalArgumentException if the bytes are zero length */ public ByteOrderMark(final String charsetName, final int... bytes) { Objects.requireNonNull(charsetName, "charsetName"); Objects.requireNonNull(bytes, "bytes"); if (charsetName.isEmpty()) { throw new IllegalArgumentException("No charsetName specified"); } if (bytes.length == 0) { throw new IllegalArgumentException("No bytes specified"); } this.charsetName = charsetName; this.bytes = bytes.clone(); } /** * Indicates if this instance'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; } /** * 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; } /** * Gets the name of the {@link java.nio.charset.Charset} the BOM represents. * * @return the character set name */ public String getCharsetName() { return charsetName; } /** * Computes the hash code for this BOM. * * @return the hash code for this BOM. * @see Object#hashCode() */ @Override public int hashCode() { int hashCode = getClass().hashCode(); for (final int b : bytes) { hashCode += b; } return hashCode; } /** * Gets the length of the BOM's bytes. * * @return the length of the BOM's bytes */ public int length() { return bytes.length; } /** * 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.16.1-src/src/main/java/org/apache/commons/io/ByteOrderParser.java0100644 0000000 0000000 00000004720 14603604450 027457 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 { /** * 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 {@link String} containing the ByteOrder representation to be parsed * @return the ByteOrder represented by the string argument * @throws IllegalArgumentException * if the {@link 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); } /** * ByteOrderUtils is a static utility class, so prevent construction with a private constructor. */ private ByteOrderParser() { } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/Charsets.java0100644 0000000 0000000 00000022166 14603604450 026163 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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); } /** * 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; /** * 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 the given charset if non-null, otherwise return defaultCharset. * * @param charset The charset to test, may be null. * @param defaultCharset The charset to return if charset is null, may be null. * @return a Charset . * @since 2.12.0 */ public static Charset toCharset(final Charset charset, final Charset defaultCharset) { return charset == null ? 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 toCharset(charsetName, Charset.defaultCharset()); } /** * Returns a Charset for the named charset. If the name is null, return the given default Charset. * * @param charsetName The name of the requested charset, may be null. * @param defaultCharset The name charset to return if charsetName is null, may be null. * @return a Charset for the named charset. * @throws UnsupportedCharsetException If the named charset is unavailable (unchecked exception). * @since 2.12.0 */ public static Charset toCharset(final String charsetName, final Charset defaultCharset) throws UnsupportedCharsetException { return charsetName == null ? defaultCharset : Charset.forName(charsetName); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/CloseableURLConnection.java0100644 0000000 0000000 00000016112 14603604450 030675 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.InputStream; import java.io.OutputStream; import java.net.URI; import java.net.URL; import java.net.URLConnection; import java.security.Permission; import java.util.List; import java.util.Map; import java.util.Objects; /** * Delegates to a URLConnection while implementing AutoCloseable. */ final class CloseableURLConnection extends URLConnection implements AutoCloseable { static CloseableURLConnection open(final URI uri) throws IOException { return open(Objects.requireNonNull(uri, "uri").toURL()); } static CloseableURLConnection open(final URL url) throws IOException { return new CloseableURLConnection(url.openConnection()); } private final URLConnection urlConnection; CloseableURLConnection(final URLConnection urlConnection) { super(Objects.requireNonNull(urlConnection, "urlConnection").getURL()); this.urlConnection = urlConnection; } @Override public void addRequestProperty(final String key, final String value) { urlConnection.addRequestProperty(key, value); } @Override public void close() { IOUtils.close(urlConnection); } @Override public void connect() throws IOException { urlConnection.connect(); } @Override public boolean equals(final Object obj) { return urlConnection.equals(obj); } @Override public boolean getAllowUserInteraction() { return urlConnection.getAllowUserInteraction(); } @Override public int getConnectTimeout() { return urlConnection.getConnectTimeout(); } @Override public Object getContent() throws IOException { return urlConnection.getContent(); } @Override public Object getContent(@SuppressWarnings("rawtypes") final Class[] classes) throws IOException { return urlConnection.getContent(classes); } @Override public String getContentEncoding() { return urlConnection.getContentEncoding(); } @Override public int getContentLength() { return urlConnection.getContentLength(); } @Override public long getContentLengthLong() { return urlConnection.getContentLengthLong(); } @Override public String getContentType() { return urlConnection.getContentType(); } @Override public long getDate() { return urlConnection.getDate(); } @Override public boolean getDefaultUseCaches() { return urlConnection.getDefaultUseCaches(); } @Override public boolean getDoInput() { return urlConnection.getDoInput(); } @Override public boolean getDoOutput() { return urlConnection.getDoOutput(); } @Override public long getExpiration() { return urlConnection.getExpiration(); } @Override public String getHeaderField(final int n) { return urlConnection.getHeaderField(n); } @Override public String getHeaderField(final String name) { return urlConnection.getHeaderField(name); } @Override public long getHeaderFieldDate(final String name, final long Default) { return urlConnection.getHeaderFieldDate(name, Default); } @Override public int getHeaderFieldInt(final String name, final int Default) { return urlConnection.getHeaderFieldInt(name, Default); } @Override public String getHeaderFieldKey(final int n) { return urlConnection.getHeaderFieldKey(n); } @Override public long getHeaderFieldLong(final String name, final long Default) { return urlConnection.getHeaderFieldLong(name, Default); } @Override public Map> getHeaderFields() { return urlConnection.getHeaderFields(); } @Override public long getIfModifiedSince() { return urlConnection.getIfModifiedSince(); } @Override public InputStream getInputStream() throws IOException { return urlConnection.getInputStream(); } @Override public long getLastModified() { return urlConnection.getLastModified(); } @Override public OutputStream getOutputStream() throws IOException { return urlConnection.getOutputStream(); } @Override public Permission getPermission() throws IOException { return urlConnection.getPermission(); } @Override public int getReadTimeout() { return urlConnection.getReadTimeout(); } @Override public Map> getRequestProperties() { return urlConnection.getRequestProperties(); } @Override public String getRequestProperty(final String key) { return urlConnection.getRequestProperty(key); } @Override public URL getURL() { return urlConnection.getURL(); } @Override public boolean getUseCaches() { return urlConnection.getUseCaches(); } @Override public int hashCode() { return urlConnection.hashCode(); } @Override public void setAllowUserInteraction(final boolean allowUserInteraction) { urlConnection.setAllowUserInteraction(allowUserInteraction); } @Override public void setConnectTimeout(final int timeout) { urlConnection.setConnectTimeout(timeout); } @Override public void setDefaultUseCaches(final boolean defaultUseCaches) { urlConnection.setDefaultUseCaches(defaultUseCaches); } @Override public void setDoInput(final boolean doInput) { urlConnection.setDoInput(doInput); } @Override public void setDoOutput(final boolean doOutput) { urlConnection.setDoOutput(doOutput); } @Override public void setIfModifiedSince(final long ifModifiedSince) { urlConnection.setIfModifiedSince(ifModifiedSince); } @Override public void setReadTimeout(final int timeout) { urlConnection.setReadTimeout(timeout); } @Override public void setRequestProperty(final String key, final String value) { urlConnection.setRequestProperty(key, value); } @Override public void setUseCaches(final boolean useCaches) { urlConnection.setUseCaches(useCaches); } @Override public String toString() { return urlConnection.toString(); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/CopyUtils.java0100644 0000000 0000000 00000033640 14603604450 026341 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 ({@link InputStream}, {@link Reader}, * {@link String} and {@code byte[]}) and destinations * ({@link OutputStream}, {@link Writer}, {@link 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. *

* Provenance: 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 { /** * Copies bytes from a {@code byte[]} to an {@link OutputStream}. * @param input the byte array to read from * @param output the {@link 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 * {@link 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 {@link Writer} to write to * @throws IOException In case of an I/O problem * @deprecated 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 * {@link Writer}, using the specified encoding. * * @param input the byte array to read from * @param output the {@link 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 {@link InputStream} to an * {@link OutputStream}. * * @param input the {@link InputStream} to read from * @param output the {@link 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; } /** * Copies and convert bytes from an {@link InputStream} to chars on a * {@link Writer}. * The platform's default encoding is used for the byte-to-char conversion. * * @param input the {@link InputStream} to read from * @param output the {@link Writer} to write to * @throws IOException In case of an I/O problem * @deprecated 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 {@link InputStream} to chars on a * {@link Writer}, using the specified encoding. * * @param input the {@link InputStream} to read from * @param output the {@link 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); } /** * Serialize chars from a {@link Reader} to bytes on an * {@link OutputStream}, and flush the {@link OutputStream}. * Uses the default platform encoding. * * @param input the {@link Reader} to read from * @param output the {@link OutputStream} to write to * @throws IOException In case of an I/O problem * @deprecated 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 {@link Reader} to bytes on an * {@link OutputStream}, and flush the {@link OutputStream}. * * @param input the {@link Reader} to read from * @param output the {@link 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(); } /** * Copies chars from a {@link Reader} to a {@link Writer}. * * @param input the {@link Reader} to read from * @param output the {@link 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.getScratchCharArray(); int count = 0; int n; while (EOF != (n = input.read(buffer))) { output.write(buffer, 0, n); count += n; } return count; } /** * Serialize chars from a {@link String} to bytes on an * {@link OutputStream}, and * flush the {@link OutputStream}. * Uses the platform default encoding. * * @param input the {@link String} to read from * @param output the {@link OutputStream} to write to * @throws IOException In case of an I/O problem * @deprecated 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 {@link String} to bytes on an * {@link OutputStream}, and * flush the {@link OutputStream}. * * @param input the {@link String} to read from * @param output the {@link 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(); } /** * Copies chars from a {@link String} to a {@link Writer}. * * @param input the {@link String} to read from * @param output the {@link 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); } /** * Instances should NOT be constructed in standard programming. * * @deprecated TODO Make private in 3.0. */ @Deprecated public CopyUtils() { // empty } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/DirectoryWalker.java0100644 0000000 0000000 00000064064 14603604450 027524 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 {@link 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 {@link 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 is a cancel button on a GUI. Calling this method sets a * (@code volatile} * flag to ensure it works properly in a multi-threaded environment. * The flag is returned by the {@code handleIsCancelled()} method, which causes 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 { /** * 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 {@link 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 {@link 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 depth when the operation was cancelled. * * @return the depth when the operation was cancelled */ public int getDepth() { return depth; } /** * Returns the file when the operation was cancelled. * * @return the file when the operation was cancelled */ public File getFile() { return file; } } /** * 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; /** * Constructs 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; } /** * Checks whether the walk has been cancelled by calling {@link #handleIsCancelled}, * throwing a {@link 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 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 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 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 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 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 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 } /** * 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 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 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 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 } /** * 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); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/EndianUtils.java0100644 0000000 0000000 00000046234 14603604450 026630 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; /** * Helps with reading and writing primitive numeric types ({@code short}, * {@code int}, {@code long}, {@code float}, and {@code double}) that are * encoded in little endian using two's complement or unsigned representations. *

* Different computer architectures have different conventions for * byte ordering. In "Little Endian" architectures (e.g. X86), * the low-order byte is stored in memory at the lowest address, and * subsequent bytes at higher addresses. In "Big Endian" architectures * (e.g. Motorola 680X0), the situation is reversed. * Most methods and classes throughout Java — e.g. {@code DataInputStream} and * {@code Double.longBitsToDouble()} — assume data is laid out * in big endian order with the most significant byte first. * The methods in this class read and write data in little endian order, * generally by reversing the bytes and then using the * regular Java methods to convert the swapped bytes to a primitive type. *

*

* Provenance: Excalibur *

* * @see org.apache.commons.io.input.SwappedDataInputStream */ public class EndianUtils { /** * 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; } /** * Reads a little endian {@code double} value from a byte array at a given offset. * * @param data source byte array * @param offset starting offset in the byte array * @return the value read * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 8 bytes */ public static double readSwappedDouble(final byte[] data, final int offset) { return Double.longBitsToDouble(readSwappedLong(data, offset)); } /** * Reads a little endian {@code double} value from an InputStream. * * @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 a little endian {@code float} value from a byte array at a given offset. * * @param data source byte array * @param offset starting offset in the byte array * @return the value read * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 4 bytes */ public static float readSwappedFloat(final byte[] data, final int offset) { return Float.intBitsToFloat(readSwappedInteger(data, offset)); } /** * Reads a little endian {@code float} value from an InputStream. * * @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)); } /** * Reads a little endian {@code int} value from a byte array at a given offset. * * @param data source byte array * @param offset starting offset in the byte array * @return the value read * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 4 bytes */ public static int readSwappedInteger(final byte[] data, final int offset) { validateByteArrayOffset(data, offset, Integer.SIZE / Byte.SIZE); return ((data[offset + 0] & 0xff) << 0) + ((data[offset + 1] & 0xff) << 8) + ((data[offset + 2] & 0xff) << 16) + ((data[offset + 3] & 0xff) << 24); } /** * Reads a little endian {@code int} value from an InputStream. * * @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 little endian {@code long} value from a byte array at a given offset. * * @param data source byte array * @param offset starting offset in the byte array * @return the value read * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 8 bytes */ public static long readSwappedLong(final byte[] data, final int offset) { validateByteArrayOffset(data, offset, Long.SIZE / Byte.SIZE); final long low = readSwappedInteger(data, offset); final long high = readSwappedInteger(data, offset + 4); return (high << 32) + (0xffffffffL & low); } /** * Reads a little endian {@code long} value from an InputStream. * * @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); } /** * Reads a little endian {@code short} value from a byte array at a given offset. * * @param data source byte array * @param offset starting offset in the byte array * @return the value read * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 2 bytes */ public static short readSwappedShort(final byte[] data, final int offset) { validateByteArrayOffset(data, offset, Short.SIZE / Byte.SIZE); return (short) (((data[offset + 0] & 0xff) << 0) + ((data[offset + 1] & 0xff) << 8)); } /** * Reads a little endian {@code short} value from an InputStream. * * @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 little endian unsigned integer (32-bit) value from a byte array at a given * offset. * * @param data source byte array * @param offset starting offset in the byte array * @return the value read * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 4 bytes */ public static long readSwappedUnsignedInteger(final byte[] data, final int offset) { validateByteArrayOffset(data, offset, Integer.SIZE / Byte.SIZE); 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); } /** * Reads a little endian unsigned integer (32-bit) from an InputStream. * * @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); } /** * Reads an unsigned short (16-bit) value from a byte array in little endian order at a given * offset. * * @param data source byte array * @param offset starting offset in the byte array * @return the value read * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 2 bytes */ public static int readSwappedUnsignedShort(final byte[] data, final int offset) { validateByteArrayOffset(data, offset, Short.SIZE / Byte.SIZE); return ((data[offset + 0] & 0xff) << 0) + ((data[offset + 1] & 0xff) << 8); } /** * Reads an unsigned short (16-bit) from an InputStream in little endian order. * * @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); } /** * Converts a {@code double} value from big endian to little endian * and vice versa. That is, it converts the {@code double} to bytes, * reverses the bytes, and then reinterprets those bytes as a new {@code double}. * This can be useful if you have a number that was read from the * underlying source in the wrong endianness. * * @param value value to convert * @return the converted value */ public static double swapDouble(final double value) { return Double.longBitsToDouble(swapLong(Double.doubleToLongBits(value))); } /** * Converts a {@code float} value from big endian to little endian and vice versa. * * @param value value to convert * @return the converted value */ public static float swapFloat(final float value) { return Float.intBitsToFloat(swapInteger(Float.floatToIntBits(value))); } /** * Converts an {@code int} value from big endian to little endian and vice versa. * * @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 {@code long} value from big endian to little endian and vice versa. * * @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 {@code short} value from big endian to little endian and vice versa. * * @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)); } /** * Validates if the provided byte array has enough data. * * @param data the input byte array * @param offset the input offset * @param byteNeeded the needed number of bytes * @throws IllegalArgumentException if the byte array does not have enough data */ private static void validateByteArrayOffset(final byte[] data, final int offset, final int byteNeeded) { if (data.length < offset + byteNeeded) { throw new IllegalArgumentException("Data only has " + data.length + "bytes, needed " + (offset + byteNeeded) + "bytes."); } } /** * Writes the 8 bytes of a {@code double} to a byte array at a given offset in little endian order. * * @param data target byte array * @param offset starting offset in the byte array * @param value value to write * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 8 bytes */ public static void writeSwappedDouble(final byte[] data, final int offset, final double value) { writeSwappedLong(data, offset, Double.doubleToLongBits(value)); } /** * Writes the 8 bytes of a {@code double} to an output stream in little endian order. * * @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)); } /** * Writes the 4 bytes of a {@code float} to a byte array at a given offset in little endian order. * * @param data target byte array * @param offset starting offset in the byte array * @param value value to write * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 4 bytes */ public static void writeSwappedFloat(final byte[] data, final int offset, final float value) { writeSwappedInteger(data, offset, Float.floatToIntBits(value)); } /** * Writes the 4 bytes of a {@code float} to an output stream in little endian order. * * @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)); } /** * Writes the 4 bytes of an {@code int} to a byte array at a given offset in little endian order. * * @param data target byte array * @param offset starting offset in the byte array * @param value value to write * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 4 bytes */ public static void writeSwappedInteger(final byte[] data, final int offset, final int value) { validateByteArrayOffset(data, offset, Integer.SIZE / Byte.SIZE); 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); } /** * Writes the 4 bytes of an {@code int} to an output stream in little endian order. * * @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)); } /** * Writes the 8 bytes of a {@code long} to a byte array at a given offset in little endian order. * * @param data target byte array * @param offset starting offset in the byte array * @param value value to write * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 8 bytes */ public static void writeSwappedLong(final byte[] data, final int offset, final long value) { validateByteArrayOffset(data, offset, Long.SIZE / Byte.SIZE); 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); } /** * Writes the 8 bytes of a {@code long} to an output stream in little endian order. * * @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)); } /** * Writes the 2 bytes of a {@code short} to a byte array at a given offset in little endian order. * * @param data target byte array * @param offset starting offset in the byte array * @param value value to write * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 2 bytes */ public static void writeSwappedShort(final byte[] data, final int offset, final short value) { validateByteArrayOffset(data, offset, Short.SIZE / Byte.SIZE); data[offset + 0] = (byte) (value >> 0 & 0xff); data[offset + 1] = (byte) (value >> 8 & 0xff); } /** * Writes the 2 bytes of a {@code short} to an output stream using little endian encoding. * * @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)); } /** * Instances should NOT be constructed in standard programming. * * @deprecated TODO Make private in 3.0. */ @Deprecated public EndianUtils() { // empty } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/FileCleaner.java0100644 0000000 0000000 00000015331 14603604450 026554 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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. */ private static final FileCleaningTracker INSTANCE = new FileCleaningTracker(); /** * 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() { INSTANCE.exitWhenFinished(); } /** * Gets 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 INSTANCE; } /** * Gets 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 INSTANCE.getTrackCount(); } /** * 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) { INSTANCE.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) { INSTANCE.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) { INSTANCE.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) { INSTANCE.track(path, marker, deleteStrategy); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/FileCleaningTracker.java0100644 0000000 0000000 00000027455 14603604450 030251 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.nio.file.Path; 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 /** * The reaper thread. */ private final class Reaper extends Thread { /** Constructs a new Reaper */ Reaper() { super("File Reaper"); setPriority(Thread.MAX_PRIORITY); setDaemon(true); } /** * Runs 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; } /** * 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)); } /** * Gets the path. * * @return the path */ public String getPath() { return path; } } /** * Queue of {@link Tracker} instances being watched. */ ReferenceQueue q = new ReferenceQueue<>(); /** * Collection of {@link 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; /** * 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)); } /** * 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(); } } } /** * Gets a copy of the file paths that failed to delete. * * @return a copy of the file paths that failed to delete * @since 2.0 */ public List getDeleteFailures() { return new ArrayList<>(deleteFailures); } /** * Gets the number of files currently being tracked, and therefore * awaiting deletion. * * @return the number of files being tracked */ public int getTrackCount() { return trackers.size(); } /** * Tracks 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); } /** * Tracks 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); } /** * Tracks 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 * @since 2.14.0 */ public void track(final Path file, final Object marker) { track(file, marker, null); } /** * Tracks 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 * @since 2.14.0 */ public void track(final Path file, final Object marker, final FileDeleteStrategy deleteStrategy) { Objects.requireNonNull(file, "file"); addTracker(file.toAbsolutePath().toString(), marker, deleteStrategy); } /** * Tracks 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); } /** * Tracks 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); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/FileDeleteStrategy.java0100644 0000000 0000000 00000012501 14603604450 030124 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 {@link 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 {@link 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.16.1-src/src/main/java/org/apache/commons/io/FileExistsException.java0100644 0000000 0000000 00000003135 14603604450 030340 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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() { } /** * Constructs an instance with the specified file. * * @param file The file that exists */ public FileExistsException(final File file) { super("File " + file + " exists"); } /** * Constructs an instance with the specified message. * * @param message The error message */ public FileExistsException(final String message) { super(message); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/FileSystem.java0100644 0000000 0000000 00000045362 14603604450 026476 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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(4096, false, false, Integer.MAX_VALUE, Integer.MAX_VALUE, new int[] { 0 }, new String[] {}, false, false, '/'), /** * Linux file system. */ LINUX(8192, true, true, 255, 4096, new int[] { // KEEP THIS ARRAY SORTED! // @formatter:off // ASCII NUL 0, '/' // @formatter:on }, new String[] {}, false, false, '/'), /** * MacOS file system. */ MAC_OSX(4096, true, true, 255, 1024, new int[] { // KEEP THIS ARRAY SORTED! // @formatter:off // ASCII NUL 0, '/', ':' // @formatter:on }, new String[] {}, false, false, '/'), /** * Windows file system. *

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

* * @see Naming Conventions * (microsoft.com) * @see * CreateFileA function - Consoles (microsoft.com) */ WINDOWS(4096, false, true, 255, 32000, // KEEP THIS ARRAY SORTED! new int[] { // 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 }, new String[] { "AUX", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", "CON", "CONIN$", "CONOUT$", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9", "NUL", "PRN" }, true, 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); /** * The current FileSystem. */ private static final FileSystem CURRENT = current(); /** * Gets the current file system. * * @return the current file system */ private static FileSystem current() { if (IS_OS_LINUX) { return LINUX; } if (IS_OS_MAC) { return MAC_OSX; } if (IS_OS_WINDOWS) { return WINDOWS; } return GENERIC; } /** * Gets the current file system. * * @return the current file system */ public static FileSystem getCurrent() { return CURRENT; } /** * 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 {@link 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; } } /** * Copied from Apache Commons Lang CharSequenceUtils. * * Returns the index within {@code cs} of the first occurrence of the * specified character, starting the search at the specified index. *

* If a character with value {@code searchChar} occurs in the * character sequence represented by the {@code cs} * object at an index no smaller than {@code start}, then * the index of the first such occurrence is returned. For values * of {@code searchChar} in the range from 0 to 0xFFFF (inclusive), * this is the smallest value k such that: *

*
     * (this.charAt(k) == searchChar) && (k >= start)
     * 
* is true. For other values of {@code searchChar}, it is the * smallest value k such that: *
     * (this.codePointAt(k) == searchChar) && (k >= start)
     * 
*

* is true. In either case, if no such character occurs in {@code cs} * at or after position {@code start}, then * {@code -1} is returned. *

*

* There is no restriction on the value of {@code start}. If it * is negative, it has the same effect as if it were zero: the entire * {@link CharSequence} may be searched. If it is greater than * the length of {@code cs}, it has the same effect as if it were * equal to the length of {@code cs}: {@code -1} is returned. *

*

All indices are specified in {@code char} values * (Unicode code units). *

* * @param cs the {@link CharSequence} to be processed, not null * @param searchChar the char to be searched for * @param start the start index, negative starts at the string start * @return the index where the search char was found, -1 if not found * @since 3.6 updated to behave more like {@link String} */ private static int indexOf(final CharSequence cs, final int searchChar, int start) { if (cs instanceof String) { return ((String) cs).indexOf(searchChar, start); } final int sz = cs.length(); if (start < 0) { start = 0; } if (searchChar < Character.MIN_SUPPLEMENTARY_CODE_POINT) { for (int i = start; i < sz; i++) { if (cs.charAt(i) == searchChar) { return i; } } return -1; } //supplementary characters (LANG1300) if (searchChar <= Character.MAX_CODE_POINT) { final char[] chars = Character.toChars(searchChar); for (int i = start; i < sz - 1; i++) { final char high = cs.charAt(i); final char low = cs.charAt(i + 1); if (high == chars[0] && low == chars[1]) { return i; } } } return -1; } /** * 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)); } /** * Null-safe replace. * * @param path the path to be changed, null ignored. * @param oldChar the old character. * @param newChar the new character. * @return the new path. */ private static String replace(final String path, final char oldChar, final char newChar) { return path == null ? null : path.replace(oldChar, newChar); } private final int blockSize; private final boolean casePreserving; private final boolean caseSensitive; private final int[] illegalFileNameChars; private final int maxFileNameLength; private final int maxPathLength; private final String[] reservedFileNames; private final boolean reservedFileNamesExtensions; private final boolean supportsDriveLetter; private final char nameSeparator; private final char nameSeparatorOther; /** * Constructs a new instance. * * @param blockSize file allocation block size in bytes. * @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 reservedFileNamesExtensions TODO * @param supportsDriveLetter Whether this file system support driver letters. * @param nameSeparator The name separator, '\\' on Windows, '/' on Linux. */ FileSystem(final int blockSize, final boolean caseSensitive, final boolean casePreserving, final int maxFileLength, final int maxPathLength, final int[] illegalFileNameChars, final String[] reservedFileNames, final boolean reservedFileNamesExtensions, final boolean supportsDriveLetter, final char nameSeparator) { this.blockSize = blockSize; this.maxFileNameLength = maxFileLength; this.maxPathLength = maxPathLength; this.illegalFileNameChars = Objects.requireNonNull(illegalFileNameChars, "illegalFileNameChars"); this.reservedFileNames = Objects.requireNonNull(reservedFileNames, "reservedFileNames"); this.reservedFileNamesExtensions = reservedFileNamesExtensions; this.caseSensitive = caseSensitive; this.casePreserving = casePreserving; this.supportsDriveLetter = supportsDriveLetter; this.nameSeparator = nameSeparator; this.nameSeparatorOther = FilenameUtils.flipSeparator(nameSeparator); } /** * Gets the file allocation block size in bytes. * @return the file allocation block size in bytes. * * @since 2.12.0 */ public int getBlockSize() { return blockSize; } /** * Gets a cloned copy of the illegal characters for this file system. * * @return the illegal characters for this file system. */ public char[] getIllegalFileNameChars() { final char[] chars = new char[illegalFileNameChars.length]; for (int i = 0; i < illegalFileNameChars.length; i++) { chars[i] = (char) illegalFileNameChars[i]; } return chars; } /** * Gets a cloned copy of the illegal code points for this file system. * * @return the illegal code points for this file system. * @since 2.12.0 */ public int[] getIllegalFileNameCodePoints() { 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 the name separator, '\\' on Windows, '/' on Linux. * * @return '\\' on Windows, '/' on Linux. * * @since 2.12.0 */ public char getNameSeparator() { return nameSeparator; } /** * Gets a cloned copy of the reserved file names. * * @return the reserved file names. */ public String[] getReservedFileNames() { return reservedFileNames.clone(); } /** * Tests whether this file system preserves case. * * @return Whether this file system preserves case. */ public boolean isCasePreserving() { return casePreserving; } /** * Tests whether this file system is case-sensitive. * * @return Whether this file system is case-sensitive. */ public boolean isCaseSensitive() { return caseSensitive; } /** * Tests 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 int c) { return Arrays.binarySearch(illegalFileNameChars, c) >= 0; } /** * Tests 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; } return candidate.chars().noneMatch(this::isIllegalFileNameChar); } /** * Tests 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) { final CharSequence test = reservedFileNamesExtensions ? trimExtension(candidate) : candidate; return Arrays.binarySearch(reservedFileNames, test) >= 0; } /** * Converts all separators to the Windows separator of backslash. * * @param path the path to be changed, null ignored * @return the updated path * @since 2.12.0 */ public String normalizeSeparators(final String path) { return replace(path, nameSeparatorOther, nameSeparator); } /** * 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)) { // %s does not work properly with NUL throw new IllegalArgumentException(String.format("The replacement character '%s' cannot be one of the %s illegal characters: %s", replacement == '\0' ? "\\0" : replacement, name(), Arrays.toString(illegalFileNameChars))); } final String truncated = candidate.length() > maxFileNameLength ? candidate.substring(0, maxFileNameLength) : candidate; final int[] array = truncated.chars().map(i -> isIllegalFileNameChar(i) ? replacement : i).toArray(); return new String(array, 0, array.length); } CharSequence trimExtension(final CharSequence cs) { final int index = indexOf(cs, '.', 0); return index < 0 ? cs : cs.subSequence(0, index); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/FileSystemUtils.java0100644 0000000 0000000 00000015713 14603604450 027514 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Objects; /** * General File System utilities. *

* This class provides static utility methods for general file system functions not provided before Java 6's {@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, * {@code Files.getFileStore(Paths.get("/home")).getUsableSpace()} or iterate over {@code FileSystems.getDefault().getFileStores()} */ @Deprecated public class FileSystemUtils { /** * Gets the number of kibibytes (1024 bytes) available to this Java virtual machine on the given file store. *

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

* *
     * FileSystemUtils.freeSpace("C:"); // Windows
     * FileSystemUtils.freeSpace("/volume"); // *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 IOException if an I/O error occurs. * @throws IllegalArgumentException if the path is invalid. * @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 getFreeSpace(path); } /** * Gets the number of kibibytes (1024 bytes) available to this Java virtual machine on the current file store. *

* Identical to: *

* *
     * freeSpaceKb(FileUtils.current().getAbsolutePath())
     * 
* * @return the amount of free drive space on the drive or volume in kilobytes * @throws IOException if an I/O error occurs. * @throws IllegalArgumentException if the path is invalid. * @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); } /** * Gets the number of kibibytes (1024 bytes) available to this Java virtual machine on the current file store. *

* Identical to: *

* *
     * freeSpaceKb(FileUtils.current().getAbsolutePath())
     * 
* * @param timeout ignored. * @return the amount of free drive space on the drive or volume in kilobytes * @throws IOException if an I/O error occurs. * @throws IllegalArgumentException if the path is invalid. * @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(FileUtils.current().getAbsolutePath(), timeout); } /** * Gets the number of kibibytes (1024 bytes) available to this Java virtual machine on the given file store. * *
     * FileSystemUtils.freeSpaceKb("C:"); // Windows
     * FileSystemUtils.freeSpaceKb("/volume"); // *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 in kilobytes * @throws IOException if an I/O error occurs. * @throws IllegalArgumentException if the path is invalid. * @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); } /** * Gets the number of kibibytes (1024 bytes) available to this Java virtual machine on the given file store. * *
     * FileSystemUtils.freeSpaceKb("C:"); // Windows
     * FileSystemUtils.freeSpaceKb("/volume"); // *nix
     * 
* * @param path the path to get free space for, not null, not empty on UNIX * @param timeout ignored. * @return the amount of free drive space on the drive or volume in kilobytes * @throws IOException if an I/O error occurs. * @throws IllegalArgumentException if the path is invalid. * @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 getFreeSpace(path) / FileUtils.ONE_KB; } /** * Gets the number of bytes available to this Java virtual machine on the given file store. * *
     * FileSystemUtils.freeSpace("C:"); // Windows
     * FileSystemUtils.freeSpace("/volume"); // *nix
     * 
* * @param pathStr 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 IOException if an I/O error occurs. * @throws IllegalArgumentException if the path is invalid. */ static long getFreeSpace(final String pathStr) throws IOException { final Path path = Paths.get(Objects.requireNonNull(pathStr, "pathStr")); if (Files.exists(path)) { // Need an absolute path for input like "" to work return Files.getFileStore(path.toAbsolutePath()).getUsableSpace(); // return path.toAbsolutePath().toFile().getUsableSpace(); } throw new IllegalArgumentException(path.toString()); } /** * Instances should NOT be constructed in standard programming. * * @deprecated TODO Make private in 3.0. */ @Deprecated public FileSystemUtils() { // empty } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/FileUtils.java0100644 0000000 0000000 00000503747 14603604450 026320 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.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.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.DirectoryStream; import java.nio.file.FileVisitOption; import java.nio.file.FileVisitResult; 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.nio.file.attribute.BasicFileAttributeView; import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.FileTime; import java.time.Duration; import java.time.Instant; import java.time.LocalTime; import java.time.OffsetDateTime; import java.time.OffsetTime; 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.Collection; import java.util.Collections; import java.util.Date; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Objects; import java.util.Set; 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; import org.apache.commons.io.function.IOConsumer; import org.apache.commons.io.function.Uncheck; /** * 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. *

*

* Provenance: 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 {@link File}. */ public static final File[] EMPTY_FILE_ARRAY = {}; /** * 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 {@link 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)); } /** * 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? * @since 2.12.0 */ // See https://issues.apache.org/jira/browse/IO-226 - should the rounding be changed? public static String byteCountToDisplaySize(final Number size) { return byteCountToDisplaySize(size.longValue()); } /** * Requires that the given {@link File} object * points to an actual file (not a directory) in the file system, * and throws a {@link FileNotFoundException} if it doesn't. * It throws an IllegalArgumentException if the object points to a directory. * * @param file The {@link File} to check. * @param name The parameter name to use in the exception message. * @throws FileNotFoundException if the file does not exist * @throws NullPointerException if the given {@link File} is {@code null}. * @throws IllegalArgumentException if the given {@link File} is not a file. */ private static void checkFileExists(final File file, final String name) throws FileNotFoundException { Objects.requireNonNull(file, name); if (!file.isFile()) { if (file.exists()) { throw new IllegalArgumentException("Parameter '" + name + "' is not a file: " + file); } if (!Files.isSymbolicLink(file.toPath())) { throw new FileNotFoundException("Source '" + file + "' does not exist"); } } } private static File checkIsFile(final File file, final String name) { if (file.isFile()) { return file; } throw new IllegalArgumentException(String.format("Parameter '%s' is not a file: %s", name, file)); } /** * Computes the checksum of a file using the specified checksum object. Multiple files may be checked using one * {@link 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 {@link File} is {@code null}. * @throws NullPointerException if the given {@link Checksum} is {@code null}. * @throws IllegalArgumentException if the given {@link File} is not a file. * @throws FileNotFoundException if the file does not exist * @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 { checkFileExists(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 {@link File} is {@code null}. * @throws IllegalArgumentException if the given {@link 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 {@link 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 { IOConsumer.forAll(FileUtils::forceDelete, listFiles(directory, null)); } /** * Cleans a directory without deleting it. * * @param directory directory to clean, must not be {@code null} * @throws NullPointerException if the given {@link 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 { IOConsumer.forAll(FileUtils::forceDeleteOnExit, listFiles(directory, null)); } /** * 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. *

* * @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 PathUtils#fileContentEquals(Path,Path) */ 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; } checkIsFile(file1, "file1"); checkIsFile(file2, "file2"); if (file1.length() != file2.length()) { // lengths differ, cannot be equal return false; } if (file1.getCanonicalFile().equals(file2.getCanonicalFile())) { // same file return true; } return PathUtils.fileContentEquals(file1.toPath(), file2.toPath()); } /** * 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; } checkFileExists(file1, "file1"); checkFileExists(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 {@link File} instances into array * representation. This is to account for the difference between * File.listFiles() and FileUtils.listFiles(). * * @param files a Collection containing {@link File} instances * @return an array of {@link 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. That is, copying /home/bar to /tmp/bang * copies the contents of /home/bar into /tmp/bang. It does not create /tmp/bang/bar. *

*

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

*

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

*

* Symbolic links in the source directory are copied to new symbolic links in the destination * directory that point to the original target. The target of the link is not copied unless * it is also under the source directory. Even if it is under the source directory, the new symbolic * link in the destination points to the original target in the source directory, not to the * newly created copy of the target. *

* * @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 {@link File}s are {@code null}. * @throws IllegalArgumentException if {@code srcDir} exists but is not a directory, * the source and the destination directory are the same * @throws FileNotFoundException if the source does not exist. * @throws IOException if an error occurs, the destination is not writable, or setting the last-modified time didn't succeed * @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 does 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 method 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 IllegalArgumentException if {@code srcDir} exists but is not a directory, or * the source and the destination directory are the same * @throws FileNotFoundException if the source does not exist. * @throws IOException if an error occurs, the destination is not writable, or setting the last-modified time didn't succeed * @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 does 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 method 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 {@link File}s are {@code null}. * @throws IllegalArgumentException if {@code srcDir} exists but is not a directory, or * the source and the destination directory are the same * @throws FileNotFoundException if the source does not exist. * @throws IOException if an error occurs, the destination is not writable, or setting the last-modified time didn't succeed * @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 does 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 file's last * modified date/times using {@link BasicFileAttributeView#setTimes(FileTime, FileTime, FileTime)}. However, it is * not guaranteed that the operation will succeed. If the modification operation fails it falls back to * {@link File#setLastModified(long)}. If that fails, the method 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 {@link File}s are {@code null}. * @throws IllegalArgumentException if {@code srcDir} exists but is not a directory, * the source and the destination directory are the same, or the destination is not writable * @throws FileNotFoundException if the source does not exist. * @throws IOException if an error occurs or setting the last-modified time didn't succeed. * @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, LinkOption.NOFOLLOW_LINKS); } /** * 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 does 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 file's last * modified date/times using {@link BasicFileAttributeView#setTimes(FileTime, FileTime, FileTime)}. However, it is * not guaranteed that the operation will succeed. If the modification operation fails it falls back to * {@link File#setLastModified(long)}. If that fails, the method 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 {@link File}s are {@code null}. * @throws IllegalArgumentException if {@code srcDir} exists but is not a directory, or * the source and the destination directory are the same * @throws FileNotFoundException if the source does not exist. * @throws IOException if an error occurs, the destination is not writable, or setting the last-modified time didn't succeed * @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 { Objects.requireNonNull(destDir, "destination"); requireDirectoryExists(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) { exclusionList.add(new File(destDir, srcFile.getName()).getCanonicalPath()); } } } doCopyDirectory(srcDir, destDir, fileFilter, exclusionList, preserveFileDate, 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 does 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 file's last * modified date/times using {@link BasicFileAttributeView#setTimes(FileTime, FileTime, FileTime)}. However, it is * not guaranteed that the operation will succeed. If the modification operation fails it falls back to * {@link File#setLastModified(long)} and if that fails, the method 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 {@link 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, the destination is not writable, or setting the last-modified time didn't succeed * @since 1.2 */ public static void copyDirectoryToDirectory(final File sourceDir, final File destinationDir) throws IOException { Objects.requireNonNull(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 * overwrites it. A symbolic link is resolved before copying so the new file is not a link. *

*

* Note: This method tries to preserve the file's last modified date/times using * {@link BasicFileAttributeView#setTimes(FileTime, FileTime, FileTime)}. However, it is not guaranteed that the * operation will succeed. If the modification operation fails, it falls back to * {@link File#setLastModified(long)}, and if that fails, the method 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 {@link 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 succeed. * @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.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 * overwrites it. A symbolic link is resolved before copying so the new file is not a link. *

*

* Note: Setting {@code preserveFileDate} to {@code true} tries to preserve the file's last * modified date/times using {@link BasicFileAttributeView#setTimes(FileTime, FileTime, FileTime)}. However, it is * not guaranteed that the operation will succeed. If the modification operation fails, it falls back to * {@link File#setLastModified(long)}, and if that fails, the method 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 {@link 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 succeed. * @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, StandardCopyOption.REPLACE_EXISTING); } /** * Copies the contents of 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}. *

* *

* By default, a symbolic link is resolved before copying so the new file is not a link. * To copy symbolic links as links, you can pass {@code LinkOption.NO_FOLLOW_LINKS} as the last argument. *

* *

* Note: Setting {@code preserveFileDate} to {@code true} tries to preserve the file's last * modified date/times using {@link BasicFileAttributeView#setTimes(FileTime, FileTime, FileTime)}. However, it is * not guaranteed that the operation will succeed. If the modification operation fails, it falls back to * {@link File#setLastModified(long)}, and if that fails, the method 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 {@link File}s are {@code null}. * @throws FileNotFoundException if the source does not exist. * @throws IllegalArgumentException if {@code srcFile} or {@code destFile} 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, setting the last-modified time didn't succeed, * or the destination is not writable * @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 { Objects.requireNonNull(destFile, "destination"); checkFileExists(srcFile, "srcFile"); requireCanonicalPathsNotEquals(srcFile, destFile); createParentDirectories(destFile); if (destFile.exists()) { checkFileExists(destFile, "destFile"); } final Path srcPath = srcFile.toPath(); Files.copy(srcPath, destFile.toPath(), copyOptions); // On Windows, the last modified time is copied by default. if (preserveFileDate && !Files.isSymbolicLink(srcPath) && !setTimes(srcFile, destFile)) { throw new IOException("Cannot set the file time."); } } /** * 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 {@link File}s are {@code null}. * @throws FileNotFoundException if the source does not exist. * @throws IllegalArgumentException if source is not a file. * @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 { copyFile(srcFile, destFile, true, copyOptions); } /** * Copies bytes from a {@link File} to an {@link OutputStream}. *

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

* * @param input the {@link File} to read. * @param output the {@link 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 BasicFileAttributeView#setTimes(FileTime, FileTime, FileTime)}. However, it is not guaranteed that the * operation will succeed. If the modification operation fails it falls back to * {@link File#setLastModified(long)} and if that fails, the method 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 {@link 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 succeed. * @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 BasicFileAttributeView#setTimes(FileTime, FileTime, FileTime)}. However, it is * not guaranteed that the operation will succeed. If the modification operation fails it falls back to * {@link File#setLastModified(long)} and if that fails, the method 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 {@link File}s are {@code null}. * @throws IOException if an error occurs or setting the last-modified time didn't succeed. * @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 {@link InputStream} to copy bytes from, must not be {@code null}, will be closed * @param destination the non-directory {@link 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 with 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 does 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 file's last * modified date/times using {@link BasicFileAttributeView#setTimes(FileTime, FileTime, FileTime)}. However, it is * not guaranteed that the operation will succeed. If the modification operation fails it falls back to * {@link File#setLastModified(long)} and if that fails, the method 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 {@link 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 succeed. * @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 BasicFileAttributeView#setTimes(FileTime, FileTime, FileTime)}. However, it is * not guaranteed that the operation will succeed. If the modification operation fails it falls back to * {@link File#setLastModified(long)} and if that fails, the method throws IOException. *

* * @param sourceIterable existing files to copy, must not be {@code null}. * @param destinationDir the directory to place the copies in, must not be {@code null}. * @throws NullPointerException if any of the given {@link 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 succeed. * @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 {@link InputStream} to copy bytes from, must not be {@code null} * @param file the non-directory {@link 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 = newOutputStream(file, false)) { 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 {@link URL} to copy bytes from, must not be {@code null} * @param destination the non-directory {@link 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 { final Path path = destination.toPath(); PathUtils.createParentDirectories(path); PathUtils.copy(source::openStream, path, StandardCopyOption.REPLACE_EXISTING); } /** * 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 {@link URL} to copy bytes from, must not be {@code null} * @param destination the non-directory {@link File} to write bytes to (possibly overwriting), must not be * {@code null} * @param connectionTimeoutMillis the number of milliseconds until this method will time out if no connection could * be established to the {@code source} * @param readTimeoutMillis the number of milliseconds until this method will time out 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 { try (CloseableURLConnection urlConnection = CloseableURLConnection.open(source)) { urlConnection.setConnectTimeout(connectionTimeoutMillis); urlConnection.setReadTimeout(readTimeoutMillis); try (InputStream stream = urlConnection.getInputStream()) { copyInputStreamToFile(stream, destination); } } } /** * Creates all parent directories for a File object, including any necessary but non-existent parent directories. If a parent directory already exists or * is null, nothing happens. * * @param file the File that may need parents, may be null. * @return The parent directory, or {@code null} if the given File does have a parent. * @throws IOException if the directory was not created along with all its parent directories. * @throws SecurityException See {@link File#mkdirs()}. * @since 2.9.0 */ public static File createParentDirectories(final File file) throws IOException { return mkdirs(getParentFile(file)); } /** * Gets the current directory. * * @return the current directory. * @since 2.12.0 */ public static File current() { return PathUtils.current().toFile(); } /** * 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 builder = new StringBuilder(); final ByteBuffer byteBuffer = 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); byteBuffer.put(octet); i += 3; } while (i < n && url.charAt(i) == '%'); continue; } catch (final IndexOutOfBoundsException | NumberFormatException ignored) { // malformed percent-encoded octet, fall through and // append characters literally } finally { if (byteBuffer.position() > 0) { byteBuffer.flip(); builder.append(StandardCharsets.UTF_8.decode(byteBuffer).toString()); byteBuffer.clear(); } } } builder.append(url.charAt(i++)); } decoded = builder.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 NullPointerException if the parameter is {@code null} * @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 NullPointerException if the parameter is {@code null} * @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 subdirectories. *

* 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 NullPointerException
  • *
  • 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 parent is {@code null}. * @throws IllegalArgumentException if the parent 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 || !child.exists()) { return false; } // Canonicalize paths (normalizes relative paths) return FilenameUtils.directoryContains(directory.getCanonicalPath(), child.getCanonicalPath()); } /** * Internal copy directory method. Creates all destination parent directories, * including any necessary but non-existent parent directories. * * @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 IllegalArgumentException if {@code destDir} is not writable * @throws SecurityException See {@link File#mkdirs()}. */ 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); 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, preserveDirDate, copyOptions); } } } // Do this last, as the above has probably affected directory metadata if (preserveDirDate) { setTimes(srcDir, destDir); } } /** * Deletes a file or directory. For a directory, delete it and all subdirectories. *

* 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 ex) { throw new IOException("Cannot delete file: " + file, ex); } 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 subdirectories. * * @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(); } } /** * Creates all directories for a File object, including any necessary but non-existent parent directories. If the {@code directory} already exists or is * null, nothing happens. *

* Calls {@link File#mkdirs()} and throws an {@link IOException} on failure. *

* * @param directory the receiver for {@code mkdirs()}. If the {@code directory} already exists or is null, nothing happens. * @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() */ public static void forceMkdir(final File directory) throws IOException { mkdirs(directory); } /** * Creates all directories for a File object, including any necessary but non-existent parent directories. If the parent directory already exists or is * null, nothing happens. *

* Calls {@link File#mkdirs()} for the parent of {@code file}. *

* * @param file file with parents to create, must not be {@code null}. * @throws NullPointerException if the file is {@code null}. * @throws IOException if the directory was not created along with all its parent directories. * @throws SecurityException See {@link File#mkdirs()}. * @see File#mkdirs() * @since 2.5 */ public static void forceMkdirParent(final File file) throws IOException { forceMkdir(getParentFile(Objects.requireNonNull(file, "file"))); } /** * Constructs 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; } /** * Constructs 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 null. Note that a file's parent may be null as well. * * @param file The file to query, may be null. * @return The parent file or {@code null}. Note that a file's parent may be null as well. */ 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 as a File * @since 2.0 */ public static File getTempDirectory() { return new File(getTempDirectoryPath()); } /** * Returns the path to the system temporary directory. * * WARNING: this method relies on the Java system property 'java.io.tmpdir' * which may or may not have a trailing file separator. * This can affect code that uses String processing to manipulate pathnames rather * than the standard libary methods in classes such as {@link java.io.File} * * @return the path to the system temporary directory as a String * @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 {@link File} is a directory or not. Implemented as a * null-safe delegate to {@link 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 {@link File} is newer than the specified {@link ChronoLocalDate} * at the end of day. * *

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 {@link File} of which the modification date must be compared. * @param chronoLocalDate the date reference. * @return true if the {@link File} exists and has been modified after the given * {@link ChronoLocalDate} at the current time. * @throws UncheckedIOException if an I/O error occurs * @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.MAX); } /** * Tests if the specified {@link File} is newer than the specified {@link 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 {@link File} of which the modification date must be compared. * @param chronoLocalDate the date reference. * @param localTime the time reference. * @return true if the {@link File} exists and has been modified after the given * {@link ChronoLocalDate} at the given time. * @throws UncheckedIOException if an I/O error occurs * @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 {@link File} is newer than the specified {@link ChronoLocalDate} at the specified * {@link OffsetTime}. * * @param file the {@link File} of which the modification date must be compared * @param chronoLocalDate the date reference * @param offsetTime the time reference * @return true if the {@link File} exists and has been modified after the given {@link ChronoLocalDate} at the given * {@link OffsetTime}. * @throws UncheckedIOException if an I/O error occurs * @throws NullPointerException if the file, local date or zone ID is {@code null} * @since 2.12.0 */ public static boolean isFileNewer(final File file, final ChronoLocalDate chronoLocalDate, final OffsetTime offsetTime) { Objects.requireNonNull(chronoLocalDate, "chronoLocalDate"); Objects.requireNonNull(offsetTime, "offsetTime"); return isFileNewer(file, chronoLocalDate.atTime(offsetTime.toLocalTime())); } /** * Tests if the specified {@link File} is newer than the specified {@link 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 {@link File} of which the modification date must be compared. * @param chronoLocalDateTime the date reference. * @return true if the {@link File} exists and has been modified after the given * {@link ChronoLocalDateTime} at the system-default time zone. * @throws UncheckedIOException if an I/O error occurs * @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 {@link File} is newer than the specified {@link ChronoLocalDateTime} * at the specified {@link ZoneId}. * * @param file the {@link File} of which the modification date must be compared. * @param chronoLocalDateTime the date reference. * @param zoneId the time zone. * @return true if the {@link File} exists and has been modified after the given * {@link ChronoLocalDateTime} at the given {@link ZoneId}. * @throws UncheckedIOException if an I/O error occurs * @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 {@link File} is newer than the specified {@link ChronoZonedDateTime}. * * @param file the {@link File} of which the modification date must be compared. * @param chronoZonedDateTime the date reference. * @return true if the {@link File} exists and has been modified after the given * {@link ChronoZonedDateTime}. * @throws NullPointerException if the file or zoned date time is {@code null}. * @throws UncheckedIOException if an I/O error occurs * @since 2.8.0 */ public static boolean isFileNewer(final File file, final ChronoZonedDateTime chronoZonedDateTime) { Objects.requireNonNull(file, "file"); Objects.requireNonNull(chronoZonedDateTime, "chronoZonedDateTime"); return Uncheck.get(() -> PathUtils.isNewer(file.toPath(), chronoZonedDateTime)); } /** * Tests if the specified {@link File} is newer than the specified {@link Date}. * * @param file the {@link File} of which the modification date must be compared. * @param date the date reference. * @return true if the {@link File} exists and has been modified * after the given {@link Date}. * @throws UncheckedIOException if an I/O error occurs * @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 {@link File} is newer than the reference {@link File}. * * @param file the {@link File} of which the modification date must be compared. * @param reference the {@link File} of which the modification date is used. * @return true if the {@link File} exists and has been modified more * recently than the reference {@link File}. * @throws NullPointerException if the file or reference file is {@code null}. * @throws UncheckedIOException if the reference file doesn't exist. */ public static boolean isFileNewer(final File file, final File reference) { return Uncheck.get(() -> PathUtils.isNewer(file.toPath(), reference.toPath())); } /** * Tests if the specified {@link File} is newer than the specified {@link FileTime}. * * @param file the {@link File} of which the modification date must be compared. * @param fileTime the file time reference. * @return true if the {@link File} exists and has been modified after the given {@link FileTime}. * @throws IOException if an I/O error occurs. * @throws NullPointerException if the file or local date is {@code null}. * @since 2.12.0 */ public static boolean isFileNewer(final File file, final FileTime fileTime) throws IOException { Objects.requireNonNull(file, "file"); return PathUtils.isNewer(file.toPath(), fileTime); } /** * Tests if the specified {@link File} is newer than the specified {@link Instant}. * * @param file the {@link File} of which the modification date must be compared. * @param instant the date reference. * @return true if the {@link File} exists and has been modified after the given {@link Instant}. * @throws NullPointerException if the file or instant is {@code null}. * @throws UncheckedIOException if an I/O error occurs * @since 2.8.0 */ public static boolean isFileNewer(final File file, final Instant instant) { Objects.requireNonNull(instant, "instant"); return Uncheck.get(() -> PathUtils.isNewer(file.toPath(), instant)); } /** * Tests if the specified {@link File} is newer than the specified time reference. * * @param file the {@link 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 {@link File} exists and has been modified after the given time reference. * @throws UncheckedIOException if an I/O error occurs * @throws NullPointerException if the file is {@code null}. */ public static boolean isFileNewer(final File file, final long timeMillis) { Objects.requireNonNull(file, "file"); return Uncheck.get(() -> PathUtils.isNewer(file.toPath(), timeMillis)); } /** * Tests if the specified {@link File} is newer than the specified {@link OffsetDateTime}. * * @param file the {@link File} of which the modification date must be compared * @param offsetDateTime the date reference * @return true if the {@link File} exists and has been modified before the given {@link OffsetDateTime}. * @throws UncheckedIOException if an I/O error occurs * @throws NullPointerException if the file or zoned date time is {@code null} * @since 2.12.0 */ public static boolean isFileNewer(final File file, final OffsetDateTime offsetDateTime) { Objects.requireNonNull(offsetDateTime, "offsetDateTime"); return isFileNewer(file, offsetDateTime.toInstant()); } /** * Tests if the specified {@link File} is older than the specified {@link ChronoLocalDate} * at the end of day. * *

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 {@link File} of which the modification date must be compared. * @param chronoLocalDate the date reference. * @return true if the {@link File} exists and has been modified before the given * {@link ChronoLocalDate} at the current time. * @throws NullPointerException if the file or local date is {@code null}. * @throws UncheckedIOException if an I/O error occurs * @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.MAX); } /** * Tests if the specified {@link File} is older than the specified {@link ChronoLocalDate} * at the specified {@link 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 {@link File} of which the modification date must be compared. * @param chronoLocalDate the date reference. * @param localTime the time reference. * @return true if the {@link File} exists and has been modified before the * given {@link ChronoLocalDate} at the specified time. * @throws UncheckedIOException if an I/O error occurs * @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 {@link File} is older than the specified {@link ChronoLocalDate} at the specified * {@link OffsetTime}. * * @param file the {@link File} of which the modification date must be compared * @param chronoLocalDate the date reference * @param offsetTime the time reference * @return true if the {@link File} exists and has been modified after the given {@link ChronoLocalDate} at the given * {@link OffsetTime}. * @throws NullPointerException if the file, local date or zone ID is {@code null} * @throws UncheckedIOException if an I/O error occurs * @since 2.12.0 */ public static boolean isFileOlder(final File file, final ChronoLocalDate chronoLocalDate, final OffsetTime offsetTime) { Objects.requireNonNull(chronoLocalDate, "chronoLocalDate"); Objects.requireNonNull(offsetTime, "offsetTime"); return isFileOlder(file, chronoLocalDate.atTime(offsetTime.toLocalTime())); } /** * Tests if the specified {@link File} is older than the specified {@link 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 {@link File} of which the modification date must be compared. * @param chronoLocalDateTime the date reference. * @return true if the {@link File} exists and has been modified before the given * {@link ChronoLocalDateTime} at the system-default time zone. * @throws NullPointerException if the file or local date time is {@code null}. * @throws UncheckedIOException if an I/O error occurs * @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 {@link File} is older than the specified {@link ChronoLocalDateTime} * at the specified {@link ZoneId}. * * @param file the {@link File} of which the modification date must be compared. * @param chronoLocalDateTime the date reference. * @param zoneId the time zone. * @return true if the {@link File} exists and has been modified before the given * {@link ChronoLocalDateTime} at the given {@link ZoneId}. * @throws NullPointerException if the file, local date time or zone ID is {@code null}. * @throws UncheckedIOException if an I/O error occurs * @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 {@link File} is older than the specified {@link ChronoZonedDateTime}. * * @param file the {@link File} of which the modification date must be compared. * @param chronoZonedDateTime the date reference. * @return true if the {@link File} exists and has been modified before the given * {@link ChronoZonedDateTime}. * @throws NullPointerException if the file or zoned date time is {@code null}. * @throws UncheckedIOException if an I/O error occurs * @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 {@link File} is older than the specified {@link Date}. * * @param file the {@link File} of which the modification date must be compared. * @param date the date reference. * @return true if the {@link File} exists and has been modified before the given {@link Date}. * @throws NullPointerException if the file or date is {@code null}. * @throws UncheckedIOException if an I/O error occurs */ public static boolean isFileOlder(final File file, final Date date) { Objects.requireNonNull(date, "date"); return isFileOlder(file, date.getTime()); } /** * Tests if the specified {@link File} is older than the reference {@link File}. * * @param file the {@link File} of which the modification date must be compared. * @param reference the {@link File} of which the modification date is used. * @return true if the {@link File} exists and has been modified before the reference {@link File}. * @throws NullPointerException if the file or reference file is {@code null}. * @throws FileNotFoundException if the reference file doesn't exist. * @throws UncheckedIOException if an I/O error occurs */ public static boolean isFileOlder(final File file, final File reference) throws FileNotFoundException { return Uncheck.get(() -> PathUtils.isOlder(file.toPath(), reference.toPath())); } /** * Tests if the specified {@link File} is older than the specified {@link FileTime}. * * @param file the {@link File} of which the modification date must be compared. * @param fileTime the file time reference. * @return true if the {@link File} exists and has been modified before the given {@link FileTime}. * @throws IOException if an I/O error occurs. * @throws NullPointerException if the file or local date is {@code null}. * @since 2.12.0 */ public static boolean isFileOlder(final File file, final FileTime fileTime) throws IOException { Objects.requireNonNull(file, "file"); return PathUtils.isOlder(file.toPath(), fileTime); } /** * Tests if the specified {@link File} is older than the specified {@link Instant}. * * @param file the {@link File} of which the modification date must be compared. * @param instant the date reference. * @return true if the {@link File} exists and has been modified before the given {@link 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 Uncheck.get(() -> PathUtils.isOlder(file.toPath(), instant)); } /** * Tests if the specified {@link File} is older than the specified time reference. * * @param file the {@link 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 {@link File} exists and has been modified before the given time reference. * @throws NullPointerException if the file is {@code null}. * @throws UncheckedIOException if an I/O error occurs */ public static boolean isFileOlder(final File file, final long timeMillis) { Objects.requireNonNull(file, "file"); return Uncheck.get(() -> PathUtils.isOlder(file.toPath(), timeMillis)); } /** * Tests if the specified {@link File} is older than the specified {@link OffsetDateTime}. * * @param file the {@link File} of which the modification date must be compared * @param offsetDateTime the date reference * @return true if the {@link File} exists and has been modified before the given {@link OffsetDateTime}. * @throws NullPointerException if the file or zoned date time is {@code null} * @since 2.12.0 */ public static boolean isFileOlder(final File file, final OffsetDateTime offsetDateTime) { Objects.requireNonNull(offsetDateTime, "offsetDateTime"); return isFileOlder(file, offsetDateTime.toInstant()); } /** * Tests whether the specified {@link File} is a regular file or not. Implemented as a * null-safe delegate to {@link 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 regular file, 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 {@link 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, for example, {"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 {@link File} with the matching files * @since 1.2 */ public static Iterator iterateFiles(final File directory, final String[] extensions, final boolean recursive) { return StreamIterator.iterator(Uncheck.get(() -> streamFiles(directory, recursive, extensions))); } /** * 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 {@link 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...)}. *

* For the best precision, use {@link #lastModifiedFileTime(File)}. *

*

* 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 lastModifiedFileTime(file).toMillis(); } /** * Returns the last modification {@link FileTime} 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.Files#getLastModifiedTime(Path, LinkOption...)}. * @throws IOException if an I/O error occurs. * @since 2.12.0 */ public static FileTime lastModifiedFileTime(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")); } /** * Returns the last modification time in milliseconds via * {@link java.nio.file.Files#getLastModifiedTime(Path, LinkOption...)}. *

* For the best precision, use {@link #lastModifiedFileTime(File)}. *

*

* 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. return Uncheck.apply(FileUtils::lastModified, file); } /** * Returns an Iterator for the lines in a {@link 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 {@link File}. *

* This method opens an {@link 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 using a try-with-resources block or calling the * {@link LineIterator#close()} method. *

*

* The recommended usage pattern is: *

*
     * LineIterator it = FileUtils.lineIterator(file, StandardCharsets.UTF_8.name());
     * 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 a LineIterator for lines in the file, never {@code null}; MUST be closed by the caller. * @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 */ @SuppressWarnings("resource") // Caller closes the result LineIterator. public static LineIterator lineIterator(final File file, final String charsetName) throws IOException { InputStream inputStream = null; try { inputStream = Files.newInputStream(file.toPath()); 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, final FileVisitOption... options) 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, (p, e) -> FileVisitResult.CONTINUE); final Set optionSet = new HashSet<>(); if (options != null) { Collections.addAll(optionSet, options); } Files.walkFileTree(directory.toPath(), optionSet, 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 {@link directory} exists but 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 {@link 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) { final AccumulatorPathVisitor visitor = Uncheck .apply(d -> listAccumulate(d, FileFileFilter.INSTANCE.and(fileFilter), dirFilter, FileVisitOption.FOLLOW_LINKS), directory); return toList(visitor.getFileList().stream().map(Path::toFile)); } /** * Lists 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, for example, {"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 {@link File} with the matching files */ public static Collection listFiles(final File directory, final String[] extensions, final boolean recursive) { try (Stream fileStream = Uncheck.get(() -> streamFiles(directory, recursive, extensions))) { return toList(fileStream); } } /** * 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 {@link 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) { final AccumulatorPathVisitor visitor = Uncheck.apply(d -> listAccumulate(d, fileFilter, dirFilter, FileVisitOption.FOLLOW_LINKS), directory); final List list = visitor.getFileList(); list.addAll(visitor.getDirList()); return toList(list.stream().map(Path::toFile)); } /** * Calls {@link File#mkdirs()} and throws an {@link IOException} on failure. *

* Creates all directories for a File object, including any necessary but non-existent parent directories. If the {@code directory} already exists or is * null, nothing happens. *

* * @param directory the receiver for {@code mkdirs()}. If the {@code directory} already exists or is null, nothing happens. * @return the given directory. * @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 {@link File}s are {@code null}. * @throws IllegalArgumentException if {@code srcDir} exists but is not a directory * @throws FileNotFoundException if the source does not exist. * @throws IOException if an error occurs or setting the last-modified time didn't succeed. * @since 1.4 */ public static void moveDirectory(final File srcDir, final File destDir) throws IOException { Objects.requireNonNull(destDir, "destination"); requireDirectoryExists(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. *

* If {@code createDestDir} is true, creates all destination parent directories, including any necessary but non-existent parent directories. *

* * @param source the directory 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 {@link 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 the directory was not created along with all its parent directories, if enabled. * @throws IOException if an error occurs or setting the last-modified time didn't succeed. * @throws SecurityException See {@link File#mkdirs()}. * @since 1.4 */ public static void moveDirectoryToDirectory(final File source, final File destDir, final boolean createDestDir) throws IOException { validateMoveParameters(source, 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(source, new File(destDir, source.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 {@link File}s are {@code null}. * @throws FileExistsException if the destination file exists. * @throws FileNotFoundException if the source file does not exist. * @throws IllegalArgumentException if {@code srcFile} is a directory * @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 {@link File}s are {@code null}. * @throws FileExistsException if the destination file exists. * @throws FileNotFoundException if the source file does not exist. * @throws IllegalArgumentException if {@code srcFile} is a directory * @throws IOException if an error occurs or setting the last-modified time didn't succeed. * @since 2.9.0 */ public static void moveFile(final File srcFile, final File destFile, final CopyOption... copyOptions) throws IOException { Objects.requireNonNull(destFile, "destination"); checkFileExists(srcFile, "srcFile"); requireAbsent(destFile, "destFile"); final boolean rename = srcFile.renameTo(destFile); if (!rename) { // Don't interfere with file date on move, handled by StandardCopyOption.COPY_ATTRIBUTES copyFile(srcFile, destFile, false, copyOptions); if (!srcFile.delete()) { FileUtils.deleteQuietly(destFile); throw new IOException("Failed to delete original file '" + srcFile + "' after copy to '" + destFile + "'"); } } } /** * Moves a file into a directory. *

* If {@code createDestDir} is true, creates all destination parent directories, including any necessary but non-existent parent directories. *

* * @param srcFile the file to be moved. * @param destDir the directory to move the file into * @param createDestDir if {@code true} create the destination directory. If {@code false} throw an * IOException if the destination directory does not already exist. * @throws NullPointerException if any of the given {@link File}s are {@code null}. * @throws FileExistsException if the destination file exists. * @throws FileNotFoundException if the source file does not exist. * @throws IOException if source or destination is invalid. * @throws IOException if the directory was not created along with all its parent directories, if enabled. * @throws IOException if an error occurs or setting the last-modified time didn't succeed. * @throws SecurityException See {@link File#mkdirs()}. * @throws IllegalArgumentException if {@code destDir} exists but is not a directory * @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); } requireDirectoryExists(destDir, "destDir"); moveFile(srcFile, new File(destDir, srcFile.getName())); } /** * Moves a file or directory into a destination directory. *

* If {@code createDestDir} is true, creates all destination parent directories, including any necessary but non-existent parent directories. *

*

* 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. If {@code false} throw an * IOException if the destination directory does not already exist. * @throws NullPointerException if any of the given {@link File}s are {@code null}. * @throws FileExistsException if the directory or file exists in the destination directory. * @throws FileNotFoundException if the source file does not exist. * @throws IOException if source or destination is invalid. * @throws IOException if an error occurs or setting the last-modified time didn't succeed. * @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); } } /** * Creates a new OutputStream by opening or creating a file, returning an output stream that may be used to write bytes * to the file. * * @param append Whether or not to append. * @param file the File. * @return a new OutputStream. * @throws IOException if an I/O error occurs. * @see PathUtils#newOutputStream(Path, boolean) * @since 2.12.0 */ public static OutputStream newOutputStream(final File file, final boolean append) throws IOException { return PathUtils.newOutputStream(Objects.requireNonNull(file, "file").toPath(), append); } /** * 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 IOException if the directories could not be created, or the file is not writable * @since 2.1 */ public static FileOutputStream openOutputStream(final File file, final boolean append) throws IOException { Objects.requireNonNull(file, "file"); if (file.exists()) { checkIsFile(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 IOException if an I/O error occurs, including when the file does not exist, is a directory rather than a * regular file, or for some other reason why the file cannot be opened for reading. * @since 1.1 */ public static byte[] readFileToByteArray(final File file) throws IOException { Objects.requireNonNull(file, "file"); return Files.readAllBytes(file.toPath()); } /** * 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 IOException if an I/O error occurs, including when the file does not exist, is a directory rather than a * regular file, or for some other reason why the file cannot be opened for reading. * @since 1.3.1 * @deprecated 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 IOException if an I/O error occurs, including when the file does not exist, is a directory rather than a * regular file, or for some other reason why the file cannot be opened for reading. * @since 2.3 */ public static String readFileToString(final File file, final Charset charsetName) throws IOException { return IOUtils.toString(() -> Files.newInputStream(file.toPath()), 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 IOException if an I/O error occurs, including when the file does not exist, is a directory rather than a * regular file, or for some other reason why the file cannot be opened for reading. * @throws java.nio.charset.UnsupportedCharsetException 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 IOException if an I/O error occurs, including when the file does not exist, is a directory rather than a * regular file, or for some other reason why the file cannot be opened for reading. * @since 1.3 * @deprecated 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 IOException if an I/O error occurs, including when the file does not exist, is a directory rather than a * regular file, or for some other reason why the file cannot be opened for reading. * @since 2.3 */ public static List readLines(final File file, final Charset charset) throws IOException { return Files.readAllLines(file.toPath(), 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 IOException if an I/O error occurs, including when the file does not exist, is a directory rather than a * regular file, or for some other reason why the file cannot be opened for reading. * @throws java.nio.charset.UnsupportedCharsetException 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 IOException if an I/O error occurs. * @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)); } } /** * Requires that the given {@link File} exists and is a directory. * * @param directory The {@link 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. * @throws NullPointerException if the given {@link File} is {@code null}. * @throws FileNotFoundException if the given {@link File} does not exist * @throws IllegalArgumentException if the given {@link File} exists but is not a directory. */ private static void requireDirectoryExists(final File directory, final String name) throws FileNotFoundException { Objects.requireNonNull(directory, name); if (!directory.isDirectory()) { if (directory.exists()) { throw new IllegalArgumentException("Parameter '" + name + "' is not a directory: '" + directory + "'"); } throw new FileNotFoundException("Directory '" + directory + "' does not exist."); } } /** * Requires that the given {@link File} is a directory if it exists. * * @param directory The {@link File} to check. * @param name The parameter name to use in the exception message in case of null input. * @throws NullPointerException if the given {@link File} is {@code null}. * @throws IllegalArgumentException if the given {@link File} exists but is not a directory. */ private static void requireDirectoryIfExists(final File directory, final String name) throws FileNotFoundException { Objects.requireNonNull(directory, name); if (directory.exists() && !directory.isDirectory()) { throw new IllegalArgumentException("Parameter '" + name + "' is not a directory: '" + directory + "'"); } } /** * Sets file lastModifiedTime, lastAccessTime and creationTime to match source file * * @param sourceFile The source file to query. * @param targetFile The target file or directory to set. * @return {@code true} if and only if the operation succeeded; * {@code false} otherwise * @throws NullPointerException if sourceFile is {@code null}. * @throws NullPointerException if targetFile is {@code null}. */ private static boolean setTimes(final File sourceFile, final File targetFile) { Objects.requireNonNull(sourceFile, "sourceFile"); Objects.requireNonNull(targetFile, "targetFile"); try { // Set creation, modified, last accessed to match source file final BasicFileAttributes srcAttr = Files.readAttributes(sourceFile.toPath(), BasicFileAttributes.class); final BasicFileAttributeView destAttrView = Files.getFileAttributeView(targetFile.toPath(), BasicFileAttributeView.class); // null guards are not needed; BasicFileAttributes.setTimes(...) is null safe destAttrView.setTimes(srcAttr.lastModifiedTime(), srcAttr.lastAccessTime(), srcAttr.creationTime()); return true; } catch (final IOException ignored) { // Fallback: Only set modified time to match source file return targetFile.setLastModified(sourceFile.lastModified()); } // TODO: (Help!) Determine historically why setLastModified(File, File) needed PathUtils.setLastModifiedTime() if // sourceFile.isFile() was true, but needed setLastModifiedTime(File, long) if sourceFile.isFile() was false } /** * 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. * @throws UncheckedIOException if an IO error occurs. * @since 2.0 */ public static long sizeOf(final File file) { return Uncheck.get(() -> PathUtils.sizeOf(file.toPath())); } /** * 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. * @throws UncheckedIOException if an IO error occurs. * @since 2.4 */ public static BigInteger sizeOfAsBigInteger(final File file) { return Uncheck.get(() -> PathUtils.sizeOfAsBigInteger(file.toPath())); } /** * 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 IllegalArgumentException if the given {@link File} exists but is not a directory * @throws NullPointerException if the directory is {@code null}. * @throws UncheckedIOException if an IO error occurs. */ public static long sizeOfDirectory(final File directory) { try { requireDirectoryExists(directory, "directory"); } catch (final FileNotFoundException e) { throw new UncheckedIOException(e); } return Uncheck.get(() -> PathUtils.sizeOfDirectory(directory.toPath())); } /** * 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 IllegalArgumentException if the given {@link File} exists but is not a directory * @throws NullPointerException if the directory is {@code null}. * @throws UncheckedIOException if an IO error occurs. * @since 2.4 */ public static BigInteger sizeOfDirectoryAsBigInteger(final File directory) { try { requireDirectoryExists(directory, "directory"); } catch (final FileNotFoundException e) { throw new UncheckedIOException(e); } return Uncheck.get(() -> PathUtils.sizeOfDirectoryAsBigInteger(directory.toPath())); } /** * Streams over the files in a given directory (and optionally its subdirectories) which match an array of extensions. *

* The returned {@link Stream} may wrap one or more {@link DirectoryStream}s. When you require timely disposal of file system resources, use a * {@code try}-with-resources block to ensure invocation of the stream's {@link Stream#close()} method after the stream operations are completed. Calling a * closed stream causes a {@link IllegalStateException}. *

* * @param directory the directory to search in * @param recursive if true all subdirectories are searched as well * @param extensions an array of extensions, for example, {"java","xml"}. If this parameter is {@code null}, all files are returned. * @return a Stream of {@link File} for 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 { // @formatter:off final IOFileFilter filter = extensions == null ? FileFileFilter.INSTANCE : FileFileFilter.INSTANCE.and(new SuffixFileFilter(toSuffixes(extensions))); // @formatter:on return PathUtils.walk(directory.toPath(), filter, toMaxDepth(recursive), false, FileVisitOption.FOLLOW_LINKS).map(Path::toFile); } /** * Converts from a {@link URL} to a {@link File}. *

* Syntax such as {@code file:///my%20docs/file.txt} will be * correctly decoded to {@code /my docs/file.txt}. * UTF-8 is used 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 {@link 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 {@link URL} to a {@link 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; } /** * Consumes all of the given stream. *

* When called from a FileTreeWalker, the walker closes the stream because {@link FileTreeWalker#next()} calls {@code top.stream().close()}. *

* * @param stream The stream to consume. * @return a new List. */ 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) { return Stream.of(Objects.requireNonNull(extensions, "extensions")).map(e -> "." + e).toArray(String[]::new); } /** * Implements behavior similar to the UNIX "touch" utility. Creates a new file with size 0, or, if the file exists, just * updates the file's modified time. This method throws an IOException if the last modified date * of the file cannot be set. It creates parent directories if they do not exist. * * @param file the File to touch. * @throws NullPointerException if the parameter is {@code null}. * @throws IOException if setting the last-modified time failed or an I/O problem occurs. */ public static void touch(final File file) throws IOException { PathUtils.touch(Objects.requireNonNull(file, "file").toPath()); } /** * Converts each element of an array of {@link File} to a {@link 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 any argument 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 NullPointerException if any of the given {@link File}s are {@code null}. * @throws FileNotFoundException if the 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 the file system to propagate a file creation, with a timeout. *

* This method repeatedly tests {@link Files#exists(Path, LinkOption...)} 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"); return PathUtils.waitFor(file.toPath(), Duration.ofSeconds(seconds), PathUtils.EMPTY_LINK_OPTION_ARRAY); } /** * 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 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 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); } /** * 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 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); } // Must be called with a directory /** * Writes a byte array to a file creating the file if it does not exist. * 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); } /** * 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 = newOutputStream(file, append)) { out.write(data, off, len); } } /** * Writes the {@code toString()} value of each item in a collection to * the specified {@link 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 {@link 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 {@link 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 {@link 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 {@link File} line by line. * The specified character encoding and the default line ending will be used. * 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 {@link 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 {@link File} line by line. * The specified character encoding and the line ending will be used. * 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 {@link 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(newOutputStream(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 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 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. * 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. * The parent directories of the file are 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 * @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 = newOutputStream(file, append)) { IOUtils.write(data, out, charset); } } /** * Writes a String to a file, creating the file if it does not exist. * The parent directories of the file are 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. * The parent directories of the file are 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 * @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 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 TODO Make private in 3.0. */ @Deprecated public FileUtils() { //NOSONAR // empty } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/FilenameUtils.java0100644 0000000 0000000 00000203627 14603604450 027153 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Stream; /** * General file name and file path manipulation utilities. The methods in this class * operate on strings that represent relative or absolute paths. Nothing in this class * ever accesses the file system, or depends on whether a path points to a file that exists. *

* 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, String) File(File,String)}. *

*

* Most methods in 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 backslashes), and both * sets of prefixes. See the Javadoc of each method for details. *

*

* This class defines six components within a path (sometimes called a file name or a full file name). * Given an absolute Windows path such as C:\dev\project\file.txt they are: *

*
    *
  • the full file name, or just file name - 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
  • *
*

* Given an absolute UNIX path such as /dev/project/file.txt they are: *

*
    *
  • the full file name, or just file name - /dev/project/file.txt
  • *
  • the prefix - /
  • *
  • the path - dev/project
  • *
  • the full path - /dev/project
  • *
  • the name - file.txt
  • *
  • the base name - file
  • *
  • the extension - txt
  • *
*

* Given a relative Windows path such as dev\project\file.txt they are: *

*
    *
  • the full file name, or just file name - dev\project\file.txt
  • *
  • the prefix - null
  • *
  • the path - dev\project\
  • *
  • the full path - dev\project\
  • *
  • the name - file.txt
  • *
  • the base name - file
  • *
  • the extension - txt
  • *
*

* Given an absolute UNIX path such as /dev/project/file.txt they are: *

*
    *
  • the full path, full file name, or just file name - /dev/project/file.txt
  • *
  • the prefix - /
  • *
  • the path - dev/project
  • *
  • the full path - /dev/project
  • *
  • the name - file.txt
  • *
  • the base name - file
  • *
  • the extension - txt
  • *
* * *

* This class works best if directory names end with a separator. * If you omit the last separator, it is impossible to determine if the last component * corresponds to a file or a directory. This class treats final components * that do not end with a separator as files, not directories. *

*

* 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, irrespective of the machine that you are * currently running on. *

* * @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_NAME_SEPARATOR = '/'; /** * The Windows separator character. */ private static final char WINDOWS_NAME_SEPARATOR = '\\'; /** * The system separator character. */ private static final char SYSTEM_NAME_SEPARATOR = File.separatorChar; /** * The separator character that is the opposite of the system separator. */ private static final char OTHER_SEPARATOR = flipSeparator(SYSTEM_NAME_SEPARATOR); 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; 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; private static final Pattern REG_NAME_PART_PATTERN = Pattern.compile("^[a-zA-Z0-9][a-zA-Z0-9-]*$"); /** * 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 [1]
     * /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 [2]
     * 
*

* [1] Note that the Windows relative drive prefix is unreliable when * used with this method. *

*

* [2] 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 file name (or path) to attach to the base * @return the concatenated path, or null if invalid * @throws IllegalArgumentException if the result path contains the null character ({@code U+0000}) */ 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} (a file or directory). * This does not read from the file system, and there is no guarantee or expectation that * these paths actually exist. *

* 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 path string to consider as the parent. * @param canonicalChild the path string to consider as the child. * @return true if the candidate leaf is under the specified composite. False otherwise. * @since 2.2 * @see FileUtils#directoryContains(File, File) */ public static boolean directoryContains(final String canonicalParent, final String canonicalChild) { if (isEmpty(canonicalParent) || isEmpty(canonicalChild)) { return false; } if (IOCase.SYSTEM.checkEquals(canonicalParent, canonicalChild)) { return false; } final char separator = toSeparator(canonicalParent.charAt(0) == UNIX_NAME_SEPARATOR); final String parentWithEndSeparator = canonicalParent.charAt(canonicalParent.length() - 1) == separator ? canonicalParent : canonicalParent + separator; return IOCase.SYSTEM.checkStartsWith(canonicalChild, parentWithEndSeparator); } /** * Does the work of getting the path. * * @param fileName the file name * @param includeSeparator true to include the end separator * @return the path * @throws IllegalArgumentException if the result path contains the null character ({@code U+0000}) */ 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); } /** * Does the work of getting the path. * * @param fileName the file name * @param separatorAdd 0 to omit the end separator, 1 to return it * @return the path * @throws IllegalArgumentException if the result path contains the null character ({@code U+0000}) */ 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; } return requireNonNullChars(fileName.substring(prefix, endIndex)); } /** * Internal method to perform the normalization. * * @param fileName the file name * @param separator The separator character to use * @param keepSeparator true to keep the final separator * @return the normalized fileName * @throws IllegalArgumentException if the file name contains the null character ({@code U+0000}) */ 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 = flipSeparator(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 } /** * Checks whether two file names are exactly equal. *

* No processing is performed on the file names other than comparison. * This is merely a null-safe case-sensitive string equality. *

* * @param fileName1 the first file name, may be null * @param fileName2 the second file name, may be null * @return true if the file names 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 file names are equal, optionally normalizing and providing * control over the case-sensitivity. * * @param fileName1 the first file name, may be null * @param fileName2 the second file name, may be null * @param normalize whether to normalize the file names * @param ioCase what case sensitivity rule to use, null means case-sensitive * @return true if the file names are equal, null equals null * @since 1.3 */ public static boolean equals(String fileName1, String fileName2, final boolean normalize, final IOCase ioCase) { if (fileName1 == null || fileName2 == null) { return fileName1 == null && fileName2 == null; } if (normalize) { fileName1 = normalize(fileName1); if (fileName1 == null) { return false; } fileName2 = normalize(fileName2); if (fileName2 == null) { return false; } } return IOCase.value(ioCase, IOCase.SENSITIVE).checkEquals(fileName1, fileName2); } /** * Checks whether two file names are equal after both have been normalized. *

* Both file names are first passed to {@link #normalize(String)}. * The check is then performed in a case-sensitive manner. *

* * @param fileName1 the first file name, may be null * @param fileName2 the second file name, may be null * @return true if the file names 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 file names are equal using the case rules of the system * after both have been normalized. *

* Both file names are first passed to {@link #normalize(String)}. * The check is then performed case-sensitively on UNIX and * case-insensitively on Windows. *

* * @param fileName1 the first file name, may be null * @param fileName2 the second file name, may be null * @return true if the file names 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 file names are equal using the case rules of the system. *

* No processing is performed on the file names other than comparison. * The check is case-sensitive on UNIX and case-insensitive on Windows. *

* * @param fileName1 the first file name, may be null * @param fileName2 the second file name, may be null * @return true if the file names 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); } /** * Flips the Windows name separator to Linux and vice-versa. * * @param ch The Windows or Linux name separator. * @return The Windows or Linux name separator. */ static char flipSeparator(final char ch) { if (ch == UNIX_NAME_SEPARATOR) { return WINDOWS_NAME_SEPARATOR; } if (ch == WINDOWS_NAME_SEPARATOR) { return UNIX_NAME_SEPARATOR; } throw new IllegalArgumentException(String.valueOf(ch)); } /** * Special handling for NTFS ADS: Don't accept colon in the file name. * * @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_NAME_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; } /** * Gets the base name, minus the full path and extension, from a full file name. *

* This method will handle a path 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\b\c.txt --> c
     * a/b/c.foo.txt --> c.foo
     * 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 file name, null returns null * @return the name of the file without the path, or an empty string if none exists * @throws IllegalArgumentException if the file name contains the null character ({@code U+0000}) */ 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 file name 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 throw * an {@link IllegalArgumentException} for names like this. *

* * @param fileName the file name to retrieve the extension of. * @return the extension of the file or an empty string if none exists or {@code null} * if the file name is {@code null}. * @throws IllegalArgumentException Windows only: the file name 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); } /** * Gets the full path (prefix + path) from a full file name. *

* 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 file name, null returns null * @return the path of the file, an empty string if none exists, null if invalid * @throws IllegalArgumentException if the result path contains the null character ({@code U+0000}) */ public static String getFullPath(final String fileName) { return doGetFullPath(fileName, true); } /** * Gets the full path (prefix + path) from a full file name, * 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 file name, null returns null * @return the path of the file, an empty string if none exists, null if invalid * @throws IllegalArgumentException if the result path contains the null character ({@code U+0000}) */ public static String getFullPathNoEndSeparator(final String fileName) { return doGetFullPath(fileName, false); } /** * Gets the name minus the path from a full file name. *

* 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\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 file name, null returns null * @return the name of the file without the path, or an empty string if none exists * @throws IllegalArgumentException if the file name contains the null character ({@code U+0000}) */ public static String getName(final String fileName) { if (fileName == null) { return null; } return requireNonNullChars(fileName).substring(indexOfLastSeparator(fileName) + 1); } /** * Gets the path from a full file name, which excludes the prefix and the name. *

* 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 file name, null returns null * @return the path of the file, an empty string if none exists, null if invalid * @throws IllegalArgumentException if the result path contains the null character ({@code U+0000}) */ public static String getPath(final String fileName) { return doGetPath(fileName, 1); } /** * Gets the path (which excludes the prefix) from a full file name, 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 file name, null returns null * @return the path of the file, an empty string if none exists, null if invalid * @throws IllegalArgumentException if the result path contains the null character ({@code U+0000}) */ public static String getPathNoEndSeparator(final String fileName) { return doGetPath(fileName, 0); } /** * Gets the prefix such as {@code C:/} or {@code ~/} from a full file name, *

* This method will handle a file in either UNIX or Windows format. * The prefix includes the first slash in the full file name 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 file name, null returns null * @return the prefix of the file, null if invalid * @throws IllegalArgumentException if the result contains the null character ({@code U+0000}) */ 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); return fileName + UNIX_NAME_SEPARATOR; } return requireNonNullChars(fileName.substring(0, len)); } /** * Returns the length of the file name 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 file name * 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 file name as only null character 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 file name. *

* * @param fileName the file name 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_NAME_SEPARATOR, 1); int posWin = fileName.indexOf(WINDOWS_NAME_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_NAME_SEPARATOR) { return 1; } return NOT_FOUND; } if (!isSeparator(ch0) || !isSeparator(ch1)) { return isSeparator(ch0) ? 1 : 0; } int posUnix = fileName.indexOf(UNIX_NAME_SEPARATOR, 2); int posWin = fileName.indexOf(WINDOWS_NAME_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 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 file name 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 file name 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 file name. 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; } /** * 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 file name 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_NAME_SEPARATOR); final int lastWindowsPos = fileName.lastIndexOf(WINDOWS_NAME_SEPARATOR); return Math.max(lastUnixPos, lastWindowsPos); } private static boolean isEmpty(final String string) { return string == null || string.isEmpty(); } /** * Checks whether the extension of the file name is one of those specified. *

* This method obtains the extension as the textual part of the file name * 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 file name, null returns false * @param extensions the extensions to check for, null checks for no extension * @return true if the file name is one of the extensions * @throws IllegalArgumentException if the file name contains the null character ({@code U+0000}) */ 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; } return extensions.contains(getExtension(fileName)); } /** * Checks whether the extension of the file name is that specified. *

* This method obtains the extension as the textual part of the file name * 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 file name, null returns false * @param extension the extension to check for, null or empty checks for no extension * @return true if the file name has the specified extension * @throws IllegalArgumentException if the file name contains the null character ({@code U+0000}) */ public static boolean isExtension(final String fileName, final String extension) { if (fileName == null) { return false; } requireNonNullChars(fileName); if (isEmpty(extension)) { return indexOfExtension(fileName) == NOT_FOUND; } return getExtension(fileName).equals(extension); } /** * Checks whether the extension of the file name is one of those specified. *

* This method obtains the extension as the textual part of the file name * 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 file name, null returns false * @param extensions the extensions to check for, null checks for no extension * @return true if the file name is one of the extensions * @throws IllegalArgumentException if the file name contains the null character ({@code U+0000}) */ 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); return Stream.of(extensions).anyMatch(fileExt::equals); } /** * 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; } // 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); } /** * 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; } /** * 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_NAME_SEPARATOR || ch == WINDOWS_NAME_SEPARATOR; } /** * Determines if Windows file system is in use. * * @return true if the system is Windows */ static boolean isSystemWindows() { return SYSTEM_NAME_SEPARATOR == WINDOWS_NAME_SEPARATOR; } /** * 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); } /** * 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, {@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 will be correct for Windows/Unix.) * * @param fileName the file name to normalize, null returns null * @return the normalized fileName, or null if invalid * @throws IllegalArgumentException if the file name contains the null character ({@code U+0000}) */ public static String normalize(final String fileName) { return doNormalize(fileName, SYSTEM_NAME_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 file name 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 * @throws IllegalArgumentException if the file name contains the null character ({@code U+0000}) * @since 2.0 */ public static String normalize(final String fileName, final boolean unixSeparator) { return doNormalize(fileName, toSeparator(unixSeparator), 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 file name to normalize, null returns null * @return the normalized fileName, or null if invalid * @throws IllegalArgumentException if the file name contains the null character ({@code U+0000}) */ public static String normalizeNoEndSeparator(final String fileName) { return doNormalize(fileName, SYSTEM_NAME_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 file name 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 * @throws IllegalArgumentException if the file name contains the null character ({@code U+0000}) * @since 2.0 */ public static String normalizeNoEndSeparator(final String fileName, final boolean unixSeparator) { return doNormalize(fileName, toSeparator(unixSeparator), false); } /** * Removes the extension from a fileName. *

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

     * foo.txt    --> foo
     * .txt       --> "" (empty string)
     * a\b\c.jpg  --> a\b\c
     * /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 file name, null returns null * @return the file name minus the extension * @throws IllegalArgumentException if the file name contains the null character ({@code U+0000}) */ 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 the input for null characters ({@code U+0000}), a sign of unsanitized data being passed to file level functions. * * This may be used to defend against poison byte attacks. * * @param path the path to check * @return The input * @throws IllegalArgumentException if path contains the null character ({@code U+0000}) */ private static String requireNonNullChars(final String path) { if (path.indexOf(0) >= 0) { throw new IllegalArgumentException( "Null character present in file/path name. There are no known legitimate use cases for such data, but several injection attacks may use it"); } return path; } /** * 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) { return FileSystem.getCurrent().normalizeSeparators(path); } /** * Converts all separators to the UNIX separator of forward slash. * * @param path the path to be changed, null ignored. * @return the new path. */ public static String separatorsToUnix(final String path) { return FileSystem.LINUX.normalizeSeparators(path); } /** * 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) { return FileSystem.WINDOWS.normalizeSeparators(path); } /** * 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); } /** * Returns '/' if given true, '\\' otherwise. * * @param unixSeparator which separator to return. * @return '/' if given true, '\\' otherwise. */ private static char toSeparator(final boolean unixSeparator) { return unixSeparator ? UNIX_NAME_SEPARATOR : WINDOWS_NAME_SEPARATOR; } /** * 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 file name to match on * @param wildcardMatcher the wildcard string to match against * @return true if the file name 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 * 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 file name to match on * @param wildcardMatcher the wildcard string to match against * @param ioCase what case sensitivity rule to use, null means case-sensitive * @return true if the file name matches the wildcard string * @since 1.3 */ public static boolean wildcardMatch(final String fileName, final String wildcardMatcher, IOCase ioCase) { if (fileName == null && wildcardMatcher == null) { return true; } if (fileName == null || wildcardMatcher == null) { return false; } ioCase = IOCase.value(ioCase, 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 = ioCase.checkIndexOf(fileName, textIdx, wcs[wcsIdx]); if (textIdx == NOT_FOUND) { // token not found break; } final int repeat = ioCase.checkIndexOf(fileName, textIdx + 1, wcs[wcsIdx]); if (repeat >= 0) { backtrack.push(new int[] {wcsIdx, repeat}); } } else if (!ioCase.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; } /** * 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 file name to match on * @param wildcardMatcher the wildcard string to match against * @return true if the file name matches the wildcard string * @see IOCase#SYSTEM */ public static boolean wildcardMatchOnSystem(final String fileName, final String wildcardMatcher) { return wildcardMatch(fileName, wildcardMatcher, IOCase.SYSTEM); } /** * Instances should NOT be constructed in standard programming. * * @deprecated TODO Make private in 3.0. */ @Deprecated public FilenameUtils() { // empty } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/HexDump.java0100644 0000000 0000000 00000021554 14603604450 025761 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.io.OutputStreamWriter; import java.nio.charset.Charset; import java.util.Objects; import org.apache.commons.io.output.CloseShieldOutputStream; /** * Dumps data in hexadecimal format. *

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

*

* Provenance: POI. *

*/ public class HexDump { /** * The line-separator (initializes to "line.separator" system property). * * @deprecated Use {@link System#lineSeparator()}. */ @Deprecated public static final String EOL = System.lineSeparator(); private static final char[] HEX_CODES = { '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 }; /** * Dumps an array of bytes to an Appendable. 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. * * @param data the byte array to be dumped * @param appendable the Appendable to which the data is to be written * * @throws IOException is thrown if anything goes wrong writing * the data to appendable * @throws NullPointerException if the output appendable is null * * @since 2.12.0 */ public static void dump(final byte[] data, final Appendable appendable) throws IOException { dump(data, 0, appendable, 0, data.length); } /** * Dumps an array of bytes to an Appendable. 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. *

* * @param data the byte array to be dumped * @param offset offset of the byte array within a larger entity * @param appendable the Appendable to which the data is to be written * @param index initial index into the byte array * @param length number of bytes to dump from the array * * @throws IOException is thrown if anything goes wrong writing * the data to appendable * @throws ArrayIndexOutOfBoundsException if the index or length is * outside the data array's bounds * @throws NullPointerException if the output appendable is null * * @since 2.12.0 */ public static void dump(final byte[] data, final long offset, final Appendable appendable, final int index, final int length) throws IOException, ArrayIndexOutOfBoundsException { Objects.requireNonNull(appendable, "appendable"); if (index < 0 || index >= data.length) { throw new ArrayIndexOutOfBoundsException( "illegal index: " + index + " into array of length " + data.length); } long display_offset = offset + index; final StringBuilder buffer = new StringBuilder(74); // TODO Use Objects.checkFromIndexSize(index, length, data.length) when upgrading to JDK9 if (length < 0 || index + length > data.length) { throw new ArrayIndexOutOfBoundsException(String.format("Range [%s, % 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(System.lineSeparator()); appendable.append(buffer); buffer.setLength(0); display_offset += chars_read; } } /** * Dumps 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 NullPointerException if the output stream is null */ @SuppressWarnings("resource") // Caller closes stream public static void dump(final byte[] data, final long offset, final OutputStream stream, final int index) throws IOException, ArrayIndexOutOfBoundsException { Objects.requireNonNull(stream, "stream"); try (OutputStreamWriter out = new OutputStreamWriter(CloseShieldOutputStream.wrap(stream), Charset.defaultCharset())) { dump(data, offset, out, index, data.length - index); } } /** * Dumps 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(HEX_CODES[value >> SHIFTS[j + 6] & 15]); } return _cbuffer; } /** * Dumps 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(HEX_CODES[(int) (value >> SHIFTS[j]) & 15]); } return _lbuffer; } /** * Instances should NOT be constructed in standard programming. */ public HexDump() { } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/IO.java0100644 0000000 0000000 00000002044 14603604450 024707 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; /** * Component-wide operations on Apache Commons IO. */ final class IO { /** * Clears any state, throughout Apache Commons IO. Handy for tests. */ static void clear() { IOUtils.clear(); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/IOCase.java0100644 0000000 0000000 00000022051 14603604450 025503 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; import java.util.stream.Stream; /** * 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", FileSystem.getCurrent().isCaseSensitive()); /** Serialization version. */ private static final long serialVersionUID = -6343169151696340687L; /** * Looks up an IOCase by 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) { return Stream.of(IOCase.values()).filter(ioCase -> ioCase.getName().equals(name)).findFirst() .orElseThrow(() -> new IllegalArgumentException("Illegal IOCase name: " + name)); } /** * Tests for cases sensitivity in a null-safe manner. * * @param ioCase an IOCase. * @return true if the input is non-null and {@link #isCaseSensitive()}. * @since 2.10.0 */ public static boolean isCaseSensitive(final IOCase ioCase) { return ioCase != null && ioCase.isCaseSensitive(); } /** * Returns the given value if not-null, the defaultValue if null. * * @param value the value to test. * @param defaultValue the default value. * @return the given value if not-null, the defaultValue if null. * @since 2.12.0 */ public static IOCase value(final IOCase value, final IOCase defaultValue) { return value != null ? value : defaultValue; } /** The enumeration name. */ private final String name; /** The sensitivity flag. */ private final transient boolean sensitive; /** * 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; } /** * 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); } /** * 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); } /** * 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. * @param str2 the second string to compare. * @return true if equal using the case rules. */ public boolean checkEquals(final String str1, final String str2) { return str1 == str2 || str1 != null && (sensitive ? str1.equals(str2) : str1.equalsIgnoreCase(str2)); } /** * 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. * @param strStartIndex the index to start at in str. * @param search the start to search for. * @return the first index of the search String, * -1 if no match or {@code null} string input. * @since 2.0 */ public int checkIndexOf(final String str, final int strStartIndex, final String search) { if (str != null && search != null) { 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. * @param strStartIndex the index to start at in str. * @param search the start to search for,. * @return true if equal using the case rules. */ public boolean checkRegionMatches(final String str, final int strStartIndex, final String search) { return str != null && search != null && str.regionMatches(!sensitive, strStartIndex, search, 0, search.length()); } /** * 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()); } /** * 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; } /** * 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 a string describing the sensitivity. * * @return a string describing the sensitivity. */ @Override public String toString() { return name; } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/IOExceptionList.java0100644 0000000 0000000 00000011157 14603604450 027427 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Objects; /** * An 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 implements Iterable { private static final long serialVersionUID = 1L; /** * Throws this exception if the list is not null or empty. * * @param causeList The list to test. * @param message The detail message, see {@link #getMessage()}. * @throws IOExceptionList if the list is not null or empty. * @since 2.12.0 */ public static void checkEmpty(final List causeList, final Object message) throws IOExceptionList { if (!isEmpty(causeList)) { throw new IOExceptionList(Objects.toString(message, null), causeList); } } private static boolean isEmpty(final List causeList) { return size(causeList) == 0; } private static int size(final List causeList) { return causeList != null ? causeList.size() : 0; } private static String toMessage(final List causeList) { return String.format("%,d exception(s): %s", size(causeList), causeList); } /** * List of causes. */ private final List causeList; /** * Constructs a new exception caused by a list of exceptions. * * @param causeList a list of cause exceptions. */ public IOExceptionList(final List causeList) { this(toMessage(causeList), causeList); } /** * Constructs 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 != null ? message : toMessage(causeList), isEmpty(causeList) ? 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(getCause(index)); } /** * Gets the cause list. * * @param type of exception to return. * @return The list of causes. */ public List getCauseList() { return (List) new ArrayList<>(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) new ArrayList<>(causeList); } @Override public Iterator iterator() { return getCauseList().iterator(); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/IOExceptionWithCause.java0100644 0000000 0000000 00000004354 14603604450 030411 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.16.1-src/src/main/java/org/apache/commons/io/IOIndexedException.java0100644 0000000 0000000 00000004155 14603604450 030074 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; /** * 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); } /** * Index. */ private final int index; /** * Constructs 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; } /** * The index of this exception. * * @return index of this exception. */ public int getIndex() { return index; } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/IOUtils.java0100644 0000000 0000000 00000450736 14603604450 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.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.UncheckedIOException; 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.Channels; import java.nio.channels.ReadableByteChannel; import java.nio.channels.Selector; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Objects; import java.util.function.Consumer; import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.Stream; import java.util.zip.InflaterInputStream; import org.apache.commons.io.function.IOConsumer; import org.apache.commons.io.function.IOSupplier; import org.apache.commons.io.function.IOTriFunction; import org.apache.commons.io.input.QueueInputStream; 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.NullWriter; 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. *

*
    *
  • 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 {@link BufferedInputStream} * or {@link 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. *

*

* Provenance: 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, intended for both reading and writing. */ private static final ThreadLocal SCRATCH_BYTE_BUFFER_RW = ThreadLocal.withInitial(IOUtils::byteArray); /** * Internal byte array buffer, intended for write only operations. */ private static final byte[] SCRATCH_BYTE_BUFFER_WO = byteArray(); /** * Internal char array buffer, intended for both reading and writing. */ private static final ThreadLocal SCRATCH_CHAR_BUFFER_RW = ThreadLocal.withInitial(IOUtils::charArray); /** * Internal char array buffer, intended for write only operations. */ private static final char[] SCRATCH_CHAR_BUFFER_WO = 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. * @throws NegativeArraySizeException if the size is negative. * @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]; } /** * Clears any state. *
    *
  • Removes the current thread's value for thread-local variables.
  • *
  • Sets static scratch arrays to 0s.
  • *
* @see IO#clear() */ static void clear() { SCRATCH_BYTE_BUFFER_RW.remove(); SCRATCH_CHAR_BUFFER_RW.remove(); Arrays.fill(SCRATCH_BYTE_BUFFER_WO, (byte) 0); Arrays.fill(SCRATCH_CHAR_BUFFER_WO, (char) 0); } /** * 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}s as null-safe operations. * * @param closeables The resource(s) to close, may be null. * @throws IOExceptionList if an I/O error occurs. * @since 2.8.0 */ public static void close(final Closeable... closeables) throws IOExceptionList { IOConsumer.forAll(IOUtils::close, closeables); } /** * 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(); } } /** * Avoids the need to type cast. * * @param closeable the object to close, may be null */ private static void closeQ(final Closeable closeable) { closeQuietly(closeable, null); } /** * Closes a {@link 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(Throwable) */ public static void closeQuietly(final Closeable closeable) { closeQuietly(closeable, null); } /** * Closes a {@link 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(Throwable) */ public static void closeQuietly(final Closeable... closeables) { if (closeables != null) { closeQuietly(Arrays.stream(closeables)); } } /** * 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 {@link 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(Throwable) */ public static void closeQuietly(final InputStream input) { closeQ(input); } /** * Closes an iterable of {@link Closeable} unconditionally. *

* Equivalent calling {@link Closeable#close()} on each element, except any exceptions will be ignored. *

* * @param closeables the objects to close, may be null or already closed * @see #closeQuietly(Closeable) * @since 2.12.0 */ public static void closeQuietly(final Iterable closeables) { if (closeables != null) { closeables.forEach(IOUtils::closeQuietly); } } /** * Closes an {@link 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(Throwable) */ public static void closeQuietly(final OutputStream output) { closeQ(output); } /** * Closes an {@link 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(Throwable) */ public static void closeQuietly(final Reader reader) { closeQ(reader); } /** * Closes a {@link 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(Throwable) */ public static void closeQuietly(final Selector selector) { closeQ(selector); } /** * Closes a {@link 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(Throwable) */ public static void closeQuietly(final ServerSocket serverSocket) { closeQ(serverSocket); } /** * Closes a {@link 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(Throwable) */ public static void closeQuietly(final Socket socket) { closeQ(socket); } /** * Closes a stream of {@link Closeable} unconditionally. *

* Equivalent calling {@link Closeable#close()} on each element, except any exceptions will be ignored. *

* * @param closeables the objects to close, may be null or already closed * @see #closeQuietly(Closeable) * @since 2.12.0 */ public static void closeQuietly(final Stream closeables) { if (closeables != null) { closeables.forEach(IOUtils::closeQuietly); } } /** * Closes an {@link 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(Throwable) */ public static void closeQuietly(final Writer writer) { closeQ(writer); } /** * Consumes bytes from a {@link InputStream} and ignores them. *

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

* * @param input the {@link 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 IOException if an I/O error occurs. * @since 2.8.0 */ public static long consume(final InputStream input) throws IOException { return copyLarge(input, NullOutputStream.INSTANCE); } /** * Consumes characters from a {@link Reader} and ignores them. *

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

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

* This method buffers the input internally using * {@link 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 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 = getScratchByteArray(); // 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; } } } } // TODO Consider making public private static boolean contentEquals(final Iterator iterator1, final Iterator iterator2) { while (iterator1.hasNext()) { if (!iterator2.hasNext()) { return false; } if (!Objects.equals(iterator1.next(), iterator2.next())) { return false; } } return !iterator2.hasNext(); } /** * Compares the contents of two Readers to determine if they are equal or not. *

* This method buffers the input internally using {@link 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 = getScratchCharArray(); // 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; } } } } // TODO Consider making public private static boolean contentEquals(final Stream stream1, final Stream stream2) { if (stream1 == stream2) { return true; } if (stream1 == null || stream2 == null) { return false; } return contentEquals(stream1.iterator(), stream2.iterator()); } // TODO Consider making public private static boolean contentEqualsIgnoreEOL(final BufferedReader reader1, final BufferedReader reader2) { if (reader1 == reader2) { return true; } if (reader1 == null || reader2 == null) { return false; } return contentEquals(reader1.lines(), reader2.lines()); } /** * Compares the contents of two Readers to determine if they are equal or * not, ignoring EOL characters. *

* This method buffers the input internally using * {@link 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 UncheckedIOException if an I/O error occurs * @since 2.2 */ @SuppressWarnings("resource") public static boolean contentEqualsIgnoreEOL(final Reader reader1, final Reader reader2) throws UncheckedIOException { if (reader1 == reader2) { return true; } if (reader1 == null || reader2 == null) { return false; } return contentEqualsIgnoreEOL(toBufferedReader(reader1), toBufferedReader(reader2)); } /** * Copies bytes from an {@link InputStream} to an {@link OutputStream}. *

* This method buffers the input internally, so there is no need to use a {@link 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 * {@link #copyLarge(InputStream, OutputStream)} method. *

* * @param inputStream the {@link InputStream} to read. * @param outputStream the {@link 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); return count > Integer.MAX_VALUE ? EOF : (int) count; } /** * Copies bytes from an {@link InputStream} to an {@link OutputStream} using an internal buffer of the * given size. *

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

* * @param inputStream the {@link InputStream} to read. * @param outputStream the {@link 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 {@link InputStream} to chars on a * {@link Writer} using the default character encoding of the platform. *

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

*

* This method uses {@link InputStreamReader}. *

* * @param input the {@link InputStream} to read * @param writer the {@link 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 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 {@link InputStream} to chars on a * {@link Writer} using the specified character encoding. *

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

*

* This method uses {@link InputStreamReader}. *

* * @param input the {@link InputStream} to read * @param writer the {@link 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 {@link InputStream} to chars on a * {@link Writer} using the specified character encoding. *

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

*

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

*

* This method uses {@link InputStreamReader}. *

* * @param input the {@link InputStream} to read * @param writer the {@link 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 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 bytes from a {@link java.io.ByteArrayOutputStream} to a {@link QueueInputStream}. *

* Unlike using JDK {@link java.io.PipedInputStream} and {@link java.io.PipedOutputStream} for this, this * solution works safely in a single thread environment. *

*

* Example usage: *

* *
     * ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
     * outputStream.writeBytes("hello world".getBytes(StandardCharsets.UTF_8));
     *
     * InputStream inputStream = IOUtils.copy(outputStream);
     * 
* * @param outputStream the {@link java.io.ByteArrayOutputStream} to read. * @return the {@link QueueInputStream} filled with the content of the outputStream. * @throws NullPointerException if the {@link java.io.ByteArrayOutputStream} is {@code null}. * @throws IOException if an I/O error occurs. * @since 2.12 */ @SuppressWarnings("resource") // streams are closed by the caller. public static QueueInputStream copy(final java.io.ByteArrayOutputStream outputStream) throws IOException { Objects.requireNonNull(outputStream, "outputStream"); final QueueInputStream in = new QueueInputStream(); outputStream.writeTo(in.newQueueOutputStream()); return in; } /** * Copies chars from a {@link Reader} to a {@link Appendable}. *

* This method buffers the input internally, so there is no need to use a * {@link 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 {@link #copyLarge(Reader, Writer)} method. *

* * @param reader the {@link Reader} to read * @param output the {@link 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 {@link Reader} to an {@link Appendable}. *

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

* * @param reader the {@link Reader} to read * @param output the {@link 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 {@link Reader} to bytes on an * {@link 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 * {@link BufferedReader}. *

*

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

*

* This method uses {@link OutputStreamWriter}. *

* * @param reader the {@link Reader} to read * @param output the {@link 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 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 {@link Reader} to bytes on an * {@link OutputStream} using the specified character encoding, and * calling flush. *

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

*

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

*

* This method uses {@link OutputStreamWriter}. *

* * @param reader the {@link Reader} to read * @param output the {@link 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 {@link Reader} to bytes on an * {@link OutputStream} using the specified character encoding, and * calling flush. *

* This method buffers the input internally, so there is no need to use a * {@link 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 {@link Reader} to read * @param output the {@link 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 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 {@link Reader} to a {@link Writer}. *

* This method buffers the input internally, so there is no need to use a * {@link 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 {@link #copyLarge(Reader, Writer)} method. *

* * @param reader the {@link Reader} to read. * @param writer the {@link 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 {@link URL} to an {@link OutputStream}. *

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

*

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

* * @param url the {@link URL} to read. * @param file the {@link 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 {@link URL} to an {@link OutputStream}. *

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

*

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

* * @param url the {@link URL} to read. * @param outputStream the {@link 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) {@link InputStream} to an * {@link OutputStream}. *

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

*

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

* * @param inputStream the {@link InputStream} to read. * @param outputStream the {@link 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) {@link InputStream} to an * {@link OutputStream}. *

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

* * @param inputStream the {@link InputStream} to read. * @param outputStream the {@link 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) {@link InputStream} to an * {@link OutputStream}, optionally skipping input bytes. *

* This method buffers the input internally, so there is no need to use a * {@link 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 {@link InputStream} to read * @param output the {@link 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, getScratchByteArray()); } /** * Copies some or all bytes from a large (over 2GB) {@link InputStream} to an * {@link OutputStream}, optionally skipping input bytes. *

* This method uses the provided buffer, so there is no need to use a * {@link 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 {@link InputStream} to read * @param output the {@link 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) {@link Reader} to a {@link Writer}. *

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

*

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

* * @param reader the {@link Reader} to source. * @param writer the {@link 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, getScratchCharArray()); } /** * Copies chars from a large (over 2GB) {@link Reader} to a {@link Writer}. *

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

* * @param reader the {@link Reader} to source. * @param writer the {@link 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) {@link InputStream} to an * {@link OutputStream}, optionally skipping input chars. *

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

*

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

* * @param reader the {@link Reader} to read * @param writer the {@link 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, getScratchCharArray()); } /** * Copies some or all chars from a large (over 2GB) {@link InputStream} to an * {@link OutputStream}, optionally skipping input chars. *

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

* * @param reader the {@link Reader} to read * @param writer the {@link 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; } /** * Fills the given array with 0s. * * @param arr The non-null array to fill. * @return The given array. */ private static byte[] fill0(final byte[] arr) { Arrays.fill(arr, (byte) 0); return arr; } /** * Fills the given array with 0s. * * @param arr The non-null array to fill. * @return The given array. */ private static char[] fill0(final char[] arr) { Arrays.fill(arr, (char) 0); return arr; } /** * Gets the internal byte array buffer, intended for both reading and writing. * * @return the internal byte array buffer, intended for both reading and writing. */ static byte[] getScratchByteArray() { return fill0(SCRATCH_BYTE_BUFFER_RW.get()); } /** * Gets the internal byte array intended for write only operations. * * @return the internal byte array intended for write only operations. */ static byte[] getScratchByteArrayWriteOnly() { return fill0(SCRATCH_BYTE_BUFFER_WO); } /** * Gets the char byte array buffer, intended for both reading and writing. * * @return the char byte array buffer, intended for both reading and writing. */ static char[] getScratchCharArray() { return fill0(SCRATCH_CHAR_BUFFER_RW.get()); } /** * Gets the internal char array intended for write only operations. * * @return the internal char array intended for write only operations. */ static char[] getScratchCharArrayWriteOnly() { return fill0(SCRATCH_CHAR_BUFFER_WO); } /** * 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 {@link InputStream}, using * the character encoding specified (or default encoding if null). *

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

*

* 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 {@link InputStream} to read, 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 {@link InputStream}, using * the character encoding specified (or default encoding if null). *

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

*

* The recommended usage pattern is: *

*
     * try {
     *   LineIterator it = IOUtils.lineIterator(stream, StandardCharsets.UTF_8.name());
     *   while (it.hasNext()) {
     *     String line = it.nextLine();
     *     /// do something with line
     *   }
     * } finally {
     *   IOUtils.closeQuietly(stream);
     * }
     * 
* * @param input the {@link InputStream} to read, 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 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 {@link Reader}. *

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

*

* 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 {@link Reader} to read, not null * @return an Iterator of the lines in the reader, never null * @throws NullPointerException 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 * @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 IllegalArgumentException if length is negative * @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) { return 0; } return read(input::read, buffer, offset, length); } /** * Reads bytes from an input. 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 How to read input * @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 IllegalArgumentException if length is negative * @throws IOException if a read error occurs * @since 2.2 */ static int read(final IOTriFunction 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.apply(buffer, offset + location, remaining); if (EOF == count) { 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 IllegalArgumentException if length is negative * @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 = 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 {@link 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 * {@link BufferedInputStream}. *

* * @param input the {@link InputStream} to read, not null * @return the list of Strings, never null * @throws NullPointerException if the input is null * @throws UncheckedIOException if an I/O error occurs * @since 1.1 * @deprecated Use {@link #readLines(InputStream, Charset)} instead */ @Deprecated public static List readLines(final InputStream input) throws UncheckedIOException { return readLines(input, Charset.defaultCharset()); } /** * Gets the contents of an {@link 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 * {@link BufferedInputStream}. *

* * @param input the {@link InputStream} to read, 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 UncheckedIOException if an I/O error occurs * @since 2.3 */ public static List readLines(final InputStream input, final Charset charset) throws UncheckedIOException { return readLines(new InputStreamReader(input, Charsets.toCharset(charset))); } /** * Gets the contents of an {@link 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 * {@link BufferedInputStream}. *

* * @param input the {@link InputStream} to read, 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 UncheckedIOException if an I/O error occurs * @throws java.nio.charset.UnsupportedCharsetException if the encoding is not supported * @since 1.1 */ public static List readLines(final InputStream input, final String charsetName) throws UncheckedIOException { return readLines(input, Charsets.toCharset(charsetName)); } /** * Gets the contents of a {@link Reader} as a list of Strings, * one entry per line. *

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

* * @param reader the {@link Reader} to read, not null * @return the list of Strings, never null * @throws NullPointerException if the input is null * @throws UncheckedIOException 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 UncheckedIOException { return toBufferedReader(reader).lines().collect(Collectors.toList()); } /** * Gets the contents of a resource as a byte array. *

* Delegates to {@link #resourceToByteArray(String, ClassLoader) resourceToByteArray(String, null)}. *

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

* Delegates to {@link #resourceToURL(String, ClassLoader)}. *

* * @param name The resource name. * @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 or the resource is not found. * @see #resourceToURL(String, ClassLoader) * @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 resource as a String using the specified character encoding. *

* Delegates to {@link #resourceToString(String, Charset, ClassLoader) resourceToString(String, Charset, null)}. *

* * @param name The resource name. * @param charset the charset to use, null means platform default * @return the requested String * @throws IOException if an I/O error occurs or the resource is not found. * @see #resourceToString(String, Charset, ClassLoader) * @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 resource as a String using the specified character encoding. *

* Delegates to {@link #resourceToURL(String, ClassLoader)}. *

* * @param name The resource name. * @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. * @see #resourceToURL(String, ClassLoader) * @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 resource. *

* Delegates to {@link #resourceToURL(String, ClassLoader) resourceToURL(String, null)}. *

* * @param name The resource name. * @return A URL object for reading the resource. * @throws IOException if the resource is not found. * @since 2.6 */ public static URL resourceToURL(final String name) throws IOException { return resourceToURL(name, null); } /** * Gets a URL pointing to the given resource. *

* If the {@code classLoader} is not null, call {@link ClassLoader#getResource(String)}, otherwise call * {@link Class#getResource(String) IOUtils.class.getResource(name)}. *

* * @param name The resource name. * @param classLoader Delegate to this class loader if not null * @return A URL object for reading the resource. * @throws IOException if the resource is not found. * @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 { return skip(input, toSkip, IOUtils::getScratchByteArrayWriteOnly); } /** * Skips bytes from an input byte stream. *

* Intended for special cases when customization of the temporary buffer is needed because, for example, a nested input stream has requirements for the * bytes read. For example, when using {@link InflaterInputStream}s from multiple threads. *

*

* 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. * @param skipBufferSupplier Supplies the buffer to use for reading. * @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.14.0 */ public static long skip(final InputStream input, final long toSkip, final Supplier skipBufferSupplier) throws IOException { if (toSkip < 0) { throw new IllegalArgumentException("Skip count must be non-negative, actual: " + toSkip); } // // No need to synchronize access to SCRATCH_BYTE_BUFFER_WO: We don't care if the buffer is written multiple // times or in parallel since the data is ignored. We reuse the same buffer, if the buffer size were variable or read-write, // we would need to synch or use a thread local to ensure some other thread safety. // long remain = toSkip; while (remain > 0) { final byte[] skipBuffer = skipBufferSupplier.get(); // See https://issues.apache.org/jira/browse/IO-203 for why we use read() rather than delegating to skip() final long n = input.read(skipBuffer, 0, (int) Math.min(remain, skipBuffer.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 = getScratchCharArrayWriteOnly(); 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 { final long skipped = skip(input, toSkip, IOUtils::getScratchByteArrayWriteOnly); 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. *

* Intended for special cases when customization of the temporary buffer is needed because, for example, a nested input stream has requirements for the * bytes read. For example, when using {@link InflaterInputStream}s from multiple threads. *

*

* 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 * @param skipBufferSupplier Supplies the buffer to use for reading. * @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.14.0 */ public static void skipFully(final InputStream input, final long toSkip, final Supplier skipBufferSupplier) throws IOException { if (toSkip < 0) { throw new IllegalArgumentException("Bytes to skip must not be negative: " + toSkip); } final long skipped = skip(input, toSkip, skipBufferSupplier); 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 {@link 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 * {@link 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 {@link 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 * {@link 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 {@link InputStream} as a {@code byte[]}. *

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

* * @param inputStream the {@link 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 (UnsynchronizedByteArrayOutputStream ubaOutput = UnsynchronizedByteArrayOutputStream.builder().get(); ThresholdingOutputStream thresholdOutput = 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, thresholdOutput); return ubaOutput.toByteArray(); } } /** * Gets the contents of an {@link InputStream} as a {@code byte[]}. Use this method instead of * {@link #toByteArray(InputStream)} when {@link InputStream} size is known. * * @param input the {@link InputStream} to read. * @param size the size of {@link InputStream} to read, where 0 < {@code size} <= length of input stream. * @return byte [] of length {@code size}. * @throws IOException if an I/O error occurs or {@link InputStream} length is smaller than parameter {@code size}. * @throws IllegalArgumentException if {@code size} is less than zero. * @since 2.1 */ public static byte[] toByteArray(final InputStream input, final int size) throws IOException { if (size == 0) { return EMPTY_BYTE_ARRAY; } return toByteArray(Objects.requireNonNull(input, "input")::read, size); } /** * Gets contents of an {@link InputStream} as a {@code byte[]}. * Use this method instead of {@link #toByteArray(InputStream)} * when {@link 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(InputStream, int)} to read into the byte array. * (Arrays can have no more than Integer.MAX_VALUE entries anyway) * * @param input the {@link InputStream} to read * @param size the size of {@link InputStream} to read, where 0 < {@code size} <= min(Integer.MAX_VALUE, length of input stream). * @return byte [] the requested byte array, of length {@code size} * @throws IOException if an I/O error occurs or {@link InputStream} length is less than {@code size} * @throws IllegalArgumentException if size is less than zero or size is greater than Integer.MAX_VALUE * @see IOUtils#toByteArray(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 an input as a {@code byte[]}. * * @param input the input to read. * @param size the size of the input to read, where 0 < {@code size} <= length of input. * @return byte [] of length {@code size}. * @throws IOException if an I/O error occurs or input length is smaller than parameter {@code size}. * @throws IllegalArgumentException if {@code size} is less than zero. */ static byte[] toByteArray(final IOTriFunction 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 = byteArray(size); int offset = 0; int read; while (offset < size && (read = input.apply(data, offset, size - offset)) != EOF) { offset += read; } if (offset != size) { throw new IOException("Unexpected read size, current: " + offset + ", expected: " + size); } return data; } /** * Gets the contents of a {@link 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 * {@link BufferedReader}. *

* * @param reader the {@link Reader} to read * @return the requested byte array * @throws NullPointerException if the input is null * @throws IOException if an I/O error occurs * @deprecated 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 {@link Reader} as a {@code byte[]} * using the specified character encoding. *

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

* * @param reader the {@link Reader} to read * @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 (ByteArrayOutputStream output = new ByteArrayOutputStream()) { copy(reader, output, charset); return output.toByteArray(); } } /** * Gets the contents of a {@link 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 * {@link BufferedReader}. *

* * @param reader the {@link Reader} to read * @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 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 {@link String} as a {@code byte[]} * using the default character encoding of the platform. *

* This is the same as {@link String#getBytes()}. *

* * @param input the {@link String} to convert * @return the requested byte array * @throws NullPointerException if the input is null * @deprecated 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 {@link URI} as a {@code byte[]}. * * @param uri the {@link 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 toByteArray(uri.toURL()); } /** * Gets the contents of a {@link URL} as a {@code byte[]}. * * @param url the {@link 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 { try (CloseableURLConnection urlConnection = CloseableURLConnection.open(url)) { return toByteArray(urlConnection); } } /** * Gets the contents of a {@link URLConnection} as a {@code byte[]}. * * @param urlConnection the {@link 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 urlConnection) throws IOException { try (InputStream inputStream = urlConnection.getInputStream()) { return toByteArray(inputStream); } } /** * Gets the contents of an {@link 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 * {@link BufferedInputStream}. *

* * @param inputStream the {@link InputStream} to read * @return the requested character array * @throws NullPointerException if the input is null * @throws IOException if an I/O error occurs * @since 1.1 * @deprecated 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 {@link InputStream} as a character array * using the specified character encoding. *

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

* * @param inputStream the {@link InputStream} to read * @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 {@link 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 * {@link BufferedInputStream}. *

* * @param inputStream the {@link InputStream} to read * @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 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 {@link Reader} as a character array. *

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

* * @param reader the {@link Reader} to read * @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 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 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 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 if the encoding is not supported * @since 1.1 */ public static InputStream toInputStream(final String input, final String charsetName) { return new ByteArrayInputStream(input.getBytes(Charsets.toCharset(charsetName))); } /** * 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 * @return the requested String * @throws NullPointerException if the input is null * @deprecated 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 * @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 {@link 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 * {@link BufferedInputStream}. *

* * @param input the {@link InputStream} to read * @return the requested String * @throws NullPointerException if the input is null * @throws IOException if an I/O error occurs * @deprecated 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 {@link InputStream} as a String * using the specified character encoding. *

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

* * @param input the {@link InputStream} to read * @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 (StringBuilderWriter sw = new StringBuilderWriter()) { copy(input, sw, charset); return sw.toString(); } } /** * Gets the contents of an {@link 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 * {@link BufferedInputStream}. *

* * @param input the {@link InputStream} to read * @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 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 an {@link InputStream} from a supplier as a String * using the specified character encoding. *

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

* * @param input supplies the {@link InputStream} to read * @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.12.0 */ public static String toString(final IOSupplier input, final Charset charset) throws IOException { return toString(input, charset, () -> { throw new NullPointerException("input"); }); } /** * Gets the contents of an {@link InputStream} from a supplier as a String * using the specified character encoding. *

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

* * @param input supplies the {@link InputStream} to read * @param charset the charset to use, null means platform default * @param defaultString the default return value if the supplier or its value is null. * @return the requested String * @throws NullPointerException if the input is null * @throws IOException if an I/O error occurs * @since 2.12.0 */ public static String toString(final IOSupplier input, final Charset charset, final IOSupplier defaultString) throws IOException { if (input == null) { return defaultString.get(); } try (InputStream inputStream = input.get()) { return inputStream != null ? toString(inputStream, charset) : defaultString.get(); } } /** * Gets the contents of a {@link Reader} as a String. *

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

* * @param reader the {@link Reader} to read * @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 (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 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 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 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 { return toString(url::openStream, 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 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 {@link OutputStream}. * * @param data the byte array to write, do not modify during output, * null ignored * @param output the {@link 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 {@link 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 {@link Writer} to write to * @throws NullPointerException if output is null * @throws IOException if an I/O error occurs * @since 1.1 * @deprecated 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 {@link 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 {@link 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 {@link 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 {@link 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 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 * {@link 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 {@link OutputStream} to write to * @throws NullPointerException if output is null * @throws IOException if an I/O error occurs * @since 1.1 * @deprecated 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 * {@link 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 {@link 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) { write(new String(data), output, charset); } } /** * Writes chars from a {@code char[]} to bytes on an * {@link 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 {@link 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 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 {@link Writer} * * @param data the char array to write, do not modify during output, * null ignored * @param writer the {@link 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 {@link CharSequence} to bytes on an * {@link OutputStream} using the default character encoding of the * platform. *

* This method uses {@link String#getBytes()}. *

* * @param data the {@link CharSequence} to write, null ignored * @param output the {@link OutputStream} to write to * @throws NullPointerException if output is null * @throws IOException if an I/O error occurs * @since 2.0 * @deprecated 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 {@link CharSequence} to bytes on an * {@link OutputStream} using the specified character encoding. *

* This method uses {@link String#getBytes(String)}. *

* * @param data the {@link CharSequence} to write, null ignored * @param output the {@link 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 {@link CharSequence} to bytes on an * {@link OutputStream} using the specified character encoding. *

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

*

* This method uses {@link String#getBytes(String)}. *

* * @param data the {@link CharSequence} to write, null ignored * @param output the {@link 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 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 {@link CharSequence} to a {@link Writer}. * * @param data the {@link CharSequence} to write, null ignored * @param writer the {@link 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 {@link String} to bytes on an * {@link OutputStream} using the default character encoding of the * platform. *

* This method uses {@link String#getBytes()}. *

* * @param data the {@link String} to write, null ignored * @param output the {@link OutputStream} to write to * @throws NullPointerException if output is null * @throws IOException if an I/O error occurs * @since 1.1 * @deprecated 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 {@link String} to bytes on an * {@link OutputStream} using the specified character encoding. *

* This method uses {@link String#getBytes(String)}. *

* * @param data the {@link String} to write, null ignored * @param output the {@link 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 */ @SuppressWarnings("resource") public static void write(final String data, final OutputStream output, final Charset charset) throws IOException { if (data != null) { // Use Charset#encode(String), since calling String#getBytes(Charset) might result in // NegativeArraySizeException or OutOfMemoryError. // The underlying OutputStream should not be closed, so the channel is not closed. Channels.newChannel(output).write(Charsets.toCharset(charset).encode(data)); } } /** * Writes chars from a {@link String} to bytes on an * {@link OutputStream} using the specified character encoding. *

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

*

* This method uses {@link String#getBytes(String)}. *

* * @param data the {@link String} to write, null ignored * @param output the {@link 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 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 {@link String} to a {@link Writer}. * * @param data the {@link String} to write, null ignored * @param writer the {@link 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 {@link StringBuffer} to bytes on an * {@link OutputStream} using the default character encoding of the * platform. *

* This method uses {@link String#getBytes()}. *

* * @param data the {@link StringBuffer} to write, null ignored * @param output the {@link OutputStream} to write to * @throws NullPointerException if output is null * @throws IOException if an I/O error occurs * @since 1.1 * @deprecated Use {@link #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 {@link StringBuffer} to bytes on an * {@link OutputStream} using the specified character encoding. *

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

*

* This method uses {@link String#getBytes(String)}. *

* * @param data the {@link StringBuffer} to write, null ignored * @param output the {@link 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 if the encoding is not supported * @since 1.1 * @deprecated Use {@link #write(CharSequence, OutputStream, String)}. */ @Deprecated public static void write(final StringBuffer data, final OutputStream output, final String charsetName) //NOSONAR throws IOException { if (data != null) { write(data.toString(), output, Charsets.toCharset(charsetName)); } } /** * Writes chars from a {@link StringBuffer} to a {@link Writer}. * * @param data the {@link StringBuffer} to write, null ignored * @param writer the {@link Writer} to write to * @throws NullPointerException if output is null * @throws IOException if an I/O error occurs * @since 1.1 * @deprecated Use {@link #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 {@link 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 {@link 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 {@link 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 {@link 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 {@link #toString()} value of each item in a collection to * an {@link 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 {@link 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 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 {@link #toString()} value of each item in a collection to * an {@link OutputStream} line by line, using the specified character * encoding and the specified line ending. *

* UTF-16 is written big-endian with no byte order mark. * For little-endian, use UTF-16LE. For a BOM, write it to the stream * before calling this method. *

* * @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 {@link OutputStream} to write to, not null, not closed * @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 writeLines(final Collection lines, String lineEnding, final OutputStream output, Charset charset) throws IOException { if (lines == null) { return; } if (lineEnding == null) { lineEnding = System.lineSeparator(); } if (StandardCharsets.UTF_16.equals(charset)) { // don't write a BOM charset = StandardCharsets.UTF_16BE; } final byte[] eolBytes = lineEnding.getBytes(charset); for (final Object line : lines) { if (line != null) { write(line.toString(), output, charset); } output.write(eolBytes); } } /** * Writes the {@link #toString()} value of each item in a collection to * an {@link 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 {@link 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 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 {@link #toString()} value of each item in a collection to * a {@link 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 {@link 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. * * @deprecated TODO Make private in 3.0. */ @Deprecated public IOUtils() { //NOSONAR // empty } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/LineIterator.java0100644 0000000 0000000 00000013566 14603604450 027014 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; import java.util.Objects; /** * An Iterator over the lines in a {@link Reader}. *

* {@link LineIterator} holds a reference to an open {@link 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, StandardCharsets.UTF_8.name());
 * 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 /** * Closes a {@link 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(Throwable) */ @Deprecated public static void closeQuietly(final LineIterator iterator) { IOUtils.closeQuietly(iterator); } /** 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 {@link Reader}. * * @param reader the {@link Reader} to read from, not null * @throws NullPointerException if the reader is null */ @SuppressWarnings("resource") // Caller closes Reader public LineIterator(final Reader reader) { Objects.requireNonNull(reader, "reader"); if (reader instanceof BufferedReader) { bufferedReader = (BufferedReader) reader; } else { bufferedReader = new BufferedReader(reader); } } /** * Closes the underlying {@link 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 {@link Reader} remains open. * This method can safely be called multiple times. * * @throws IOException if closing the underlying {@link Reader} fails. */ @Override public void close() throws IOException { finished = true; cachedLine = null; IOUtils.close(bufferedReader); } /** * Indicates whether the {@link Reader} has more lines. * If there is an {@link 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 {@link 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 {@link 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; } /** * Unsupported. * * @throws UnsupportedOperationException always */ @Override public void remove() { throw new UnsupportedOperationException("remove not supported"); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/RandomAccessFileMode.java0100644 0000000 0000000 00000006607 14603604450 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; import java.io.File; import java.io.FileNotFoundException; import java.io.RandomAccessFile; import java.nio.file.Path; import java.util.Objects; /** * Access modes and factory methods for {@link RandomAccessFile}. * * @since 2.12.0 */ public enum RandomAccessFileMode { /** * Mode {@code "r"} opens for reading only. */ READ_ONLY("r"), /** * Mode {@code "rw"} opens for reading and writing. */ READ_WRITE("rw"), /** * Mode {@code "rws"} opens for reading and writing, as with {@code "rw"}, and also require that every update to the file's content or metadata be written * synchronously to the underlying storage device. */ READ_WRITE_SYNC_ALL("rws"), /** * Mode {@code "rwd"} open for reading and writing, as with {@code "rw"}, and also require that every update to the file's content be written synchronously * to the underlying storage device. */ READ_WRITE_SYNC_CONTENT("rwd"); private final String mode; RandomAccessFileMode(final String mode) { this.mode = mode; } /** * Constructs a random access file stream to read from, and optionally to write to, the file specified by the {@link File} * argument. * * @param file the file object * @return a random access file stream * @throws FileNotFoundException See {@link RandomAccessFile#RandomAccessFile(File, String)}. */ public RandomAccessFile create(final File file) throws FileNotFoundException { return new RandomAccessFile(file, mode); } /** * Constructs a random access file stream to read from, and optionally to write to, the file specified by the {@link File} * argument. * * @param file the file object * @return a random access file stream * @throws FileNotFoundException See {@link RandomAccessFile#RandomAccessFile(File, String)}. */ public RandomAccessFile create(final Path file) throws FileNotFoundException { return create(Objects.requireNonNull(file.toFile(), "file")); } /** * Constructs a random access file stream to read from, and optionally to write to, the file specified by the {@link File} * argument. * * @param file the file object * @return a random access file stream * @throws FileNotFoundException See {@link RandomAccessFile#RandomAccessFile(File, String)}. */ public RandomAccessFile create(final String file) throws FileNotFoundException { return new RandomAccessFile(file, mode); } @Override public String toString() { return mode; } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/RandomAccessFiles.java0100644 0000000 0000000 00000007465 14603604450 027741 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.RandomAccessFile; import java.nio.channels.FileChannel; import java.util.Objects; import org.apache.commons.io.channels.FileChannels; /** * Works with {@link RandomAccessFile}. * * @since 2.13.0 */ public class RandomAccessFiles { /** * Tests if two RandomAccessFile contents are equal. * * @param raf1 A RandomAccessFile. * @param raf2 Another RandomAccessFile. * @return true if the contents of both RandomAccessFiles are equal, false otherwise. * @throws IOException if an I/O error occurs. * @since 2.15.0 */ @SuppressWarnings("resource") // See comments public static boolean contentEquals(final RandomAccessFile raf1, final RandomAccessFile raf2) throws IOException { // Short-circuit test if (Objects.equals(raf1, raf2)) { return true; } // Short-circuit test final long length1 = length(raf1); final long length2 = length(raf2); if (length1 != length2) { return false; } if (length1 == 0 && length2 == 0) { return true; } // Dig in and to the work // We do not close FileChannels because that closes the owning RandomAccessFile. // Instead, the caller is assumed to manage the given RandomAccessFile objects. final FileChannel channel1 = raf1.getChannel(); final FileChannel channel2 = raf2.getChannel(); return FileChannels.contentEquals(channel1, channel2, IOUtils.DEFAULT_BUFFER_SIZE); } private static long length(final RandomAccessFile raf) throws IOException { return raf != null ? raf.length() : 0; } /** * Reads a byte array starting at "position" for "length" bytes. * * @param input The source RandomAccessFile. * @param position The offset position, measured in bytes from the beginning of the file, at which to set the file pointer. * @param length How many bytes to read. * @return a new byte array. * @throws IOException If the first byte cannot be read for any reason other than end of file, or if the random access file has been closed, or if some * other I/O error occurs. */ public static byte[] read(final RandomAccessFile input, final long position, final int length) throws IOException { input.seek(position); return IOUtils.toByteArray(input::read, length); } /** * Resets the given file to position 0. * * @param raf The RandomAccessFile to reset. * @return The given RandomAccessFile. * @throws IOException If {@code pos} is less than {@code 0} or if an I/O error occurs. * @since 2.15.0 */ public static RandomAccessFile reset(final RandomAccessFile raf) throws IOException { raf.seek(0); return raf; } /** * Make private in 3.0. * * @deprecated TODO Make private in 3.0. */ @Deprecated public RandomAccessFiles() { // empty } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/StandardLineSeparator.java0100644 0000000 0000000 00000004261 14603604450 030634 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.16.1-src/src/main/java/org/apache/commons/io/StreamIterator.java0100644 0000000 0000000 00000006044 14603604450 027351 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.Iterator; import java.util.Objects; import java.util.stream.Stream; /** * Wraps and presents a {@link Stream} as a {@link AutoCloseable} {@link Iterator} 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 this iterator until the end. *

* * @param The {@link Stream} and {@link Iterator} type. * @since 2.15.0 */ public final class StreamIterator implements Iterator, AutoCloseable { /** * 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 this iterator until the end. *

* * @param The stream and iterator type. * @param stream The stream iterate. * @return A new iterator. */ public static StreamIterator iterator(final Stream stream) { return new StreamIterator<>(stream); } /** * The given stream's Iterator. */ private final Iterator iterator; /** * The given stream. */ private final Stream stream; /** * Whether {@link #close()} has been called. */ private boolean closed; private StreamIterator(final Stream stream) { this.stream = Objects.requireNonNull(stream, "stream"); this.iterator = stream.iterator(); } /** * Closes the underlying stream. */ @Override public void close() { closed = true; stream.close(); } @Override public boolean hasNext() { if (closed) { // Calling Iterator#hasNext() on a closed java.nio.file.FileTreeIterator causes an IllegalStateException. return false; } 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; } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/TaggedIOException.java0100644 0000000 0000000 00000010766 14603604450 027714 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; /** * Constructs 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 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(); } /** * Returns the serializable tag object. * * @return tag object */ public Serializable getTag() { return tag; } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/ThreadMonitor.java0100644 0000000 0000000 00000006724 14603604450 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 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. *

* *
 * Duration timeout = Duration.ofSeconds(1);
 * try {
 *     Thread monitor = ThreadMonitor.start(timeout);
 *     // do some work here
 *     ThreadMonitor.stop(monitor);
 * } catch (InterruptedException e) {
 *     // timed amount was reached
 * }
 * 
*/ final class ThreadMonitor implements Runnable { /** * Starts monitoring the current thread. * * @param timeout The timeout amount. 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); } /** * Starts monitoring the specified thread. * * @param thread The thread to monitor * @param timeout The timeout amount. 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 Thread monitor = new Thread(new ThreadMonitor(thread, timeout), ThreadMonitor.class.getSimpleName()); monitor.setDaemon(true); monitor.start(); return monitor; } /** * Stops monitoring the specified thread. * * @param thread The monitor thread, may be {@code null}. */ static void stop(final Thread thread) { if (thread != null) { thread.interrupt(); } } private final Thread thread; private final Duration timeout; /** * Constructs a new monitor. * * @param thread The thread to monitor. * @param timeout The timeout amount. */ private ThreadMonitor(final Thread thread, final Duration timeout) { this.thread = thread; this.timeout = timeout; } /** * Sleeps until the specified timeout amount and then interrupt the thread being monitored. * * @see Runnable#run() */ @Override public void run() { try { ThreadUtils.sleep(timeout); thread.interrupt(); } catch (final InterruptedException e) { // timeout not reached } } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/ThreadUtils.java0100644 0000000 0000000 00000004345 14603604450 026636 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; import java.time.Instant; /** * Helps work with threads. * * @since 2.12.0 */ public final class ThreadUtils { private static int getNanosOfMilli(final Duration duration) { return duration.getNano() % 1_000_000; } /** * 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 * {@link Thread#sleep(long, int)}} for further interesting details. *

* * @param duration the sleep duration. * @throws InterruptedException if interrupted * @see Thread#sleep(long, int) */ public static void sleep(final Duration duration) throws InterruptedException { // Using this method avoids depending on the vagaries of the precision and accuracy of system timers and schedulers. final Instant finishInstant = Instant.now().plus(duration); Duration remainingDuration = duration; do { Thread.sleep(remainingDuration.toMillis(), getNanosOfMilli(remainingDuration)); remainingDuration = Duration.between(Instant.now(), finishInstant); } while (!remainingDuration.isNegative()); } /** * Make private in 3.0. * * @deprecated TODO Make private in 3.0. */ @Deprecated public ThreadUtils() { // empty } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/UncheckedIOExceptions.java0100644 0000000 0000000 00000004231 14603604450 030563 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.UncheckedIOException; import java.util.Objects; /** * Helps use lambdas that throw {@link IOException} rethrow as {@link UncheckedIOException}. * * @since 2.12.0 */ final class UncheckedIOExceptions { /** * Constructs a new UncheckedIOException for the given detail message. *

* This method exists because there is no String constructor in {@link UncheckedIOException}. *

* * @param message the detail message. * @return a new {@link UncheckedIOException}. */ public static UncheckedIOException create(final Object message) { final String string = Objects.toString(message); return new UncheckedIOException(string, new IOException(string)); } /** * Constructs a new UncheckedIOException for the given detail message. *

* This method exists because there is no String constructor in {@link UncheckedIOException}. *

* @param e cause the {@link IOException}. * @param message the detail message. * * @return a new {@link UncheckedIOException}. */ public static UncheckedIOException wrap(final IOException e, final Object message) { return new UncheckedIOException(Objects.toString(message), e); } private UncheckedIOExceptions() { // no instance } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/build/AbstractOrigin.java0100644 0000000 0000000 00000046273 14603604450 030426 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.build; 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.io.OutputStreamWriter; import java.io.RandomAccessFile; import java.io.Reader; import java.io.Writer; import java.net.URI; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.OpenOption; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; import java.util.Objects; import org.apache.commons.io.IOUtils; import org.apache.commons.io.RandomAccessFileMode; import org.apache.commons.io.RandomAccessFiles; import org.apache.commons.io.input.CharSequenceInputStream; import org.apache.commons.io.input.CharSequenceReader; import org.apache.commons.io.input.ReaderInputStream; import org.apache.commons.io.output.WriterOutputStream; /** * Abstracts the origin of data for builders like a {@link File}, {@link Path}, {@link Reader}, {@link Writer}, {@link InputStream}, {@link OutputStream}, and * {@link URI}. *

* Some methods may throw {@link UnsupportedOperationException} if that method is not implemented in a concrete subclass, see {@link #getFile()} and * {@link #getPath()}. *

* * @param the type of instances to build. * @param the type of builder subclass. * @since 2.12.0 */ public abstract class AbstractOrigin> extends AbstractSupplier { /** * A {@code byte[]} origin. */ public static class ByteArrayOrigin extends AbstractOrigin { /** * Constructs a new instance for the given origin. * * @param origin The origin. */ public ByteArrayOrigin(final byte[] origin) { super(origin); } @Override public byte[] getByteArray() { // No conversion return get(); } /** * {@inheritDoc} *

* The {@code options} parameter is ignored since a {@code byte[]} does not need an {@link OpenOption} to be read. *

*/ @Override public InputStream getInputStream(final OpenOption... options) throws IOException { return new ByteArrayInputStream(origin); } @Override public Reader getReader(final Charset charset) throws IOException { return new InputStreamReader(getInputStream(), charset); } @Override public long size() throws IOException { return origin.length; } } /** * A {@link CharSequence} origin. */ public static class CharSequenceOrigin extends AbstractOrigin { /** * Constructs a new instance for the given origin. * * @param origin The origin. */ public CharSequenceOrigin(final CharSequence origin) { super(origin); } @Override public byte[] getByteArray() { // TODO Pass in a Charset? Consider if call sites actually need this. return origin.toString().getBytes(Charset.defaultCharset()); } /** * {@inheritDoc} *

* The {@code charset} parameter is ignored since a {@link CharSequence} does not need a {@link Charset} to be read. *

*/ @Override public CharSequence getCharSequence(final Charset charset) { // No conversion return get(); } /** * {@inheritDoc} *

* The {@code options} parameter is ignored since a {@link CharSequence} does not need an {@link OpenOption} to be read. *

*/ @Override public InputStream getInputStream(final OpenOption... options) throws IOException { // TODO Pass in a Charset? Consider if call sites actually need this. return CharSequenceInputStream.builder().setCharSequence(getCharSequence(Charset.defaultCharset())).get(); } /** * {@inheritDoc} *

* The {@code charset} parameter is ignored since a {@link CharSequence} does not need a {@link Charset} to be read. *

*/ @Override public Reader getReader(final Charset charset) throws IOException { return new CharSequenceReader(get()); } @Override public long size() throws IOException { return origin.length(); } } /** * A {@link File} origin. *

* Starting from this origin, you can get a byte array, a file, an input stream, an output stream, a path, a reader, and a writer. *

*/ public static class FileOrigin extends AbstractOrigin { /** * Constructs a new instance for the given origin. * * @param origin The origin. */ public FileOrigin(final File origin) { super(origin); } @Override public byte[] getByteArray(final long position, final int length) throws IOException { try (RandomAccessFile raf = RandomAccessFileMode.READ_ONLY.create(origin)) { return RandomAccessFiles.read(raf, position, length); } } @Override public File getFile() { // No conversion return get(); } @Override public Path getPath() { return get().toPath(); } } /** * An {@link InputStream} origin. *

* This origin cannot provide some of the other aspects. *

*/ public static class InputStreamOrigin extends AbstractOrigin { /** * Constructs a new instance for the given origin. * * @param origin The origin. */ public InputStreamOrigin(final InputStream origin) { super(origin); } @Override public byte[] getByteArray() throws IOException { return IOUtils.toByteArray(origin); } /** * {@inheritDoc} *

* The {@code options} parameter is ignored since a {@link InputStream} does not need an {@link OpenOption} to be read. *

*/ @Override public InputStream getInputStream(final OpenOption... options) { // No conversion return get(); } @Override public Reader getReader(final Charset charset) throws IOException { return new InputStreamReader(getInputStream(), charset); } } /** * An {@link OutputStream} origin. *

* This origin cannot provide some of the other aspects. *

*/ public static class OutputStreamOrigin extends AbstractOrigin { /** * Constructs a new instance for the given origin. * * @param origin The origin. */ public OutputStreamOrigin(final OutputStream origin) { super(origin); } /** * {@inheritDoc} *

* The {@code options} parameter is ignored since a {@link OutputStream} does not need an {@link OpenOption} to be written. *

*/ @Override public OutputStream getOutputStream(final OpenOption... options) { // No conversion return get(); } /** * {@inheritDoc} *

* The {@code options} parameter is ignored since a {@link OutputStream} does not need an {@link OpenOption} to be written. *

*/ @Override public Writer getWriter(final Charset charset, final OpenOption... options) throws IOException { return new OutputStreamWriter(origin, charset); } } /** * A {@link Path} origin. *

* Starting from this origin, you can get a byte array, a file, an input stream, an output stream, a path, a reader, and a writer. *

*/ public static class PathOrigin extends AbstractOrigin { /** * Constructs a new instance for the given origin. * * @param origin The origin. */ public PathOrigin(final Path origin) { super(origin); } @Override public byte[] getByteArray(final long position, final int length) throws IOException { try (RandomAccessFile raf = RandomAccessFileMode.READ_ONLY.create(origin)) { return RandomAccessFiles.read(raf, position, length); } } @Override public File getFile() { return get().toFile(); } @Override public Path getPath() { // No conversion return get(); } } /** * An {@link Reader} origin. *

* This origin cannot provide other aspects. *

*/ public static class ReaderOrigin extends AbstractOrigin { /** * Constructs a new instance for the given origin. * * @param origin The origin. */ public ReaderOrigin(final Reader origin) { super(origin); } @Override public byte[] getByteArray() throws IOException { // TODO Pass in a Charset? Consider if call sites actually need this. return IOUtils.toByteArray(origin, Charset.defaultCharset()); } /** * {@inheritDoc} *

* The {@code charset} parameter is ignored since a {@link Reader} does not need a {@link Charset} to be read. *

*/ @Override public CharSequence getCharSequence(final Charset charset) throws IOException { return IOUtils.toString(origin); } /** * {@inheritDoc} *

* The {@code options} parameter is ignored since a {@link Reader} does not need an {@link OpenOption} to be read. *

*/ @Override public InputStream getInputStream(final OpenOption... options) throws IOException { // TODO Pass in a Charset? Consider if call sites actually need this. return ReaderInputStream.builder().setReader(origin).setCharset(Charset.defaultCharset()).get(); } /** * {@inheritDoc} *

* The {@code charset} parameter is ignored since a {@link Reader} does not need a {@link Charset} to be read. *

*/ @Override public Reader getReader(final Charset charset) throws IOException { // No conversion return get(); } } /** * A {@link URI} origin. */ public static class URIOrigin extends AbstractOrigin { /** * Constructs a new instance for the given origin. * * @param origin The origin. */ public URIOrigin(final URI origin) { super(origin); } @Override public File getFile() { return getPath().toFile(); } @Override public Path getPath() { return Paths.get(get()); } } /** * An {@link Writer} origin. *

* This origin cannot provide other aspects. *

*/ public static class WriterOrigin extends AbstractOrigin { /** * Constructs a new instance for the given origin. * * @param origin The origin. */ public WriterOrigin(final Writer origin) { super(origin); } /** * {@inheritDoc} *

* The {@code options} parameter is ignored since a {@link Writer} does not need an {@link OpenOption} to be written. *

*/ @Override public OutputStream getOutputStream(final OpenOption... options) throws IOException { // TODO Pass in a Charset? Consider if call sites actually need this. return WriterOutputStream.builder().setWriter(origin).setCharset(Charset.defaultCharset()).get(); } /** * {@inheritDoc} *

* The {@code charset} parameter is ignored since a {@link Writer} does not need a {@link Charset} to be written. *

*

* The {@code options} parameter is ignored since a {@link Writer} does not need an {@link OpenOption} to be written. *

*/ @Override public Writer getWriter(final Charset charset, final OpenOption... options) throws IOException { // No conversion return get(); } } /** * The non-null origin. */ final T origin; /** * Constructs a new instance for a subclass. * * @param origin The origin. */ protected AbstractOrigin(final T origin) { this.origin = Objects.requireNonNull(origin, "origin"); } /** * Gets the origin. * * @return the origin. */ @Override public T get() { return origin; } /** * Gets this origin as a byte array, if possible. * * @return this origin as a byte array, if possible. * @throws IOException if an I/O error occurs. * @throws UnsupportedOperationException if the origin cannot be converted to a Path. */ public byte[] getByteArray() throws IOException { return Files.readAllBytes(getPath()); } /** * Gets this origin as a byte array, if possible. * * @param position the initial index of the range to be copied, inclusive. * @param length How many bytes to copy. * @return this origin as a byte array, if possible. * @throws UnsupportedOperationException if the origin cannot be converted to a Path. * @throws ArithmeticException if the {@code position} overflows an int * @throws IOException if an I/O error occurs. * @since 2.13.0 */ public byte[] getByteArray(final long position, final int length) throws IOException { final byte[] bytes = getByteArray(); // Checks for int overflow. final int start = Math.toIntExact(position); if (start < 0 || length < 0 || start + length < 0 || start + length > bytes.length) { throw new IllegalArgumentException("Couldn't read array (start: " + start + ", length: " + length + ", data length: " + bytes.length + ")."); } return Arrays.copyOfRange(bytes, start, start + length); } /** * Gets this origin as a byte array, if possible. * * @param charset The charset to use if conversion from bytes is needed. * @return this origin as a byte array, if possible. * @throws IOException if an I/O error occurs. * @throws UnsupportedOperationException if the origin cannot be converted to a Path. */ public CharSequence getCharSequence(final Charset charset) throws IOException { return new String(getByteArray(), charset); } /** * Gets this origin as a Path, if possible. * * @return this origin as a Path, if possible. * @throws UnsupportedOperationException if this method is not implemented in a concrete subclass. */ public File getFile() { throw new UnsupportedOperationException( String.format("%s#getFile() for %s origin %s", getSimpleName(), origin.getClass().getSimpleName(), origin)); } /** * Gets this origin as an InputStream, if possible. * * @param options options specifying how the file is opened * @return this origin as an InputStream, if possible. * @throws IOException if an I/O error occurs. * @throws UnsupportedOperationException if the origin cannot be converted to a Path. */ public InputStream getInputStream(final OpenOption... options) throws IOException { return Files.newInputStream(getPath(), options); } /** * Gets this origin as an OutputStream, if possible. * * @param options options specifying how the file is opened * @return this origin as an OutputStream, if possible. * @throws IOException if an I/O error occurs. * @throws UnsupportedOperationException if the origin cannot be converted to a Path. */ public OutputStream getOutputStream(final OpenOption... options) throws IOException { return Files.newOutputStream(getPath(), options); } /** * Gets this origin as a Path, if possible. * * @return this origin as a Path, if possible. * @throws UnsupportedOperationException if this method is not implemented in a concrete subclass. */ public Path getPath() { throw new UnsupportedOperationException( String.format("%s#getPath() for %s origin %s", getSimpleName(), origin.getClass().getSimpleName(), origin)); } /** * Gets a new Reader on the origin, buffered by default. * * @param charset the charset to use for decoding * @return a new Reader on the origin. * @throws IOException if an I/O error occurs opening the file. */ public Reader getReader(final Charset charset) throws IOException { return Files.newBufferedReader(getPath(), charset); } private String getSimpleName() { return getClass().getSimpleName(); } /** * Gets a new Writer on the origin, buffered by default. * * @param charset the charset to use for encoding * @param options options specifying how the file is opened * @return a new Writer on the origin. * @throws IOException if an I/O error occurs opening or creating the file. * @throws UnsupportedOperationException if the origin cannot be converted to a Path. */ public Writer getWriter(final Charset charset, final OpenOption... options) throws IOException { return Files.newBufferedWriter(getPath(), charset, options); } /** * Gets the size of the origin, if possible. * * @return the size of the origin in bytes or characters. * @throws IOException if an I/O error occurs. * @since 2.13.0 */ public long size() throws IOException { return Files.size(getPath()); } @Override public String toString() { return getSimpleName() + "[" + origin.toString() + "]"; } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/build/AbstractOriginSupplier.java0100644 0000000 0000000 00000020210 14603604450 032131 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.build; import java.io.File; import java.io.InputStream; import java.io.OutputStream; import java.io.Reader; import java.io.Writer; import java.net.URI; import java.nio.file.Path; import java.nio.file.Paths; import org.apache.commons.io.build.AbstractOrigin.ByteArrayOrigin; import org.apache.commons.io.build.AbstractOrigin.CharSequenceOrigin; import org.apache.commons.io.build.AbstractOrigin.FileOrigin; import org.apache.commons.io.build.AbstractOrigin.InputStreamOrigin; import org.apache.commons.io.build.AbstractOrigin.OutputStreamOrigin; import org.apache.commons.io.build.AbstractOrigin.PathOrigin; import org.apache.commons.io.build.AbstractOrigin.ReaderOrigin; import org.apache.commons.io.build.AbstractOrigin.URIOrigin; import org.apache.commons.io.build.AbstractOrigin.WriterOrigin; /** * Abstracts building an instance of {@code T}. * * @param the type of instances to build. * @param the type of builder subclass. * @since 2.12.0 */ public abstract class AbstractOriginSupplier> extends AbstractSupplier { /** * Constructs a new byte array origin for a byte array. * * @param origin the byte array. * @return a new byte array origin. */ protected static ByteArrayOrigin newByteArrayOrigin(final byte[] origin) { return new ByteArrayOrigin(origin); } /** * Constructs a new CharSequence origin for a CharSequence. * * @param origin the CharSequence. * @return a new file origin. * @since 2.13.0 */ protected static CharSequenceOrigin newCharSequenceOrigin(final CharSequence origin) { return new CharSequenceOrigin(origin); } /** * Constructs a new file origin for a file. * * @param origin the file. * @return a new file origin. */ protected static FileOrigin newFileOrigin(final File origin) { return new FileOrigin(origin); } /** * Constructs a new file origin for a file path. * * @param origin the file path. * @return a new file origin. */ protected static FileOrigin newFileOrigin(final String origin) { return new FileOrigin(new File(origin)); } /** * Constructs a new input stream origin for a file. * * @param origin the input stream. * @return a new input stream origin. */ protected static InputStreamOrigin newInputStreamOrigin(final InputStream origin) { return new InputStreamOrigin(origin); } /** * Constructs a new output stream origin for a file. * * @param origin the output stream. * @return a new output stream origin. */ protected static OutputStreamOrigin newOutputStreamOrigin(final OutputStream origin) { return new OutputStreamOrigin(origin); } /** * Constructs a new path origin for a file. * * @param origin the path. * @return a new path origin. */ protected static PathOrigin newPathOrigin(final Path origin) { return new PathOrigin(origin); } /** * Constructs a new path name origin for a path name. * * @param origin the path name. * @return a new path name origin. */ protected static PathOrigin newPathOrigin(final String origin) { return new PathOrigin(Paths.get(origin)); } /** * Constructs a new reader origin for a reader. * * @param origin the reader. * @return a new reader origin. */ protected static ReaderOrigin newReaderOrigin(final Reader origin) { return new ReaderOrigin(origin); } /** * Constructs a new reader origin for a URI. * * @param origin the URI. * @return a new URI origin. */ protected static URIOrigin newURIOrigin(final URI origin) { return new URIOrigin(origin); } /** * Constructs a new writer origin for a file. * * @param origin the writer. * @return a new writer . */ protected static WriterOrigin newWriterOrigin(final Writer origin) { return new WriterOrigin(origin); } /** * The underlying origin. */ private AbstractOrigin origin; /** * Checks whether the origin is null. * * @return the origin. * @throws IllegalStateException if the {@code origin} is {@code null}. */ protected AbstractOrigin checkOrigin() { if (origin == null) { throw new IllegalStateException("origin == null"); } return origin; } /** * Gets the origin. * * @return the origin. */ protected AbstractOrigin getOrigin() { return origin; } /** * Tests whether the origin is null. * * @return whether the origin is null. */ protected boolean hasOrigin() { return origin != null; } /** * Sets a new origin. * * @param origin the new origin. * @return this */ public B setByteArray(final byte[] origin) { return setOrigin(newByteArrayOrigin(origin)); } /** * Sets a new origin. * * @param origin the new origin. * @return this * @since 2.13.0 */ public B setCharSequence(final CharSequence origin) { return setOrigin(newCharSequenceOrigin(origin)); } /** * Sets a new origin. * * @param origin the new origin. * @return this */ public B setFile(final File origin) { return setOrigin(newFileOrigin(origin)); } /** * Sets a new origin. * * @param origin the new origin. * @return this */ public B setFile(final String origin) { return setOrigin(newFileOrigin(origin)); } /** * Sets a new origin. * * @param origin the new origin. * @return this */ public B setInputStream(final InputStream origin) { return setOrigin(newInputStreamOrigin(origin)); } /** * Sets a new origin. * * @param origin the new origin. * @return this */ protected B setOrigin(final AbstractOrigin origin) { this.origin = origin; return asThis(); } /** * Sets a new origin. * * @param origin the new origin. * @return this */ public B setOutputStream(final OutputStream origin) { return setOrigin(newOutputStreamOrigin(origin)); } /** * Sets a new origin. * * @param origin the new origin. * @return this */ public B setPath(final Path origin) { return setOrigin(newPathOrigin(origin)); } /** * Sets a new origin. * * @param origin the new origin. * @return this */ public B setPath(final String origin) { return setOrigin(newPathOrigin(origin)); } /** * Sets a new origin. * * @param origin the new origin. * @return this */ public B setReader(final Reader origin) { return setOrigin(newReaderOrigin(origin)); } /** * Sets a new origin. * * @param origin the new origin. * @return this */ public B setURI(final URI origin) { return setOrigin(newURIOrigin(origin)); } /** * Sets a new origin. * * @param origin the new origin. * @return this */ public B setWriter(final Writer origin) { return setOrigin(newWriterOrigin(origin)); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/build/AbstractStreamBuilder.java0100644 0000000 0000000 00000027456 14603604450 031743 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.build; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.Reader; import java.io.Writer; import java.nio.charset.Charset; import java.nio.file.OpenOption; import java.nio.file.Path; import java.util.function.IntUnaryOperator; import org.apache.commons.io.Charsets; import org.apache.commons.io.IOUtils; import org.apache.commons.io.file.PathUtils; /** * Abstracts building a typed instance of {@code T}. * * @param the type of instances to build. * @param the type of builder subclass. * @since 2.12.0 */ public abstract class AbstractStreamBuilder> extends AbstractOriginSupplier { private static final int DEFAULT_MAX_VALUE = Integer.MAX_VALUE; private static final OpenOption[] DEFAULT_OPEN_OPTIONS = PathUtils.EMPTY_OPEN_OPTION_ARRAY; /** * The buffer size, defaults to {@link IOUtils#DEFAULT_BUFFER_SIZE} ({@value IOUtils#DEFAULT_BUFFER_SIZE}). */ private int bufferSize = IOUtils.DEFAULT_BUFFER_SIZE; /** * The buffer size, defaults to {@link IOUtils#DEFAULT_BUFFER_SIZE} ({@value IOUtils#DEFAULT_BUFFER_SIZE}). */ private int bufferSizeDefault = IOUtils.DEFAULT_BUFFER_SIZE; /** * The maximum buffer size. */ private int bufferSizeMax = DEFAULT_MAX_VALUE; /** * The Charset, defaults to {@link Charset#defaultCharset()}. */ private Charset charset = Charset.defaultCharset(); /** * The Charset, defaults to {@link Charset#defaultCharset()}. */ private Charset charsetDefault = Charset.defaultCharset(); private OpenOption[] openOptions = DEFAULT_OPEN_OPTIONS; /** * The default checking behavior for a buffer size request. Throws a {@link IllegalArgumentException} by default. */ private final IntUnaryOperator defaultSizeChecker = size -> size > bufferSizeMax ? throwIae(size, bufferSizeMax) : size; /** * The checking behavior for a buffer size request. */ private IntUnaryOperator bufferSizeChecker = defaultSizeChecker; /** * Applies the buffer size request. * * @param size the size request. * @return the size to use, usually the input, or can throw an unchecked exception, like {@link IllegalArgumentException}. */ private int checkBufferSize(final int size) { return bufferSizeChecker.applyAsInt(size); } /** * Gets the buffer size, defaults to {@link IOUtils#DEFAULT_BUFFER_SIZE} ({@value IOUtils#DEFAULT_BUFFER_SIZE}). * * @return the buffer size, defaults to {@link IOUtils#DEFAULT_BUFFER_SIZE} ({@value IOUtils#DEFAULT_BUFFER_SIZE}). */ protected int getBufferSize() { return bufferSize; } /** * Gets the buffer size default, defaults to {@link IOUtils#DEFAULT_BUFFER_SIZE} ({@value IOUtils#DEFAULT_BUFFER_SIZE}). * * @return the buffer size default, defaults to {@link IOUtils#DEFAULT_BUFFER_SIZE} ({@value IOUtils#DEFAULT_BUFFER_SIZE}). */ protected int getBufferSizeDefault() { return bufferSizeDefault; } /** * Gets a CharSequence from the origin with a Charset. * * @return An input stream * @throws IllegalStateException if the {@code origin} is {@code null}. * @throws UnsupportedOperationException if the origin cannot be converted to a CharSequence. * @throws IOException if an I/O error occurs. * @see AbstractOrigin#getCharSequence(Charset) * @since 2.13.0 */ protected CharSequence getCharSequence() throws IOException { return checkOrigin().getCharSequence(getCharset()); } /** * Gets the Charset, defaults to {@link Charset#defaultCharset()}. * * @return the Charset, defaults to {@link Charset#defaultCharset()}. */ public Charset getCharset() { return charset; } /** * Gets the Charset default, defaults to {@link Charset#defaultCharset()}. * * @return the Charset default, defaults to {@link Charset#defaultCharset()}. */ protected Charset getCharsetDefault() { return charsetDefault; } /** * Gets an InputStream from the origin with OpenOption[]. * * @return An input stream * @throws IllegalStateException if the {@code origin} is {@code null}. * @throws UnsupportedOperationException if the origin cannot be converted to an {@link InputStream}. * @throws IOException if an I/O error occurs. * @see AbstractOrigin#getInputStream(OpenOption...) * @see #getOpenOptions() * @since 2.13.0 */ protected InputStream getInputStream() throws IOException { return checkOrigin().getInputStream(getOpenOptions()); } /** * Gets the OpenOption array. * * @return the OpenOption array. */ protected OpenOption[] getOpenOptions() { return openOptions; } /** * Gets an OutputStream from the origin with OpenOption[]. * * @return An OutputStream * @throws IllegalStateException if the {@code origin} is {@code null}. * @throws UnsupportedOperationException if the origin cannot be converted to an {@link OutputStream}. * @throws IOException if an I/O error occurs. * @see AbstractOrigin#getOutputStream(OpenOption...) * @see #getOpenOptions() * @since 2.13.0 */ protected OutputStream getOutputStream() throws IOException { return checkOrigin().getOutputStream(getOpenOptions()); } /** * Gets a Path from the origin. * * @return A Path * @throws IllegalStateException if the {@code origin} is {@code null}. * @throws UnsupportedOperationException if the origin cannot be converted to a {@link Path}. * @see AbstractOrigin#getPath() * @since 2.13.0 */ protected Path getPath() { return checkOrigin().getPath(); } /** * Gets a Reader from the origin with a Charset. * * @return A Reader * @throws IllegalStateException if the {@code origin} is {@code null}. * @throws UnsupportedOperationException if the origin cannot be converted to a {@link Reader}. * @throws IOException if an I/O error occurs. * @see AbstractOrigin#getReader(Charset) * @see #getCharset() * @since 2.16.0 */ protected Reader getReader() throws IOException { return checkOrigin().getReader(getCharset()); } /** * Gets a Writer from the origin with an OpenOption[]. * * @return An writer. * @throws IllegalStateException if the {@code origin} is {@code null}. * @throws UnsupportedOperationException if the origin cannot be converted to a {@link Writer}. * @throws IOException if an I/O error occurs. * @see AbstractOrigin#getOutputStream(OpenOption...) * @see #getOpenOptions() * @since 2.13.0 */ protected Writer getWriter() throws IOException { return checkOrigin().getWriter(getCharset(), getOpenOptions()); } /** * Sets the buffer size. Invalid input (bufferSize <= 0) resets the value to its default. *

* Subclasses may ignore this setting. *

* * @param bufferSize the buffer size. * @return this. */ public B setBufferSize(final int bufferSize) { this.bufferSize = checkBufferSize(bufferSize > 0 ? bufferSize : bufferSizeDefault); return asThis(); } /** * Sets the buffer size. *

* Subclasses may ignore this setting. *

* * @param bufferSize the buffer size, null resets to the default. * @return this. */ public B setBufferSize(final Integer bufferSize) { setBufferSize(bufferSize != null ? bufferSize : bufferSizeDefault); return asThis(); } /** * Sets the buffer size checker function. Throws a {@link IllegalArgumentException} by default. * * @param bufferSizeChecker the buffer size checker function. null resets to the default behavior. * @return this * @since 2.14.0 */ public B setBufferSizeChecker(final IntUnaryOperator bufferSizeChecker) { this.bufferSizeChecker = bufferSizeChecker != null ? bufferSizeChecker : defaultSizeChecker; return asThis(); } /** * Sets the buffer size for subclasses to initialize. *

* Subclasses may ignore this setting. *

* * @param bufferSizeDefault the buffer size, null resets to the default. * @return this. */ protected B setBufferSizeDefault(final int bufferSizeDefault) { this.bufferSizeDefault = bufferSizeDefault; return asThis(); } /** * The maximum buffer size checked by the buffer size checker. Values less or equal to 0, resets to the int max value. By default, if this value is * exceeded, this methods throws an {@link IllegalArgumentException}. * * @param bufferSizeMax maximum buffer size checked by the buffer size checker. * @return this. * @since 2.14.0 */ public B setBufferSizeMax(final int bufferSizeMax) { this.bufferSizeMax = bufferSizeMax > 0 ? bufferSizeMax : DEFAULT_MAX_VALUE; return asThis(); } /** * Sets the Charset. *

* Subclasses may ignore this setting. *

* * @param charset the Charset, null resets to the default. * @return this. */ public B setCharset(final Charset charset) { this.charset = Charsets.toCharset(charset, charsetDefault); return asThis(); } /** * Sets the Charset. *

* Subclasses may ignore this setting. *

* * @param charset the Charset name, null resets to the default. * @return this. */ public B setCharset(final String charset) { return setCharset(Charsets.toCharset(charset, charsetDefault)); } /** * Sets the Charset default for subclasses to initialize. *

* Subclasses may ignore this setting. *

* * @param defaultCharset the Charset name, null resets to the default. * @return this. */ protected B setCharsetDefault(final Charset defaultCharset) { this.charsetDefault = defaultCharset; return asThis(); } /** * Sets the OpenOption[]. *

* Normally used with InputStream, OutputStream, and Writer. *

*

* Subclasses may ignore this setting. *

* * @param openOptions the OpenOption[] name, null resets to the default. * @return this. * @since 2.13.0 * @see #setInputStream(InputStream) * @see #setOutputStream(OutputStream) * @see #setWriter(Writer) */ public B setOpenOptions(final OpenOption... openOptions) { this.openOptions = openOptions != null ? openOptions : DEFAULT_OPEN_OPTIONS; return asThis(); } private int throwIae(final int size, final int max) { throw new IllegalArgumentException(String.format("Request %,d exceeds maximum %,d", size, max)); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/build/AbstractSupplier.java0100644 0000000 0000000 00000002651 14603604450 030772 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.build; import org.apache.commons.io.function.IOSupplier; /** * Abstracts supplying an instance of {@code T}. Use to implement the builder pattern. * * @param the type of instances to build. * @param the type of builder subclass. * @since 2.12.0 */ public abstract class AbstractSupplier> implements IOSupplier { /** * Returns this instance typed as the proper subclass type. * * @return this instance typed as the proper subclass type. */ @SuppressWarnings("unchecked") protected B asThis() { return (B) this; } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/build/package-info.java0100644 0000000 0000000 00000001623 14603604450 030025 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Provides classes to implement IO builders. * * @since 2.12.0 */ package org.apache.commons.io.build; commons-io-2.16.1-src/src/main/java/org/apache/commons/io/channels/FileChannels.java0100644 0000000 0000000 00000005632 14603604450 030534 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.channels; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.util.Objects; import org.apache.commons.io.IOUtils; /** * Works with {@link FileChannel}. * * @since 2.15.0 */ public final class FileChannels { /** * Tests if two RandomAccessFiles contents are equal. * * @param channel1 A FileChannel. * @param channel2 Another FileChannel. * @param byteBufferSize The two internal buffer capacities, in bytes. * @return true if the contents of both RandomAccessFiles are equal, false otherwise. * @throws IOException if an I/O error occurs. */ public static boolean contentEquals(final FileChannel channel1, final FileChannel channel2, final int byteBufferSize) throws IOException { // Short-circuit test if (Objects.equals(channel1, channel2)) { return true; } // Short-circuit test final long size1 = size(channel1); final long size2 = size(channel2); if (size1 != size2) { return false; } if (size1 == 0 && size2 == 0) { return true; } // Dig in and do the work final ByteBuffer byteBuffer1 = ByteBuffer.allocateDirect(byteBufferSize); final ByteBuffer byteBuffer2 = ByteBuffer.allocateDirect(byteBufferSize); while (true) { final int read1 = channel1.read(byteBuffer1); final int read2 = channel2.read(byteBuffer2); byteBuffer1.clear(); byteBuffer2.clear(); if (read1 == IOUtils.EOF && read2 == IOUtils.EOF) { return byteBuffer1.equals(byteBuffer2); } if (read1 != read2) { return false; } if (!byteBuffer1.equals(byteBuffer2)) { return false; } } } private static long size(final FileChannel channel) throws IOException { return channel != null ? channel.size() : 0; } /** * Don't instantiate. */ private FileChannels() { // no-op } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/channels/package-info.java0100644 0000000 0000000 00000001644 14603604450 030524 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Provides classes to work with {@link java.nio.channels}. * * @since 2.15.0 */ package org.apache.commons.io.channels; commons-io-2.16.1-src/src/main/java/org/apache/commons/io/charset/CharsetDecoders.java0100644 0000000 0000000 00000003014 14603604450 031071 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.charset; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; /** * Works with {@link CharsetDecoder}. * * @since 2.12.0 */ public final class CharsetDecoders { /** * Returns the given non-null CharsetDecoder or a new default CharsetDecoder. * * @param charsetDecoder The CharsetDecoder to test. * @return the given non-null CharsetDecoder or a new default CharsetDecoder. */ public static CharsetDecoder toCharsetDecoder(final CharsetDecoder charsetDecoder) { return charsetDecoder != null ? charsetDecoder : Charset.defaultCharset().newDecoder(); } /** No instances. */ private CharsetDecoders() { // No instances. } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/charset/CharsetEncoders.java0100644 0000000 0000000 00000004166 14603604450 031114 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.charset; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; import java.util.function.Supplier; /** * Works with {@link CharsetEncoder}. * * @since 2.12.0 */ public final class CharsetEncoders { /** * Returns the given non-null CharsetEncoder or a new default CharsetEncoder. * * @param charsetEncoder The CharsetEncoder to test. * @return the given non-null CharsetEncoder or a new default CharsetEncoder. */ public static CharsetEncoder toCharsetEncoder(final CharsetEncoder charsetEncoder) { return toCharsetEncoder(charsetEncoder, () -> Charset.defaultCharset().newEncoder()); } /** * Returns the given non-null CharsetEncoder or a new default CharsetEncoder. * * @param charsetEncoder The CharsetEncoder to test. * @param defaultSupplier The CharsetEncoder supplier to get when charsetEncoder is null. * @return the given non-null CharsetEncoder or a new default CharsetEncoder. * @since 2.13.0 */ public static CharsetEncoder toCharsetEncoder(final CharsetEncoder charsetEncoder, final Supplier defaultSupplier) { return charsetEncoder != null ? charsetEncoder : defaultSupplier.get(); } /** No instances. */ private CharsetEncoders() { // No instances. } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/charset/package-info.java0100644 0000000 0000000 00000001654 14603604450 030363 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Provides classes to work with code from {@link java.nio.charset}. * * @since 2.12.0 */ package org.apache.commons.io.charset; commons-io-2.16.1-src/src/main/java/org/apache/commons/io/comparator/AbstractFileComparator.java0100644 0000000 0000000 00000004235 14603604450 033146 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.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 { /** * Sorts 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; } /** * Sorts a List of files. *

* This method uses {@link List#sort(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.16.1-src/src/main/java/org/apache/commons/io/comparator/CompositeFileComparator.java0100644 0000000 0000000 00000007726 14603604450 033355 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 java.util.function.IntFunction; import java.util.stream.Stream; import java.util.stream.StreamSupport; /** * 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 of other comparators. *

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

 *       CompositeFileComparator comparator = new CompositeFileComparator(
 *           DirectoryFileComparator.DIRECTORY_COMPARATOR,
 *           NameFileComparator.NAME_COMPARATOR);
 *       List<File> list = ...
 *       comparator.sort(list);
 * 
*

Deprecating Serialization

*

* Serialization is deprecated and will be removed in 3.0. *

* * @since 2.0 */ public class CompositeFileComparator extends AbstractFileComparator implements Serializable { private static final Comparator[] EMPTY_COMPARATOR_ARRAY = {}; private static final long serialVersionUID = -2224170307287243428L; /** * Delegates. */ private final Comparator[] delegates; /** * Constructs a composite comparator for the set of delegate comparators. * * @param delegates The delegate file comparators */ public CompositeFileComparator(@SuppressWarnings("unchecked") final Comparator... delegates) { this.delegates = delegates == null ? emptyArray() : delegates.clone(); } /** * Constructs a composite comparator for the set of delegate comparators. * * @param delegates The delegate file comparators */ public CompositeFileComparator(final Iterable> delegates) { this.delegates = delegates == null ? emptyArray() : StreamSupport.stream(delegates.spliterator(), false).toArray((IntFunction[]>) Comparator[]::new); } /** * Compares 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) { return Stream.of(delegates).map(delegate -> delegate.compare(file1, file2)).filter(r -> r != 0).findFirst().orElse(0); } @SuppressWarnings("unchecked") // types are already correct private Comparator[] emptyArray() { return (Comparator[]) EMPTY_COMPARATOR_ARRAY; } /** * 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.16.1-src/src/main/java/org/apache/commons/io/comparator/DefaultFileComparator.java0100644 0000000 0000000 00000005373 14603604450 032773 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; /** * Compares 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);
 * 
*

Deprecating Serialization

*

* Serialization is deprecated and will be removed in 3.0. *

* * @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); /** * Constructs a new instance. */ public DefaultFileComparator() { // empty } /** * Compares 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.16.1-src/src/main/java/org/apache/commons/io/comparator/DirectoryFileComparator.java0100644 0000000 0000000 00000005762 14603604450 033355 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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);
 * 
*

Deprecating Serialization

*

* Serialization is deprecated and will be removed in 3.0. *

* * @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); /** * Compares 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); } /** * Converts 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.16.1-src/src/main/java/org/apache/commons/io/comparator/ExtensionFileComparator.java0100644 0000000 0000000 00000012206 14603604450 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);
 * 
*

Deprecating Serialization

*

* Serialization is deprecated and will be removed in 3.0. *

* * @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 ioCase; /** * Constructs a case-sensitive file extension comparator instance. */ public ExtensionFileComparator() { this.ioCase = IOCase.SENSITIVE; } /** * Constructs a file extension comparator instance with the specified case-sensitivity. * * @param ioCase how to handle case sensitivity, null means case-sensitive */ public ExtensionFileComparator(final IOCase ioCase) { this.ioCase = IOCase.value(ioCase, IOCase.SENSITIVE); } /** * Compares 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 ioCase.checkCompareTo(suffix1, suffix2); } /** * String representation of this file comparator. * * @return String representation of this file comparator */ @Override public String toString() { return super.toString() + "[ioCase=" + ioCase + "]"; } } ././@LongLink0100644 0000000 0000000 00000000145 14603604450 011635 Lustar 0000000 0000000 commons-io-2.16.1-src/src/main/java/org/apache/commons/io/comparator/LastModifiedFileComparator.javacommons-io-2.16.1-src/src/main/java/org/apache/commons/io/comparator/LastModifiedFileComparator.java0100644 0000000 0000000 00000006156 14603604450 033753 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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);
 * 
*

Deprecating Serialization

*

* Serialization is deprecated and will be removed in 3.0. *

* * @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 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.16.1-src/src/main/java/org/apache/commons/io/comparator/NameFileComparator.java0100644 0000000 0000000 00000011253 14603604450 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);
 * 
*

Deprecating Serialization

*

* Serialization is deprecated and will be removed in 3.0. *

* * @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 ioCase; /** * Constructs a case-sensitive file name comparator instance. */ public NameFileComparator() { this.ioCase = IOCase.SENSITIVE; } /** * Constructs a file name comparator instance with the specified case-sensitivity. * * @param ioCase how to handle case sensitivity, null means case-sensitive */ public NameFileComparator(final IOCase ioCase) { this.ioCase = IOCase.value(ioCase, IOCase.SENSITIVE); } /** * Compares 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 ioCase.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() + "[ioCase=" + ioCase + "]"; } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/comparator/PathFileComparator.java0100644 0000000 0000000 00000011242 14603604450 032273 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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);
 * 
*

Deprecating Serialization

*

* Serialization is deprecated and will be removed in 3.0. *

* @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 ioCase; /** * Constructs a case-sensitive file path comparator instance. */ public PathFileComparator() { this.ioCase = IOCase.SENSITIVE; } /** * Constructs a file path comparator instance with the specified case-sensitivity. * * @param ioCase how to handle case sensitivity, null means case-sensitive */ public PathFileComparator(final IOCase ioCase) { this.ioCase = IOCase.value(ioCase, IOCase.SENSITIVE); } /** * Compares 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 ioCase.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() + "[ioCase=" + ioCase + "]"; } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/comparator/ReverseFileComparator.java0100644 0000000 0000000 00000004700 14603604450 033013 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 java.util.Objects; /** * Reverses the result of comparing two {@link File} objects using the delegate {@link Comparator}. *

Deprecating Serialization

*

* Serialization is deprecated and will be removed in 3.0. *

* * @since 1.4 */ final class ReverseFileComparator extends AbstractFileComparator implements Serializable { private static final long serialVersionUID = -4808255005272229056L; private final Comparator delegate; /** * Constructs an instance with the specified delegate {@link Comparator}. * * @param delegate The comparator to delegate to. */ public ReverseFileComparator(final Comparator delegate) { this.delegate = Objects.requireNonNull(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.16.1-src/src/main/java/org/apache/commons/io/comparator/SizeFileComparator.java0100644 0000000 0000000 00000012433 14603604450 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.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}. *

*

Deprecating Serialization

*

* Serialization is deprecated and will be removed in 3.0. *

* * @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; /** * Constructs a file size comparator instance (directories treated as zero size). */ public SizeFileComparator() { this.sumDirectoryContents = false; } /** * Constructs 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; } /** * Compares 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.16.1-src/src/main/java/org/apache/commons/io/comparator/package-info.java0100644 0000000 0000000 00000017717 14603604450 031110 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Provides various {@link java.util.Comparator} implementations * for {@link java.io.File}s and {@link java.nio.file.Path}. *

Sorting

*

* All the comparators 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 of 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: *

* */ package org.apache.commons.io.comparator; commons-io-2.16.1-src/src/main/java/org/apache/commons/io/file/AccumulatorPathVisitor.java0100644 0000000 0000000 00000017765 14603604450 032013 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.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; import org.apache.commons.io.function.IOBiFunction; /** * Accumulates normalized paths during visitation. *

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

*

Example

* *
 * Path dir = PathUtils.current();
 * // We are interested in files older than one day
 * Instant cutoff = Instant.now().minus(Duration.ofDays(1));
 * 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 { /** * Constructs 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()); } /** * Constructs 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); } /** * Constructs 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()); } /** * Constructs 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); } /** * 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. * @param visitFileFailed Called on {@link #visitFileFailed(Path, IOException)}. * @since 2.12.0 */ public AccumulatorPathVisitor(final PathCounters pathCounter, final PathFilter fileFilter, final PathFilter dirFilter, final IOBiFunction visitFileFailed) { super(pathCounter, fileFilter, dirFilter, visitFileFailed); } 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 a copy of the list of visited directories. * * @return a copy of the list of visited directories. */ public List getDirList() { return new ArrayList<>(dirList); } /** * Gets a copy of the list of visited files. * * @return a copy of the list of visited files. */ public List getFileList() { return new ArrayList<>(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.16.1-src/src/main/java/org/apache/commons/io/file/CleaningPathVisitor.java0100644 0000000 0000000 00000011556 14603604450 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.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 { /** * Constructs 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()); } /** * Constructs 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, PathUtils.getFileNameString(path)) < 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.16.1-src/src/main/java/org/apache/commons/io/file/CopyDirectoryVisitor.java0100644 0000000 0000000 00000014344 14603604450 031504 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 static CopyOption[] toCopyOption(final CopyOption... copyOptions) { return copyOptions == null ? PathUtils.EMPTY_COPY_OPTIONS : copyOptions.clone(); } 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 = toCopyOption(copyOptions); } /** * 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 = toCopyOption(copyOptions); } /** * 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.16.1-src/src/main/java/org/apache/commons/io/file/Counters.java0100644 0000000 0000000 00000025401 14603604450 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 {@link 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 void reset() { value = BigInteger.ZERO; } @Override public String toString() { return value.toString(); } } /** * 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 {@code 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 void reset() { value = 0L; } @Override public String toString() { return Long.toString(value); } } /** * 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 } /** * Returns {@code "0"}, always. * * @return {@code "0"}, always. * @since 2.12.0 */ @Override public String toString() { return "0"; } } /** * 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 no-op Counter. * * @return the no-op Counter. * @since 2.9.0 */ public static Counter noopCounter() { return NoopCounter.INSTANCE; } /** * Returns the no-op PathCounters. * * @return the no-op PathCounters. * @since 2.9.0 */ public static PathCounters noopPathCounters() { return NoopPathCounters.INSTANCE; } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/file/CountingPathVisitor.java0100644 0000000 0000000 00000014715 14603604450 031312 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.math.BigInteger; 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.IOFileFilter; import org.apache.commons.io.filefilter.SymbolicLinkFileFilter; import org.apache.commons.io.filefilter.TrueFileFilter; import org.apache.commons.io.function.IOBiFunction; /** * Counts files, directories, and sizes, as a visit proceeds. * * @since 2.7 */ public class CountingPathVisitor extends SimplePathVisitor { static final String[] EMPTY_STRING_ARRAY = {}; static IOFileFilter defaultDirFilter() { return TrueFileFilter.INSTANCE; } static IOFileFilter defaultFileFilter() { return new SymbolicLinkFileFilter(FileVisitResult.TERMINATE, FileVisitResult.CONTINUE); } /** * Constructs a new instance configured with a {@link BigInteger} {@link PathCounters}. * * @return a new instance configured with a {@link BigInteger} {@link PathCounters}. */ public static CountingPathVisitor withBigIntegerCounters() { return new CountingPathVisitor(Counters.bigIntegerPathCounters()); } /** * Constructs a new instance configured with a {@code long} {@link PathCounters}. * * @return a new instance configured with a {@code 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, defaultFileFilter(), defaultDirFilter()); } /** * 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"); } /** * 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. * @param visitFileFailed Called on {@link #visitFileFailed(Path, IOException)}. * @since 2.12.0 */ public CountingPathVisitor(final PathCounters pathCounter, final PathFilter fileFilter, final PathFilter dirFilter, final IOBiFunction visitFileFailed) { super(visitFileFailed); 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 { // Note: A file can be a symbolic link to a directory. if (Files.exists(file) && fileFilter.accept(file, attributes) == FileVisitResult.CONTINUE) { updateFileCounters(file, attributes); } return FileVisitResult.CONTINUE; } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/file/DeleteOption.java0100644 0000000 0000000 00000002110 14603604450 027704 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.16.1-src/src/main/java/org/apache/commons/io/file/DeletingPathVisitor.java0100644 0000000 0000000 00000014542 14603604450 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.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 { /** * Constructs 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()); } /** * Constructs 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.noFollowLinkOptionArray(), 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.noFollowLinkOptionArray() : 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, PathUtils.getFileNameString(path)) < 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 ignored) { // ignore } } } updateFileCounters(file, attrs); return FileVisitResult.CONTINUE; } }commons-io-2.16.1-src/src/main/java/org/apache/commons/io/file/DirectoryStreamFilter.java0100644 0000000 0000000 00000004174 14603604450 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.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, PathUtils.EMPTY_LINK_OPTION_ARRAY)) == FileVisitResult.CONTINUE; } /** * Gets the path filter. * * @return the path filter. */ public PathFilter getPathFilter() { return pathFilter; } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/file/FilesUncheck.java0100644 0000000 0000000 00000075761 14603604450 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; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.Reader; import java.io.UncheckedIOException; import java.nio.channels.SeekableByteChannel; import java.nio.charset.Charset; import java.nio.file.CopyOption; import java.nio.file.DirectoryStream; import java.nio.file.FileStore; import java.nio.file.FileVisitOption; import java.nio.file.FileVisitor; import java.nio.file.Files; import java.nio.file.LinkOption; import java.nio.file.OpenOption; import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.FileAttribute; import java.nio.file.attribute.FileTime; import java.nio.file.attribute.PosixFilePermission; import java.nio.file.attribute.UserPrincipal; import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.BiPredicate; import java.util.stream.Stream; import org.apache.commons.io.function.Uncheck; /** * Delegates to {@link Files} to uncheck calls by throwing {@link UncheckedIOException} instead of {@link IOException}. * * @see Files * @see IOException * @see UncheckedIOException * @since 2.12.0 */ public final class FilesUncheck { /** * Delegates to {@link Files#copy(InputStream, Path, CopyOption...)} throwing {@link UncheckedIOException} instead of * {@link IOException}. * * @param in See delegate. * @param target See delegate. * @param options See delegate. * @return See delegate. * @throws UncheckedIOException Wraps an {@link IOException}. * @see Files#copy(InputStream, Path,CopyOption...) */ public static long copy(final InputStream in, final Path target, final CopyOption... options) { return Uncheck.apply(Files::copy, in, target, options); } /** * Delegates to {@link Files#copy(Path, OutputStream)} throwing {@link UncheckedIOException} instead of * {@link IOException}. * * @param source See delegate. See delegate. * @param out See delegate. See delegate. * @return See delegate. See delegate. * @throws UncheckedIOException Wraps an {@link IOException}. */ public static long copy(final Path source, final OutputStream out) { return Uncheck.apply(Files::copy, source, out); } /** * Delegates to {@link Files#copy(Path, Path, CopyOption...)} throwing {@link UncheckedIOException} instead of * {@link IOException}. * * @param source See delegate. * @param target See delegate. * @param options See delegate. * @return See delegate. * @throws UncheckedIOException Wraps an {@link IOException}. */ public static Path copy(final Path source, final Path target, final CopyOption... options) { return Uncheck.apply(Files::copy, source, target, options); } /** * Delegates to {@link Files#createDirectories(Path, FileAttribute...)} throwing {@link UncheckedIOException} instead of * {@link IOException}. * * @param dir See delegate. * @param attrs See delegate. * @return See delegate. * @throws UncheckedIOException Wraps an {@link IOException}. */ public static Path createDirectories(final Path dir, final FileAttribute... attrs) { return Uncheck.apply(Files::createDirectories, dir, attrs); } /** * Delegates to {@link Files#createDirectory(Path, FileAttribute...)} throwing {@link UncheckedIOException} instead of * {@link IOException}. * * @param dir See delegate. * @param attrs See delegate. * @return See delegate. * @throws UncheckedIOException Wraps an {@link IOException}. */ public static Path createDirectory(final Path dir, final FileAttribute... attrs) { return Uncheck.apply(Files::createDirectory, dir, attrs); } /** * Delegates to {@link Files#createFile(Path, FileAttribute...)} throwing {@link UncheckedIOException} instead of * {@link IOException}. * * @param path See delegate. * @param attrs See delegate. * @return See delegate. * @throws UncheckedIOException Wraps an {@link IOException}. */ public static Path createFile(final Path path, final FileAttribute... attrs) { return Uncheck.apply(Files::createFile, path, attrs); } /** * Delegates to {@link Files#createLink(Path, Path)} throwing {@link UncheckedIOException} instead of * {@link IOException}. * * @param link See delegate. * @param existing See delegate. * @return See delegate. * @throws UncheckedIOException Wraps an {@link IOException}. */ public static Path createLink(final Path link, final Path existing) { return Uncheck.apply(Files::createLink, link, existing); } /** * Delegates to {@link Files#createSymbolicLink(Path, Path, FileAttribute...)} throwing {@link UncheckedIOException} * instead of {@link IOException}. * * @param link See delegate. * @param target See delegate. * @param attrs See delegate. * @return See delegate. * @throws UncheckedIOException Wraps an {@link IOException}. */ public static Path createSymbolicLink(final Path link, final Path target, final FileAttribute... attrs) { return Uncheck.apply(Files::createSymbolicLink, link, target, attrs); } /** * Delegates to {@link Files#createTempDirectory(Path, String, FileAttribute...)} throwing {@link UncheckedIOException} * instead of {@link IOException}. * * @param dir See delegate. * @param prefix See delegate. * @param attrs See delegate. * @return See delegate. * @throws UncheckedIOException Wraps an {@link IOException}. */ public static Path createTempDirectory(final Path dir, final String prefix, final FileAttribute... attrs) { return Uncheck.apply(Files::createTempDirectory, dir, prefix, attrs); } /** * Delegates to {@link Files#createTempDirectory(String, FileAttribute...)} throwing {@link UncheckedIOException} * instead of {@link IOException}. * * @param prefix See delegate. * @param attrs See delegate. * @return See delegate. * @throws UncheckedIOException Wraps an {@link IOException}. */ public static Path createTempDirectory(final String prefix, final FileAttribute... attrs) { return Uncheck.apply(Files::createTempDirectory, prefix, attrs); } /** * Delegates to {@link Files#createTempFile(Path, String, String, FileAttribute...)} throwing * {@link UncheckedIOException} instead of {@link IOException}. * * @param dir See delegate. * @param prefix See delegate. * @param suffix See delegate. * @param attrs See delegate. * @return See delegate. * @throws UncheckedIOException Wraps an {@link IOException}. */ public static Path createTempFile(final Path dir, final String prefix, final String suffix, final FileAttribute... attrs) { return Uncheck.apply(Files::createTempFile, dir, prefix, suffix, attrs); } /** * Delegates to {@link Files#createTempFile(String, String, FileAttribute...)} throwing {@link UncheckedIOException} * instead of {@link IOException}. * * @param prefix See delegate. * @param suffix See delegate. * @param attrs See delegate. * @return See delegate. * @throws UncheckedIOException Wraps an {@link IOException}. */ public static Path createTempFile(final String prefix, final String suffix, final FileAttribute... attrs) { return Uncheck.apply(Files::createTempFile, prefix, suffix, attrs); } /** * Delegates to {@link Files#delete(Path)} throwing {@link UncheckedIOException} instead of {@link IOException}. * * @param path See delegate. * @throws UncheckedIOException Wraps an {@link IOException}. */ public static void delete(final Path path) { Uncheck.accept(Files::delete, path); } /** * Delegates to {@link Files#deleteIfExists(Path)} throwing {@link UncheckedIOException} instead of {@link IOException}. * * @param path See delegate. * @return See delegate. * @throws UncheckedIOException Wraps an {@link IOException}. */ public static boolean deleteIfExists(final Path path) { return Uncheck.apply(Files::deleteIfExists, path); } /** * Delegates to {@link Files#find(Path, int, BiPredicate, FileVisitOption...)} throwing {@link UncheckedIOException} instead of {@link IOException}. *

* The returned {@link Stream} wraps a {@link DirectoryStream}. When you require timely disposal of file system resources, use a {@code try}-with-resources * block to ensure invocation of the stream's {@link Stream#close()} method after the stream operations are completed. *

* * @param start See delegate. * @param maxDepth See delegate. * @param matcher See delegate. * @param options See delegate. * @return See delegate. * @throws UncheckedIOException Wraps an {@link IOException}. * @since 2.14.0 */ public static Stream find(final Path start, final int maxDepth, final BiPredicate matcher, final FileVisitOption... options) { return Uncheck.apply(Files::find, start, maxDepth, matcher, options); } /** * Delegates to {@link Files#getAttribute(Path, String, LinkOption...)} throwing {@link UncheckedIOException} instead of * {@link IOException}. * * @param path See delegate. * @param attribute See delegate. * @param options See delegate. * @return See delegate. * @throws UncheckedIOException Wraps an {@link IOException}. */ public static Object getAttribute(final Path path, final String attribute, final LinkOption... options) { return Uncheck.apply(Files::getAttribute, path, attribute, options); } /** * Delegates to {@link Files#getFileStore(Path)} throwing {@link UncheckedIOException} instead of {@link IOException}. * * @param path See delegate. * @return See delegate. * @throws UncheckedIOException Wraps an {@link IOException}. */ public static FileStore getFileStore(final Path path) { return Uncheck.apply(Files::getFileStore, path); } /** * Delegates to {@link Files#getLastModifiedTime(Path, LinkOption...)} throwing {@link UncheckedIOException} instead of * {@link IOException}. * * @param path See delegate. * @param options See delegate. * @return See delegate. * @throws UncheckedIOException Wraps an {@link IOException}. */ public static FileTime getLastModifiedTime(final Path path, final LinkOption... options) { return Uncheck.apply(Files::getLastModifiedTime, path, options); } /** * Delegates to {@link Files#getOwner(Path, LinkOption...)} throwing {@link UncheckedIOException} instead of * {@link IOException}. * * @param path See delegate. * @param options See delegate. * @return See delegate. * @throws UncheckedIOException Wraps an {@link IOException}. */ public static UserPrincipal getOwner(final Path path, final LinkOption... options) { return Uncheck.apply(Files::getOwner, path, options); } /** * Delegates to {@link Files#getPosixFilePermissions(Path, LinkOption...)} throwing {@link UncheckedIOException} instead * of {@link IOException}. * * @param path See delegate. * @param options See delegate. * @return See delegate. * @throws UncheckedIOException Wraps an {@link IOException}. */ public static Set getPosixFilePermissions(final Path path, final LinkOption... options) { return Uncheck.apply(Files::getPosixFilePermissions, path, options); } /** * Delegates to {@link Files#isHidden(Path)} throwing {@link UncheckedIOException} instead of {@link IOException}. * * @param path See delegate. * @return See delegate. * @throws UncheckedIOException Wraps an {@link IOException}. */ public static boolean isHidden(final Path path) { return Uncheck.apply(Files::isHidden, path); } /** * Delegates to {@link Files#isSameFile(Path, Path)} throwing {@link UncheckedIOException} instead of * {@link IOException}. * * @param path See delegate. * @param path2 See delegate. * @return See delegate. * @throws UncheckedIOException Wraps an {@link IOException}. */ public static boolean isSameFile(final Path path, final Path path2) { return Uncheck.apply(Files::isSameFile, path, path2); } /** * Delegates to {@link Files#lines(Path)} throwing {@link UncheckedIOException} instead of {@link IOException}. *

* The returned {@link Stream} wraps a {@link Reader}. When you require timely disposal of file system resources, use a {@code try}-with-resources block to * ensure invocation of the stream's {@link Stream#close()} method after the stream operations are completed. *

* * @param path See delegate. * @return See delegate. * @throws UncheckedIOException Wraps an {@link IOException}. */ public static Stream lines(final Path path) { return Uncheck.apply(Files::lines, path); } /** * Delegates to {@link Files#lines(Path, Charset)} throwing {@link UncheckedIOException} instead of {@link IOException}. *

* The returned {@link Stream} wraps a {@link Reader}. When you require timely disposal of file system resources, use a {@code try}-with-resources block to * ensure invocation of the stream's {@link Stream#close()} method after the stream operations are completed. *

* * @param path See delegate. * @param cs See delegate. * @return See delegate. * @throws UncheckedIOException Wraps an {@link IOException}. */ public static Stream lines(final Path path, final Charset cs) { return Uncheck.apply(Files::lines, path, cs); } /** * Delegates to {@link Files#list(Path)} throwing {@link UncheckedIOException} instead of {@link IOException}. *

* The returned {@link Stream} wraps a {@link DirectoryStream}. When you require timely disposal of file system resources, use a {@code try}-with-resources * block to ensure invocation of the stream's {@link Stream#close()} method after the stream operations are completed. *

* * @param dir See delegate. * @return See delegate. * @throws UncheckedIOException Wraps an {@link IOException}. */ public static Stream list(final Path dir) { return Uncheck.apply(Files::list, dir); } /** * Delegates to {@link Files#move(Path, Path, CopyOption...)} throwing {@link UncheckedIOException} instead of * {@link IOException}. * * @param source See delegate. * @param target See delegate. * @param options See delegate. * @return See delegate. * @throws UncheckedIOException Wraps an {@link IOException}. */ public static Path move(final Path source, final Path target, final CopyOption... options) { return Uncheck.apply(Files::move, source, target, options); } /** * Delegates to {@link Files#newBufferedReader(Path)} throwing {@link UncheckedIOException} instead of * {@link IOException}. * * @param path See delegate. * @return See delegate. * @throws UncheckedIOException Wraps an {@link IOException}. */ public static BufferedReader newBufferedReader(final Path path) { return Uncheck.apply(Files::newBufferedReader, path); } /** * Delegates to {@link Files#newBufferedReader(Path, Charset)} throwing {@link UncheckedIOException} instead of * {@link IOException}. * * @param path See delegate. * @param cs See delegate. * @return See delegate. * @throws UncheckedIOException Wraps an {@link IOException}. */ public static BufferedReader newBufferedReader(final Path path, final Charset cs) { return Uncheck.apply(Files::newBufferedReader, path, cs); } /** * Delegates to {@link Files#newBufferedWriter(Path, Charset, OpenOption...)} throwing {@link UncheckedIOException} * instead of {@link IOException}. * * @param path See delegate. * @param cs See delegate. * @param options See delegate. * @return See delegate. * @throws UncheckedIOException Wraps an {@link IOException}. */ public static BufferedWriter newBufferedWriter(final Path path, final Charset cs, final OpenOption... options) { return Uncheck.apply(Files::newBufferedWriter, path, cs, options); } /** * Delegates to {@link Files#newBufferedWriter(Path, OpenOption...)} throwing {@link UncheckedIOException} instead of * {@link IOException}. * * @param path See delegate. * @param options See delegate. * @return See delegate. * @throws UncheckedIOException Wraps an {@link IOException}. */ public static BufferedWriter newBufferedWriter(final Path path, final OpenOption... options) { return Uncheck.apply(Files::newBufferedWriter, path, options); } /** * Delegates to {@link Files#newByteChannel(Path, OpenOption...)} throwing {@link UncheckedIOException} instead of * {@link IOException}. * * @param path See delegate. * @param options See delegate. * @return See delegate. * @throws UncheckedIOException Wraps an {@link IOException}. */ public static SeekableByteChannel newByteChannel(final Path path, final OpenOption... options) { return Uncheck.apply(Files::newByteChannel, path, options); } /** * Delegates to {@link Files#newByteChannel(Path, Set, FileAttribute...)} throwing {@link UncheckedIOException} instead * of {@link IOException}. * * @param path See delegate. * @param options See delegate. * @param attrs See delegate. * @return See delegate. * @throws UncheckedIOException Wraps an {@link IOException}. */ public static SeekableByteChannel newByteChannel(final Path path, final Set options, final FileAttribute... attrs) { return Uncheck.apply(Files::newByteChannel, path, options, attrs); } /** * Delegates to {@link Files#newDirectoryStream(Path)} throwing {@link UncheckedIOException} instead of {@link IOException}. *

* If you don't use the try-with-resources construct, then you must call the stream's {@link Stream#close()} method after iteration is complete to free any * resources held for the open directory. *

* * @param dir See delegate. * @return See delegate. */ public static DirectoryStream newDirectoryStream(final Path dir) { return Uncheck.apply(Files::newDirectoryStream, dir); } /** * Delegates to {@link Files#newDirectoryStream(Path, java.nio.file.DirectoryStream.Filter)} throwing {@link UncheckedIOException} instead of * {@link IOException}. *

* If you don't use the try-with-resources construct, then you must call the stream's {@link Stream#close()} method after iteration is complete to free any * resources held for the open directory. *

* * @param dir See delegate. * @param filter See delegate. * @return See delegate. */ public static DirectoryStream newDirectoryStream(final Path dir, final DirectoryStream.Filter filter) { return Uncheck.apply(Files::newDirectoryStream, dir, filter); } /** * Delegates to {@link Files#newDirectoryStream(Path, String)} throwing {@link UncheckedIOException} instead of * {@link IOException}. *

* The returned {@link Stream} wraps a {@link DirectoryStream}. When you require timely disposal of file system resources, use a {@code try}-with-resources * block to ensure invocation of the stream's {@link Stream#close()} method after the stream operations are completed. *

* * @param dir See delegate. * @param glob See delegate. * @return See delegate. */ public static DirectoryStream newDirectoryStream(final Path dir, final String glob) { return Uncheck.apply(Files::newDirectoryStream, dir, glob); } /** * Delegates to {@link Files#newInputStream(Path, OpenOption...)} throwing {@link UncheckedIOException} instead of * {@link IOException}. * * @param path See delegate. * @param options See delegate. * @return See delegate. */ public static InputStream newInputStream(final Path path, final OpenOption... options) { return Uncheck.apply(Files::newInputStream, path, options); } /** * Delegates to {@link Files#newOutputStream(Path, OpenOption...)} throwing {@link UncheckedIOException} instead of * {@link IOException}. * * @param path See delegate. * @param options See delegate. * @return See delegate. */ public static OutputStream newOutputStream(final Path path, final OpenOption... options) { return Uncheck.apply(Files::newOutputStream, path, options); } /** * Delegates to {@link Files#probeContentType(Path)} throwing {@link UncheckedIOException} instead of * {@link IOException}. * * @param path See delegate. * @return See delegate. */ public static String probeContentType(final Path path) { return Uncheck.apply(Files::probeContentType, path); } /** * Delegates to {@link Files#readAllBytes(Path)} throwing {@link UncheckedIOException} instead of {@link IOException}. * * @param path See delegate. * @return See delegate. */ public static byte[] readAllBytes(final Path path) { return Uncheck.apply(Files::readAllBytes, path); } /** * Delegates to {@link Files#readAllLines(Path)} throwing {@link UncheckedIOException} instead of {@link IOException}. * * @param path See delegate. * @return See delegate. */ public static List readAllLines(final Path path) { return Uncheck.apply(Files::readAllLines, path); } /** * Delegates to {@link Files#readAllLines(Path, Charset)} throwing {@link UncheckedIOException} instead of * {@link IOException}. * * @param path See delegate. * @param cs See delegate. * @return See delegate. */ public static List readAllLines(final Path path, final Charset cs) { return Uncheck.apply(Files::readAllLines, path, cs); } /** * Delegates to {@link Files#readAttributes(Path, Class, LinkOption...)} throwing {@link UncheckedIOException} instead * of {@link IOException}. * * @param See delegate. * @param path See delegate. * @param type See delegate. * @param options See delegate. * @return See delegate. */ public static A readAttributes(final Path path, final Class type, final LinkOption... options) { return Uncheck.apply(Files::readAttributes, path, type, options); } /** * Delegates to {@link Files#readAttributes(Path, String, LinkOption...)} throwing {@link UncheckedIOException} instead * of {@link IOException}. * * @param path See delegate. * @param attributes See delegate. * @param options See delegate. * @return See delegate. */ public static Map readAttributes(final Path path, final String attributes, final LinkOption... options) { return Uncheck.apply(Files::readAttributes, path, attributes, options); } /** * Delegates to {@link Files#readSymbolicLink(Path)} throwing {@link UncheckedIOException} instead of * {@link IOException}. * * @param link See delegate. * @return See delegate. */ public static Path readSymbolicLink(final Path link) { return Uncheck.apply(Files::readSymbolicLink, link); } /** * Delegates to {@link Files#setAttribute(Path, String, Object, LinkOption...)} throwing {@link UncheckedIOException} * instead of {@link IOException}. * * @param path See delegate. * @param attribute See delegate. * @param value See delegate. * @param options See delegate. * @return See delegate. */ public static Path setAttribute(final Path path, final String attribute, final Object value, final LinkOption... options) { return Uncheck.apply(Files::setAttribute, path, attribute, value, options); } /** * Delegates to {@link Files#setLastModifiedTime(Path, FileTime)} throwing {@link UncheckedIOException} instead of * {@link IOException}. * * @param path See delegate. * @param time See delegate. * @return See delegate. */ public static Path setLastModifiedTime(final Path path, final FileTime time) { return Uncheck.apply(Files::setLastModifiedTime, path, time); } /** * Delegates to {@link Files#setOwner(Path, UserPrincipal)} throwing {@link UncheckedIOException} instead of * {@link IOException}. * * @param path See delegate. * @param owner See delegate. * @return See delegate. */ public static Path setOwner(final Path path, final UserPrincipal owner) { return Uncheck.apply(Files::setOwner, path, owner); } /** * Delegates to {@link Files#setPosixFilePermissions(Path, Set)} throwing {@link UncheckedIOException} instead of * {@link IOException}. * * @param path See delegate. * @param perms See delegate. * @return See delegate. */ public static Path setPosixFilePermissions(final Path path, final Set perms) { return Uncheck.apply(Files::setPosixFilePermissions, path, perms); } /** * Delegates to {@link Files#size(Path)} throwing {@link UncheckedIOException} instead of {@link IOException}. * * @param path See delegate. * @return See delegate. */ public static long size(final Path path) { return Uncheck.apply(Files::size, path); } /** * Delegates to {@link Files#walk(Path, FileVisitOption...)} throwing {@link UncheckedIOException} instead of {@link IOException}. *

* The returned {@link Stream} may wrap one or more {@link DirectoryStream}s. When you require timely disposal of file system resources, use a * {@code try}-with-resources block to ensure invocation of the stream's {@link Stream#close()} method after the stream operations are completed. Calling a * closed stream causes a {@link IllegalStateException}. *

* * @param start See delegate. * @param options See delegate. * @return See delegate. */ public static Stream walk(final Path start, final FileVisitOption... options) { return Uncheck.apply(Files::walk, start, options); } /** * Delegates to {@link Files#walk(Path, int, FileVisitOption...)} throwing {@link UncheckedIOException} instead of {@link IOException}. *

* The returned {@link Stream} may wrap one or more {@link DirectoryStream}s. When you require timely disposal of file system resources, use a * {@code try}-with-resources block to ensure invocation of the stream's {@link Stream#close()} method after the stream operations are completed. Calling a * closed stream causes a {@link IllegalStateException}. *

* * @param start See delegate. * @param maxDepth See delegate. * @param options See delegate. * @return See delegate. */ public static Stream walk(final Path start, final int maxDepth, final FileVisitOption... options) { return Uncheck.apply(Files::walk, start, maxDepth, options); } /** * Delegates to {@link Files#walkFileTree(Path, FileVisitor)} throwing {@link UncheckedIOException} instead of * {@link IOException}. * * @param start See delegate. * @param visitor See delegate. * @return See delegate. */ public static Path walkFileTree(final Path start, final FileVisitor visitor) { return Uncheck.apply(Files::walkFileTree, start, visitor); } /** * Delegates to {@link Files#walkFileTree(Path, Set, int, FileVisitor)} throwing {@link UncheckedIOException} instead of * {@link IOException}. * * @param start See delegate. * @param options See delegate. * @param maxDepth See delegate. * @param visitor See delegate. * @return See delegate. */ public static Path walkFileTree(final Path start, final Set options, final int maxDepth, final FileVisitor visitor) { return Uncheck.apply(Files::walkFileTree, start, options, maxDepth, visitor); } /** * Delegates to {@link Files#write(Path, byte[], OpenOption...)} throwing {@link UncheckedIOException} instead of * {@link IOException}. * * @param path See delegate. * @param bytes See delegate. * @param options See delegate. * @return See delegate. */ public static Path write(final Path path, final byte[] bytes, final OpenOption... options) { return Uncheck.apply(Files::write, path, bytes, options); } /** * Delegates to {@link Files#write(Path, Iterable, Charset, OpenOption...)} throwing {@link UncheckedIOException} * instead of {@link IOException}. * * @param path See delegate. * @param lines See delegate. * @param cs See delegate. * @param options See delegate. * @return See delegate. */ public static Path write(final Path path, final Iterable lines, final Charset cs, final OpenOption... options) { return Uncheck.apply(Files::write, path, lines, cs, options); } /** * Delegates to {@link Files#write(Path, Iterable, OpenOption...)} throwing {@link UncheckedIOException} instead of * {@link IOException}. * * @param path See delegate. * @param lines See delegate. * @param options See delegate. * @return See delegate. */ public static Path write(final Path path, final Iterable lines, final OpenOption... options) { return Uncheck.apply(Files::write, path, lines, options); } /** * No instances. */ private FilesUncheck() { // No instances } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/file/NoopPathVisitor.java0100644 0000000 0000000 00000003113 14603604450 030425 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.Path; import org.apache.commons.io.function.IOBiFunction; /** * A noop path visitor. * * @since 2.9.0 */ public class NoopPathVisitor extends SimplePathVisitor { /** * The singleton instance. */ public static final NoopPathVisitor INSTANCE = new NoopPathVisitor(); /** * Constructs a new instance. */ public NoopPathVisitor() { } /** * Constructs a new instance. * * @param visitFileFailed Called on {@link #visitFileFailed(Path, IOException)}. * @since 2.12.0 */ public NoopPathVisitor(final IOBiFunction visitFileFailed) { super(visitFileFailed); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/file/PathFilter.java0100644 0000000 0000000 00000002543 14603604450 027365 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.16.1-src/src/main/java/org/apache/commons/io/file/PathUtils.java0100644 0000000 0000000 00000245170 14603604450 027245 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.OutputStream; import java.io.RandomAccessFile; import java.math.BigInteger; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.nio.charset.Charset; import java.nio.file.AccessDeniedException; 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.StandardOpenOption; 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.DosFileAttributes; import java.nio.file.attribute.FileAttribute; import java.nio.file.attribute.FileTime; import java.nio.file.attribute.PosixFileAttributeView; import java.nio.file.attribute.PosixFileAttributes; import java.nio.file.attribute.PosixFilePermission; import java.time.Duration; import java.time.Instant; import java.time.chrono.ChronoZonedDateTime; 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.HashSet; import java.util.List; import java.util.Objects; import java.util.Set; import java.util.function.Function; import java.util.stream.Collector; import java.util.stream.Collectors; import java.util.stream.Stream; import org.apache.commons.io.Charsets; import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.io.RandomAccessFileMode; import org.apache.commons.io.RandomAccessFiles; import org.apache.commons.io.ThreadUtils; import org.apache.commons.io.file.Counters.PathCounters; import org.apache.commons.io.file.attribute.FileTimes; import org.apache.commons.io.filefilter.IOFileFilter; import org.apache.commons.io.function.IOFunction; import org.apache.commons.io.function.IOSupplier; /** * 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 final 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; } } private static final OpenOption[] OPEN_OPTIONS_TRUNCATE = { StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING }; private static final OpenOption[] OPEN_OPTIONS_APPEND = { StandardOpenOption.CREATE, StandardOpenOption.APPEND }; /** * Empty {@link CopyOption} array. * * @since 2.8.0 */ public static final CopyOption[] EMPTY_COPY_OPTIONS = {}; /** * Empty {@link DeleteOption} array. * * @since 2.8.0 */ public static final DeleteOption[] EMPTY_DELETE_OPTION_ARRAY = {}; /** * Empty {@link FileAttribute} array. * * @since 2.13.0 */ public static final FileAttribute[] EMPTY_FILE_ATTRIBUTE_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 * @deprecated Use {@link #noFollowLinkOptionArray()}. */ @Deprecated public static final LinkOption[] NOFOLLOW_LINK_OPTION_ARRAY = { LinkOption.NOFOLLOW_LINKS }; /** * A LinkOption used to follow link in this class, the inverse of {@link LinkOption#NOFOLLOW_LINKS}. * * @since 2.12.0 */ static final LinkOption NULL_LINK_OPTION = null; /** * 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 subdirectories 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 subdirectories 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(); } /** * Compares the given {@link Path}'s last modified time to the given file time. * * @param file the {@link Path} to test. * @param fileTime the time reference. * @param options options indicating how to handle symbolic links. * @return See {@link FileTime#compareTo(FileTime)} * @throws IOException if an I/O error occurs. * @throws NullPointerException if the file is {@code null}. */ private static int compareLastModifiedTimeTo(final Path file, final FileTime fileTime, final LinkOption... options) throws IOException { return getLastModifiedTime(file, options).compareTo(fileTime); } /** * Copies the InputStream from the supplier with {@link Files#copy(InputStream, Path, CopyOption...)}. * * @param in Supplies the InputStream. * @param target See {@link Files#copy(InputStream, Path, CopyOption...)}. * @param copyOptions See {@link Files#copy(InputStream, Path, CopyOption...)}. * @return See {@link Files#copy(InputStream, Path, CopyOption...)} * @throws IOException See {@link Files#copy(InputStream, Path, CopyOption...)} * @since 2.12.0 */ public static long copy(final IOSupplier in, final Path target, final CopyOption... copyOptions) throws IOException { try (InputStream inputStream = in.get()) { return Files.copy(inputStream, target, copyOptions); } } /** * 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 { copy(sourceFile::openStream, 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 { final Path resolve = targetDirectory.resolve(FilenameUtils.getName(sourceFile.getFile())); copy(sourceFile::openStream, resolve, copyOptions); return resolve; } /** * Counts aspects of a directory including subdirectories. * * @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(CountingPathVisitor.withLongCounters(), directory).getPathCounters(); } /** * Counts aspects of a directory including subdirectories. * * @param directory directory to count. * @return The visitor used to count the given directory. * @throws IOException if an I/O error occurs. * @since 2.12.0 */ public static PathCounters countDirectoryAsBigInteger(final Path directory) throws IOException { return visitFileTree(CountingPathVisitor.withBigIntegerCounters(), directory).getPathCounters(); } /** * Creates the parent directories for the given {@code path}. *

* If the parent directory already exists, then return it. *

* * @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 { return createParentDirectories(path, LinkOption.NOFOLLOW_LINKS, attrs); } /** * Creates the parent directories for the given {@code path}. *

* If the parent directory already exists, then return it. *

* * @param path The path to a file (or directory). * @param linkOption A {@link LinkOption} or null. * @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.12.0 */ public static Path createParentDirectories(final Path path, final LinkOption linkOption, final FileAttribute... attrs) throws IOException { Path parent = getParent(path); parent = linkOption == LinkOption.NOFOLLOW_LINKS ? parent : readIfSymbolicLink(parent); if (parent == null) { return null; } final boolean exists = linkOption == null ? Files.exists(parent) : Files.exists(parent, linkOption); return exists ? parent : 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 subdirectories. *

* 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 subdirectories. *

* 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 subdirectories. *

* 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 subdirectories. * * @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 subdirectories. * * @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 { final LinkOption[] linkOptions = PathUtils.noFollowLinkOptionArray(); // POSIX ops will noop on non-POSIX. return withPosixFileAttributes(getParent(directory), linkOptions, overrideReadOnly(deleteOptions), pfa -> visitFileTree(new DeletingPathVisitor(Counters.longPathCounters(), linkOptions, deleteOptions), directory).getPathCounters()); } /** * Deletes a directory including subdirectories. * * @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, noFollowLinkOptionArray(), 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 { // // TODO Needs clean up // if (Files.isDirectory(file, linkOptions)) { throw new NoSuchFileException(file.toString()); } final PathCounters pathCounts = Counters.longPathCounters(); boolean exists = exists(file, linkOptions); long size = exists && !Files.isSymbolicLink(file) ? Files.size(file) : 0; try { if (Files.deleteIfExists(file)) { pathCounts.getFileCounter().increment(); pathCounts.getByteCounter().add(size); return pathCounts; } } catch (final AccessDeniedException ignored) { // Ignore and try again below. } final Path parent = getParent(file); PosixFileAttributes posixFileAttributes = null; try { if (overrideReadOnly(deleteOptions)) { posixFileAttributes = readPosixFileAttributes(parent, linkOptions); setReadOnly(file, false, linkOptions); } // Read size _after_ having read/execute access on POSIX. exists = exists(file, linkOptions); size = exists && !Files.isSymbolicLink(file) ? Files.size(file) : 0; if (Files.deleteIfExists(file)) { pathCounts.getFileCounter().increment(); pathCounts.getByteCounter().add(size); } } finally { if (posixFileAttributes != null) { Files.setPosixFilePermissions(parent, posixFileAttributes.permissions()); } } return pathCounts; } /** * Delegates to {@link File#deleteOnExit()}. * * @param path the path to delete. * @since 3.13.0 */ public static void deleteOnExit(final Path path) { Objects.requireNonNull(path.toFile()).deleteOnExit(); } /** * 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 * subdirectories. * * @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 * subdirectories. * * @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 (notExists(path1) && 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 * subdirectories. * * @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 * subdirectories. * * @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; } private static boolean exists(final Path path, final LinkOption... options) { Objects.requireNonNull(path, "path"); return options != null ? Files.exists(path, options) : Files.exists(path); } /** * 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 RandomAccessFileMode#create(Path)}. *

* * @param path1 the first stream. * @param path2 the second stream. * @param linkOptions options specifying how files are followed. * @param openOptions ignored. * @return true if the content of the streams are equal or they both don't exist, false otherwise. * @throws NullPointerException if openOptions 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 = exists(nPath1, linkOptions); if (path1Exists != 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; } // Faster: try (RandomAccessFile raf1 = RandomAccessFileMode.READ_ONLY.create(path1.toRealPath(linkOptions)); RandomAccessFile raf2 = RandomAccessFileMode.READ_ONLY.create(path2.toRealPath(linkOptions))) { return RandomAccessFiles.contentEquals(raf1, raf2); } catch (final UnsupportedOperationException e) { // Slower: // Handle // java.lang.UnsupportedOperationException // at com.sun.nio.zipfs.ZipPath.toFile(ZipPath.java:656) try (InputStream inputStream1 = Files.newInputStream(nPath1, openOptions); 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 NullPointerException if the filter is {@code null} * @throws IllegalArgumentException if {@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 given 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 = getAclFileAttributeView(sourcePath); return fileAttributeView == null ? null : fileAttributeView.getAcl(); } /** * Shorthand for {@code Files.getFileAttributeView(path, AclFileAttributeView.class)}. * * @param path the path to the file. * @param options how to handle symbolic links. * @return a AclFileAttributeView, or {@code null} if the attribute view type is not available. * @since 2.12.0 */ public static AclFileAttributeView getAclFileAttributeView(final Path path, final LinkOption... options) { return Files.getFileAttributeView(path, AclFileAttributeView.class, options); } /** * Gets the base name (the part up to and not including the last ".") of the last path segment of a file name. *

* Will return the file name itself if it doesn't contain any dots. All leading directories of the {@code file name} parameter are skipped. *

* * @return the base name of file name * @param path the path of the file to obtain the base name of. * @since 2.16.0 */ public static String getBaseName(final Path path) { if (path == null) { return null; } final Path fileName = path.getFileName(); return fileName != null ? FilenameUtils.removeExtension(fileName.toString()) : null; } /** * Shorthand for {@code Files.getFileAttributeView(path, DosFileAttributeView.class)}. * * @param path the path to the file. * @param options how to handle symbolic links. * @return a DosFileAttributeView, or {@code null} if the attribute view type is not available. * @since 2.12.0 */ public static DosFileAttributeView getDosFileAttributeView(final Path path, final LinkOption... options) { return Files.getFileAttributeView(path, DosFileAttributeView.class, options); } /** * Gets the extension of a Path. *

* This method returns the textual part of the Path after the last 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. *

* * @param path the path to query. * @return the extension of the file or an empty string if none exists or {@code null} if the fileName is {@code null}. * @since 2.16.0 */ public static String getExtension(final Path path) { final String fileName = getFileNameString(path); return fileName != null ? FilenameUtils.getExtension(fileName) : null; } /** * Gets the Path's file name and apply the given function if the file name is non-null. * * @param The function's result type. * @param path the path to query. * @param function function to apply to the file name. * @return the Path's file name as a string or null. * @see Path#getFileName() * @since 2.16.0 */ public static R getFileName(final Path path, final Function function) { final Path fileName = path != null ? path.getFileName() : null; return fileName != null ? function.apply(fileName) : null; } /** * Gets the Path's file name as a string. * * @param path the path to query. * @return the Path's file name as a string or null. * @see Path#getFileName() * @since 2.16.0 */ public static String getFileNameString(final Path path) { return getFileName(path, Path::toString); } /** * Gets the file's last modified time or null if the file does not exist. *

* The method provides a workaround for bug JDK-8177809 where {@link File#lastModified()} * looses milliseconds and always ends in 000. This bug is in OpenJDK 8 and 9, and fixed in 11. *

* * @param file the file to query. * @return the file's last modified time. * @throws IOException Thrown if an I/O error occurs. * @since 2.12.0 */ public static FileTime getLastModifiedFileTime(final File file) throws IOException { return getLastModifiedFileTime(file.toPath(), null, EMPTY_LINK_OPTION_ARRAY); } /** * Gets the file's last modified time or null if the file does not exist. * * @param path the file to query. * @param defaultIfAbsent Returns this file time of the file does not exist, may be null. * @param options options indicating how symbolic links are handled. * @return the file's last modified time. * @throws IOException Thrown if an I/O error occurs. * @since 2.12.0 */ public static FileTime getLastModifiedFileTime(final Path path, final FileTime defaultIfAbsent, final LinkOption... options) throws IOException { return Files.exists(path) ? getLastModifiedTime(path, options) : defaultIfAbsent; } /** * Gets the file's last modified time or null if the file does not exist. * * @param path the file to query. * @param options options indicating how symbolic links are handled. * @return the file's last modified time. * @throws IOException Thrown if an I/O error occurs. * @since 2.12.0 */ public static FileTime getLastModifiedFileTime(final Path path, final LinkOption... options) throws IOException { return getLastModifiedFileTime(path, null, options); } /** * Gets the file's last modified time or null if the file does not exist. * * @param uri the file to query. * @return the file's last modified time. * @throws IOException Thrown if an I/O error occurs. * @since 2.12.0 */ public static FileTime getLastModifiedFileTime(final URI uri) throws IOException { return getLastModifiedFileTime(Paths.get(uri), null, EMPTY_LINK_OPTION_ARRAY); } /** * Gets the file's last modified time or null if the file does not exist. * * @param url the file to query. * @return the file's last modified time. * @throws IOException Thrown if an I/O error occurs. * @throws URISyntaxException if the URL is not formatted strictly according to RFC2396 and cannot be converted to a URI. * @since 2.12.0 */ public static FileTime getLastModifiedFileTime(final URL url) throws IOException, URISyntaxException { return getLastModifiedFileTime(url.toURI()); } private static FileTime getLastModifiedTime(final Path path, final LinkOption... options) throws IOException { return Files.getLastModifiedTime(Objects.requireNonNull(path, "path"), options); } private static Path getParent(final Path path) { return path == null ? null : path.getParent(); } /** * Shorthand for {@code Files.getFileAttributeView(path, PosixFileAttributeView.class)}. * * @param path the path to the file. * @param options how to handle symbolic links. * @return a PosixFileAttributeView, or {@code null} if the attribute view type is not available. * @since 2.12.0 */ public static PosixFileAttributeView getPosixFileAttributeView(final Path path, final LinkOption... options) { return Files.getFileAttributeView(path, PosixFileAttributeView.class, options); } /** * Gets a {@link Path} representing the system temporary directory. * * @return the system temporary directory. * @since 2.12.0 */ public static Path getTempDirectory() { return Paths.get(FileUtils.getTempDirectoryPath()); } /** * Tests whether the given {@link 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 to handle symbolic links * @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 given {@link Path} is newer than the given time reference. * * @param file the {@link Path} to test. * @param czdt the time reference. * @param options options indicating how to handle symbolic links. * @return true if the {@link 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.12.0 */ public static boolean isNewer(final Path file, final ChronoZonedDateTime czdt, final LinkOption... options) throws IOException { Objects.requireNonNull(czdt, "czdt"); return isNewer(file, czdt.toInstant(), options); } /** * Tests if the given {@link Path} is newer than the given time reference. * * @param file the {@link Path} to test. * @param fileTime the time reference. * @param options options indicating how to handle symbolic links. * @return true if the {@link 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.12.0 */ public static boolean isNewer(final Path file, final FileTime fileTime, final LinkOption... options) throws IOException { if (notExists(file)) { return false; } return compareLastModifiedTimeTo(file, fileTime, options) > 0; } /** * Tests if the given {@link Path} is newer than the given time reference. * * @param file the {@link Path} to test. * @param instant the time reference. * @param options options indicating how to handle symbolic links. * @return true if the {@link 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.12.0 */ public static boolean isNewer(final Path file, final Instant instant, final LinkOption... options) throws IOException { return isNewer(file, FileTime.from(instant), options); } /** * Tests if the given {@link Path} is newer than the given time reference. * * @param file the {@link Path} to test. * @param timeMillis the time reference measured in milliseconds since the epoch (00:00:00 GMT, January 1, 1970) * @param options options indicating how to handle symbolic links. * @return true if the {@link 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 { return isNewer(file, FileTime.fromMillis(timeMillis), options); } /** * Tests if the given {@link Path} is newer than the reference {@link Path}. * * @param file the {@link File} to test. * @param reference the {@link File} of which the modification date is used. * @return true if the {@link File} exists and has been modified more recently than the reference {@link File}. * @throws IOException if an I/O error occurs. * @since 2.12.0 */ public static boolean isNewer(final Path file, final Path reference) throws IOException { return isNewer(file, getLastModifiedTime(reference)); } /** * Tests if the given {@link Path} is older than the given time reference. * * @param file the {@link Path} to test. * @param fileTime the time reference. * @param options options indicating how to handle symbolic links. * @return true if the {@link Path} exists and has been modified before the given time reference. * @throws IOException if an I/O error occurs. * @throws NullPointerException if the file is {@code null}. * @since 2.12.0 */ public static boolean isOlder(final Path file, final FileTime fileTime, final LinkOption... options) throws IOException { if (notExists(file)) { return false; } return compareLastModifiedTimeTo(file, fileTime, options) < 0; } /** * Tests if the given {@link Path} is older than the given time reference. * * @param file the {@link Path} to test. * @param instant the time reference. * @param options options indicating how to handle symbolic links. * @return true if the {@link Path} exists and has been modified before the given time reference. * @throws IOException if an I/O error occurs. * @throws NullPointerException if the file is {@code null}. * @since 2.12.0 */ public static boolean isOlder(final Path file, final Instant instant, final LinkOption... options) throws IOException { return isOlder(file, FileTime.from(instant), options); } /** * Tests if the given {@link Path} is older than the given time reference. * * @param file the {@link Path} to test. * @param timeMillis the time reference measured in milliseconds since the epoch (00:00:00 GMT, January 1, 1970) * @param options options indicating how to handle symbolic links. * @return true if the {@link Path} exists and has been modified before the given time reference. * @throws IOException if an I/O error occurs. * @throws NullPointerException if the file is {@code null}. * @since 2.12.0 */ public static boolean isOlder(final Path file, final long timeMillis, final LinkOption... options) throws IOException { return isOlder(file, FileTime.fromMillis(timeMillis), options); } /** * Tests if the given {@link Path} is older than the reference {@link Path}. * * @param file the {@link File} to test. * @param reference the {@link File} of which the modification date is used. * @return true if the {@link File} exists and has been modified before than the reference {@link File}. * @throws IOException if an I/O error occurs. * @since 2.12.0 */ public static boolean isOlder(final Path file, final Path reference) throws IOException { return isOlder(file, getLastModifiedTime(reference)); } /** * Tests whether the given path is on a POSIX file system. * * @param test The Path to test. * @param options options indicating how to handle symbolic links. * @return true if test is on a POSIX file system. * @since 2.12.0 */ public static boolean isPosix(final Path test, final LinkOption... options) { return exists(test, options) && readPosixFileAttributes(test, options) != null; } /** * Tests whether the given {@link 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 to handle symbolic links. * @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. *

* If you don't use the try-with-resources construct, then you must call the stream's {@link Stream#close()} method after iteration is complete to free any * resources held for the open 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)); } /** * Creates a new OutputStream by opening or creating a file, returning an output stream that may be used to write bytes to the file. * * @param path the Path. * @param append Whether or not to append. * @return a new OutputStream. * @throws IOException if an I/O error occurs. * @see Files#newOutputStream(Path, OpenOption...) * @since 2.12.0 */ public static OutputStream newOutputStream(final Path path, final boolean append) throws IOException { return newOutputStream(path, EMPTY_LINK_OPTION_ARRAY, append ? OPEN_OPTIONS_APPEND : OPEN_OPTIONS_TRUNCATE); } static OutputStream newOutputStream(final Path path, final LinkOption[] linkOptions, final OpenOption... openOptions) throws IOException { if (!exists(path, linkOptions)) { createParentDirectories(path, linkOptions != null && linkOptions.length > 0 ? linkOptions[0] : NULL_LINK_OPTION); } final List list = new ArrayList<>(Arrays.asList(openOptions != null ? openOptions : EMPTY_OPEN_OPTION_ARRAY)); list.addAll(Arrays.asList(linkOptions != null ? linkOptions : EMPTY_LINK_OPTION_ARRAY)); return Files.newOutputStream(path, list.toArray(EMPTY_OPEN_OPTION_ARRAY)); } /** * Copy of the {@link LinkOption} array for {@link LinkOption#NOFOLLOW_LINKS}. * * @return Copy of the {@link LinkOption} array for {@link LinkOption#NOFOLLOW_LINKS}. */ public static LinkOption[] noFollowLinkOptionArray() { return NOFOLLOW_LINK_OPTION_ARRAY.clone(); } private static boolean notExists(final Path path, final LinkOption... options) { return Files.notExists(Objects.requireNonNull(path, "path"), options); } /** * 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); } /** * Reads the BasicFileAttributes from the given path. Returns null if the attributes can't be read. * * @param The {@link BasicFileAttributes} type * @param path The Path to test. * @param type the {@link Class} of the file attributes required to read. * @param options options indicating how to handle symbolic links. * @return the file attributes or null if the attributes can't be read. * @see Files#readAttributes(Path, Class, LinkOption...) * @since 2.12.0 */ public static A readAttributes(final Path path, final Class type, final LinkOption... options) { try { return path == null ? null : Files.readAttributes(path, type, options); } catch (final UnsupportedOperationException | IOException e) { // For example, on Windows. return null; } } /** * Reads the BasicFileAttributes from the given path. * * @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); } /** * Reads the BasicFileAttributes from the given path. Returns null if the attributes can't be read. * * @param path the path to read. * @param options options indicating how to handle symbolic links. * @return the path attributes. * @since 2.12.0 */ public static BasicFileAttributes readBasicFileAttributes(final Path path, final LinkOption... options) { return readAttributes(path, BasicFileAttributes.class, options); } /** * Reads the BasicFileAttributes from the given path. Returns null if the attributes can't be read. * * @param path the path to read. * @return the path attributes. * @since 2.9.0 * @deprecated Use {@link #readBasicFileAttributes(Path, LinkOption...)}. */ @Deprecated public static BasicFileAttributes readBasicFileAttributesUnchecked(final Path path) { return readBasicFileAttributes(path, EMPTY_LINK_OPTION_ARRAY); } /** * Reads the DosFileAttributes from the given path. Returns null if the attributes can't be read. * * @param path the path to read. * @param options options indicating how to handle symbolic links. * @return the path attributes. * @since 2.12.0 */ public static DosFileAttributes readDosFileAttributes(final Path path, final LinkOption... options) { return readAttributes(path, DosFileAttributes.class, options); } private static Path readIfSymbolicLink(final Path path) throws IOException { return path != null ? Files.isSymbolicLink(path) ? Files.readSymbolicLink(path) : path : null; } /** * Reads the PosixFileAttributes or DosFileAttributes from the given path. Returns null if the attributes can't be read. * * @param path The Path to read. * @param options options indicating how to handle symbolic links. * @return the file attributes. * @since 2.12.0 */ public static BasicFileAttributes readOsFileAttributes(final Path path, final LinkOption... options) { final PosixFileAttributes fileAttributes = readPosixFileAttributes(path, options); return fileAttributes != null ? fileAttributes : readDosFileAttributes(path, options); } /** * Reads the PosixFileAttributes from the given path. Returns null instead of throwing {@link UnsupportedOperationException}. * * @param path The Path to read. * @param options options indicating how to handle symbolic links. * @return the file attributes. * @since 2.12.0 */ public static PosixFileAttributes readPosixFileAttributes(final Path path, final LinkOption... options) { return readAttributes(path, PosixFileAttributes.class, options); } /** * Reads the given path as a String. * * @param path The source path. * @param charset How to convert bytes to a String, null uses the default Charset. * @return a new String. * @throws IOException if an I/O error occurs reading from the stream. * @see Files#readAllBytes(Path) * @since 2.12.0 */ public static String readString(final Path path, final Charset charset) throws IOException { return new String(Files.readAllBytes(path), Charsets.toCharset(charset)); } /** * 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()); } /** * Requires that the given {@link File} exists and throws an {@link IllegalArgumentException} if it doesn't. * * @param file The {@link File} to check. * @param fileParamName The parameter name to use in the exception message in case of {@code null} input. * @param options options indicating how to handle symbolic links. * @return the given file. * @throws NullPointerException if the given {@link File} is {@code null}. * @throws IllegalArgumentException if the given {@link File} does not exist. */ private static Path requireExists(final Path file, final String fileParamName, final LinkOption... options) { Objects.requireNonNull(file, fileParamName); if (!exists(file, options)) { throw new IllegalArgumentException("File system element for parameter '" + fileParamName + "' does not exist: '" + file + "'"); } return file; } private static boolean setDosReadOnly(final Path path, final boolean readOnly, final LinkOption... linkOptions) throws IOException { final DosFileAttributeView dosFileAttributeView = getDosFileAttributeView(path, linkOptions); if (dosFileAttributeView != null) { dosFileAttributeView.setReadOnly(readOnly); return true; } return false; } /** * Sets the given {@code targetFile}'s last modified time to the value from {@code sourceFile}. * * @param sourceFile The source path to query. * @param targetFile The target path 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. * @since 2.12.0 */ public static void setLastModifiedTime(final Path sourceFile, final Path targetFile) throws IOException { Objects.requireNonNull(sourceFile, "sourceFile"); Files.setLastModifiedTime(targetFile, getLastModifiedTime(sourceFile)); } /** * To delete a file in POSIX, you need Write and Execute permissions on its parent directory. * * @param parent The parent path for a file element to delete which needs RW permissions. * @param enableDeleteChildren true to set permissions to delete. * @param linkOptions options indicating how handle symbolic links. * @return true if the operation was attempted and succeeded, false if parent is null. * @throws IOException if an I/O error occurs. */ private static boolean setPosixDeletePermissions(final Path parent, final boolean enableDeleteChildren, final LinkOption... linkOptions) throws IOException { // To delete a file in POSIX, you need write and execute permissions on its parent directory. // @formatter:off return setPosixPermissions(parent, enableDeleteChildren, Arrays.asList( PosixFilePermission.OWNER_WRITE, //PosixFilePermission.GROUP_WRITE, //PosixFilePermission.OTHERS_WRITE, PosixFilePermission.OWNER_EXECUTE //PosixFilePermission.GROUP_EXECUTE, //PosixFilePermission.OTHERS_EXECUTE ), linkOptions); // @formatter:on } /** * Low-level POSIX permission operation to set permissions. *

* If the permissions to update are already set, then make no additional calls. *

* * @param path Set this path's permissions. * @param addPermissions true to add, false to remove. * @param updatePermissions the List of PosixFilePermission to add or remove. * @param linkOptions options indicating how handle symbolic links. * @return true if the operation was attempted and succeeded, false if parent is null. * @throws IOException if an I/O error occurs. */ private static boolean setPosixPermissions(final Path path, final boolean addPermissions, final List updatePermissions, final LinkOption... linkOptions) throws IOException { if (path != null) { final Set permissions = Files.getPosixFilePermissions(path, linkOptions); final Set newPermissions = new HashSet<>(permissions); if (addPermissions) { newPermissions.addAll(updatePermissions); } else { newPermissions.removeAll(updatePermissions); } if (!newPermissions.equals(permissions)) { Files.setPosixFilePermissions(path, newPermissions); } return true; } return false; } private static void setPosixReadOnlyFile(final Path path, final boolean readOnly, final LinkOption... linkOptions) throws IOException { // Not Windows 10 final Set permissions = Files.getPosixFilePermissions(path, linkOptions); // @formatter:off final List readPermissions = Arrays.asList( PosixFilePermission.OWNER_READ //PosixFilePermission.GROUP_READ, //PosixFilePermission.OTHERS_READ ); final List writePermissions = Arrays.asList( PosixFilePermission.OWNER_WRITE //PosixFilePermission.GROUP_WRITE, //PosixFilePermission.OTHERS_WRITE ); // @formatter:on if (readOnly) { // RO: We can read, we cannot write. permissions.addAll(readPermissions); permissions.removeAll(writePermissions); } else { // Not RO: We can read, we can write. permissions.addAll(readPermissions); permissions.addAll(writePermissions); } Files.setPosixFilePermissions(path, permissions); } /** * 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 to handle symbolic links. * @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 { try { // Windows is simplest if (setDosReadOnly(path, readOnly, linkOptions)) { return path; } } catch (final IOException ignored) { // Retry with POSIX below. } final Path parent = getParent(path); if (!isPosix(parent, linkOptions)) { // Test parent because we may not the permissions to test the file. throw new IOException(String.format("DOS or POSIX file operations not available for '%s' %s", path, Arrays.toString(linkOptions))); } // POSIX if (readOnly) { // RO // File, then parent dir (if any). setPosixReadOnlyFile(path, readOnly, linkOptions); setPosixDeletePermissions(parent, false, linkOptions); } else { // RE // Parent dir (if any), then file. setPosixDeletePermissions(parent, true, linkOptions); } return path; } /** * Returns the size of the given file or directory. If the provided {@link Path} is a regular file, then the file's size is returned. If the argument is a * directory, then the size of the directory is calculated recursively. *

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

* * @param path 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, in bytes. * @throws NullPointerException if the file is {@code null}. * @throws IllegalArgumentException if the file does not exist. * @throws IOException if an I/O error occurs. * @since 2.12.0 */ public static long sizeOf(final Path path) throws IOException { requireExists(path, "path"); return Files.isDirectory(path) ? sizeOfDirectory(path) : Files.size(path); } /** * Returns the size of the given file or directory. If the provided {@link Path} is a regular file, then the file's size is returned. If the argument is a * directory, then the size of the directory is calculated recursively. * * @param path 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. * @throws IOException if an I/O error occurs. * @since 2.12.0 */ public static BigInteger sizeOfAsBigInteger(final Path path) throws IOException { requireExists(path, "path"); return Files.isDirectory(path) ? sizeOfDirectoryAsBigInteger(path) : BigInteger.valueOf(Files.size(path)); } /** * Counts the size of a directory recursively (sum of the size of all files). *

* Note that overflow is not detected, and the return value may be negative if overflow occurs. See {@link #sizeOfDirectoryAsBigInteger(Path)} 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}. * @throws IOException if an I/O error occurs. * @since 2.12.0 */ public static long sizeOfDirectory(final Path directory) throws IOException { return countDirectory(directory).getByteCounter().getLong(); } /** * Counts the size of a directory recursively (sum of the size 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}. * @throws IOException if an I/O error occurs. * @since 2.12.0 */ public static BigInteger sizeOfDirectoryAsBigInteger(final Path directory) throws IOException { return countDirectoryAsBigInteger(directory).getByteCounter().getBigInteger(); } /** * 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()); } /** * Implements behavior similar to the UNIX "touch" utility. Creates a new file with size 0, or, if the file exists, just updates the file's modified time. * this method creates parent directories if they do not exist. * * @param file the file to touch. * @return The given file. * @throws NullPointerException if the parameter is {@code null}. * @throws IOException if setting the last-modified time failed or an I/O problem occurs.\ * @since 2.12.0 */ public static Path touch(final Path file) throws IOException { Objects.requireNonNull(file, "file"); if (!Files.exists(file)) { createParentDirectories(file); Files.createFile(file); } else { FileTimes.setLastModifiedTime(file); } return file; } /** * 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 NoSuchFileException if the directory does not exist. * @throws IOException if an I/O error is thrown by a visitor method. * @throws NullPointerException if the directory is {@code null}. */ 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)); } /** * Waits for the file system to propagate a file creation, with a timeout. *

* This method repeatedly tests {@link Files#exists(Path,LinkOption...)} until it returns true up to the maximum time given. *

* * @param file the file to check, must not be {@code null}. * @param timeout the maximum time to wait. * @param options options indicating how to handle symbolic links. * @return true if file exists. * @throws NullPointerException if the file is {@code null}. * @since 2.12.0 */ public static boolean waitFor(final Path file, final Duration timeout, final LinkOption... options) { Objects.requireNonNull(file, "file"); final Instant finishInstant = Instant.now().plus(timeout); boolean interrupted = false; final long minSleepMillis = 100; try { while (!exists(file, options)) { final Instant now = Instant.now(); if (now.isAfter(finishInstant)) { return false; } try { ThreadUtils.sleep(Duration.ofMillis(Math.min(minSleepMillis, finishInstant.minusMillis(now.toEpochMilli()).toEpochMilli()))); } catch (final InterruptedException ignore) { interrupted = true; } catch (final Exception ex) { break; } } } finally { if (interrupted) { Thread.currentThread().interrupt(); } } return exists(file, options); } /** * Returns a stream of filtered paths. *

* The returned {@link Stream} may wrap one or more {@link DirectoryStream}s. When you require timely disposal of file system resources, use a * {@code try}-with-resources block to ensure invocation of the stream's {@link Stream#close()} method after the stream operations are completed. Calling a * closed stream causes a {@link IllegalStateException}. *

* * @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 */ @SuppressWarnings("resource") // Caller closes 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); } private static R withPosixFileAttributes(final Path path, final LinkOption[] linkOptions, final boolean overrideReadOnly, final IOFunction function) throws IOException { final PosixFileAttributes posixFileAttributes = overrideReadOnly ? readPosixFileAttributes(path, linkOptions) : null; try { return function.apply(posixFileAttributes); } finally { if (posixFileAttributes != null && path != null && Files.exists(path, linkOptions)) { Files.setPosixFilePermissions(path, posixFileAttributes.permissions()); } } } /** * Writes the given character sequence to a file at the given path. * * @param path The target file. * @param charSequence The character sequence text. * @param charset The Charset to encode the text. * @param openOptions options How to open the file. * @return The given path. * @throws IOException if an I/O error occurs writing to or creating the file. * @throws NullPointerException if either {@code path} or {@code charSequence} is {@code null}. * @since 2.12.0 */ public static Path writeString(final Path path, final CharSequence charSequence, final Charset charset, final OpenOption... openOptions) throws IOException { // Check the text is not null before opening file. Objects.requireNonNull(path, "path"); Objects.requireNonNull(charSequence, "charSequence"); Files.write(path, String.valueOf(charSequence).getBytes(Charsets.toCharset(charset)), openOptions); return path; } /** * Prevents instantiation. */ private PathUtils() { // do not instantiate. } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/file/PathVisitor.java0100644 0000000 0000000 00000002034 14603604450 027572 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.16.1-src/src/main/java/org/apache/commons/io/file/SimplePathVisitor.java0100644 0000000 0000000 00000003743 14603604450 030754 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.Path; import java.nio.file.SimpleFileVisitor; import java.util.Objects; import org.apache.commons.io.function.IOBiFunction; /** * A {@link SimpleFileVisitor} typed to a {@link Path}. * * @since 2.7 */ public abstract class SimplePathVisitor extends SimpleFileVisitor implements PathVisitor { private final IOBiFunction visitFileFailedFunction; /** * Constructs a new instance. */ protected SimplePathVisitor() { this.visitFileFailedFunction = super::visitFileFailed; } /** * Constructs a new instance. * * @param visitFileFailed Called on {@link #visitFileFailed(Path, IOException)}. */ protected SimplePathVisitor(final IOBiFunction visitFileFailed) { this.visitFileFailedFunction = Objects.requireNonNull(visitFileFailed, "visitFileFailed"); } @Override public FileVisitResult visitFileFailed(final Path file, final IOException exc) throws IOException { return visitFileFailedFunction.apply(file, exc); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/file/StandardDeleteOption.java0100644 0000000 0000000 00000003350 14603604450 031374 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.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, on POSIX, this means Write and Execute on the parent. */ 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; } return Stream.of(options).anyMatch(e -> StandardDeleteOption.OVERRIDE_READ_ONLY == e); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/file/attribute/FileTimes.java0100644 0000000 0000000 00000024417 14603604450 031213 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.attribute; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.attribute.FileTime; import java.time.Instant; import java.util.Date; import java.util.concurrent.TimeUnit; /** * Helps use {@link FileTime} and interoperate Date and NTFS times. * * @since 2.12.0 */ public final class FileTimes { /** * Constant for the {@code 1970-01-01T00:00:00Z} {@link Instant#EPOCH epoch} as a time stamp attribute. * * @see Instant#EPOCH */ public static final FileTime EPOCH = FileTime.from(Instant.EPOCH); /** * The offset of Windows time 0 to UNIX epoch in 100-nanosecond intervals. * *
Windows File Times *

* A file time is a 64-bit value that represents the number of 100-nanosecond intervals that have elapsed since 12:00 * A.M. January 1, 1601 Coordinated Universal Time (UTC). This is the offset of Windows time 0 to UNIX epoch in * 100-nanosecond intervals. *

*/ static final long WINDOWS_EPOCH_OFFSET = -116444736000000000L; /** * The amount of 100-nanosecond intervals in one second. */ private static final long HUNDRED_NANOS_PER_SECOND = TimeUnit.SECONDS.toNanos(1) / 100; /** * The amount of 100-nanosecond intervals in one millisecond. */ static final long HUNDRED_NANOS_PER_MILLISECOND = TimeUnit.MILLISECONDS.toNanos(1) / 100; /** * Converts standard UNIX time (in seconds, UTC/GMT) to {@link FileTime}. * * @param time UNIX timestamp (seconds). * @return the corresponding FileTime. * @since 2.16.0 */ public static FileTime fromUnixTime(final long time) { return FileTime.from(time, TimeUnit.SECONDS); } /** * Tests whether a FileTime can be safely represented in the standard UNIX time. *

* If the FileTime is null, this method returns true. *

* * @param time the FileTime to evaluate, can be null. * @return true if the time exceeds the minimum or maximum UNIX time, false otherwise. * @since 2.16.0 */ public static boolean isUnixTime(final FileTime time) { return isUnixTime(toUnixTime(time)); } /** * Tests whether a given number of seconds (since Epoch) can be safely represented in the standard UNIX time. * * @param seconds the number of seconds (since Epoch) to evaluate. * @return true if the time can be represented in the standard UNIX time, false otherwise. * @since 2.16.0 */ public static boolean isUnixTime(final long seconds) { return Integer.MIN_VALUE <= seconds && seconds <= Integer.MAX_VALUE; } /** * Subtracts milliseconds from a source FileTime. * * @param fileTime The source FileTime. * @param millisToSubtract The milliseconds to subtract. * @return The resulting FileTime. */ public static FileTime minusMillis(final FileTime fileTime, final long millisToSubtract) { return FileTime.from(fileTime.toInstant().minusMillis(millisToSubtract)); } /** * Subtracts nanoseconds from a source FileTime. * * @param fileTime The source FileTime. * @param nanosToSubtract The nanoseconds to subtract. * @return The resulting FileTime. */ public static FileTime minusNanos(final FileTime fileTime, final long nanosToSubtract) { return FileTime.from(fileTime.toInstant().minusNanos(nanosToSubtract)); } /** * Subtracts seconds from a source FileTime. * * @param fileTime The source FileTime. * @param secondsToSubtract The seconds to subtract. * @return The resulting FileTime. */ public static FileTime minusSeconds(final FileTime fileTime, final long secondsToSubtract) { return FileTime.from(fileTime.toInstant().minusSeconds(secondsToSubtract)); } /** * Obtains the current instant FileTime from the system clock. * * @return the current instant FileTime from the system clock. */ public static FileTime now() { return FileTime.from(Instant.now()); } /** * Converts NTFS time (100 nanosecond units since 1 January 1601) to Java time. * * @param ntfsTime the NTFS time in 100 nanosecond units * @return the Date */ public static Date ntfsTimeToDate(final long ntfsTime) { final long javaHundredNanos = Math.addExact(ntfsTime, WINDOWS_EPOCH_OFFSET); final long javaMillis = Math.floorDiv(javaHundredNanos, HUNDRED_NANOS_PER_MILLISECOND); return new Date(javaMillis); } /** * Converts NTFS time (100-nanosecond units since 1 January 1601) to a FileTime. * * @param ntfsTime the NTFS time in 100-nanosecond units * @return the FileTime * * @see #toNtfsTime(FileTime) */ public static FileTime ntfsTimeToFileTime(final long ntfsTime) { final long javaHundredsNanos = Math.addExact(ntfsTime, WINDOWS_EPOCH_OFFSET); final long javaSeconds = Math.floorDiv(javaHundredsNanos, HUNDRED_NANOS_PER_SECOND); final long javaNanos = Math.floorMod(javaHundredsNanos, HUNDRED_NANOS_PER_SECOND) * 100; return FileTime.from(Instant.ofEpochSecond(javaSeconds, javaNanos)); } /** * Adds milliseconds to a source FileTime. * * @param fileTime The source FileTime. * @param millisToAdd The milliseconds to add. * @return The resulting FileTime. */ public static FileTime plusMillis(final FileTime fileTime, final long millisToAdd) { return FileTime.from(fileTime.toInstant().plusMillis(millisToAdd)); } /** * Adds nanoseconds from a source FileTime. * * @param fileTime The source FileTime. * @param nanosToSubtract The nanoseconds to subtract. * @return The resulting FileTime. */ public static FileTime plusNanos(final FileTime fileTime, final long nanosToSubtract) { return FileTime.from(fileTime.toInstant().plusNanos(nanosToSubtract)); } /** * Adds seconds to a source FileTime. * * @param fileTime The source FileTime. * @param secondsToAdd The seconds to add. * @return The resulting FileTime. */ public static FileTime plusSeconds(final FileTime fileTime, final long secondsToAdd) { return FileTime.from(fileTime.toInstant().plusSeconds(secondsToAdd)); } /** * Sets the last modified time of the given file path to now. * * @param path The file path to set. * @throws IOException if an I/O error occurs. */ public static void setLastModifiedTime(final Path path) throws IOException { Files.setLastModifiedTime(path, now()); } /** * Converts {@link FileTime} to a {@link Date}. If the provided FileTime is {@code null}, the returned Date is also * {@code null}. * * @param fileTime the file time to be converted. * @return a {@link Date} which corresponds to the supplied time, or {@code null} if the time is {@code null}. * @see #toFileTime(Date) */ public static Date toDate(final FileTime fileTime) { return fileTime != null ? new Date(fileTime.toMillis()) : null; } /** * Converts {@link Date} to a {@link FileTime}. If the provided Date is {@code null}, the returned FileTime is also * {@code null}. * * @param date the date to be converted. * @return a {@link FileTime} which corresponds to the supplied date, or {@code null} if the date is {@code null}. * @see #toDate(FileTime) */ public static FileTime toFileTime(final Date date) { return date != null ? FileTime.fromMillis(date.getTime()) : null; } /** * Converts a {@link Date} to NTFS time. * * @param date the Date * @return the NTFS time */ public static long toNtfsTime(final Date date) { final long javaHundredNanos = date.getTime() * HUNDRED_NANOS_PER_MILLISECOND; return Math.subtractExact(javaHundredNanos, WINDOWS_EPOCH_OFFSET); } /** * Converts a {@link FileTime} to NTFS time (100-nanosecond units since 1 January 1601). * * @param fileTime the FileTime * @return the NTFS time in 100-nanosecond units */ public static long toNtfsTime(final FileTime fileTime) { final Instant instant = fileTime.toInstant(); final long javaHundredNanos = instant.getEpochSecond() * HUNDRED_NANOS_PER_SECOND + instant.getNano() / 100; return Math.subtractExact(javaHundredNanos, WINDOWS_EPOCH_OFFSET); } /** * Converts Java time (milliseconds since Epoch) to NTFS time. * * @param javaTime the Java time * @return the NTFS time * @since 2.16.0 */ public static long toNtfsTime(final long javaTime) { final long javaHundredNanos = javaTime * HUNDRED_NANOS_PER_MILLISECOND; return Math.subtractExact(javaHundredNanos, WINDOWS_EPOCH_OFFSET); } /** * Converts {@link FileTime} to standard UNIX time in seconds. *

* The returned seconds value may lie out of bounds of UNIX time. Check with {@link FileTimes#isUnixTime(long)}. *

* * @param fileTime the original FileTime. * @return the UNIX timestamp or 0 if the input is null. * @see #isUnixTime(long) * @since 2.16.0 */ public static long toUnixTime(final FileTime fileTime) { return fileTime != null ? fileTime.to(TimeUnit.SECONDS) : 0; } private FileTimes() { // No instances. } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/file/attribute/package-info.java0100644 0000000 0000000 00000001630 14603604450 031646 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Provides help using {@link java.nio.file.attribute} types. */ package org.apache.commons.io.file.attribute; commons-io-2.16.1-src/src/main/java/org/apache/commons/io/file/package-info.java0100644 0000000 0000000 00000001616 14603604450 027647 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Provides extensions in the realm of {@link java.nio.file}. */ package org.apache.commons.io.file; commons-io-2.16.1-src/src/main/java/org/apache/commons/io/file/spi/FileSystemProviders.java0100644 0000000 0000000 00000007316 14603604450 032103 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.Collections; import java.util.List; import java.util.Objects; /** * Helps to work with {@link FileSystemProvider}. * * @since 2.9.0 */ public class FileSystemProviders { // NOPMD Class will be final in 3.0. 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 != null ? providers : Collections.emptyList(); } /** * 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. return providers.stream().filter(provider -> provider.getScheme().equalsIgnoreCase(scheme)).findFirst().orElse(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.16.1-src/src/main/java/org/apache/commons/io/file/spi/package-info.java0100644 0000000 0000000 00000001651 14603604450 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. */ /** * Provides extensions in the realm of {@link java.nio.file.spi}. * * @since 2.9.0 */ package org.apache.commons.io.file.spi; commons-io-2.16.1-src/src/main/java/org/apache/commons/io/filefilter/AbstractFileFilter.java0100644 0000000 0000000 00000012550 14603604450 032241 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.List; import java.util.Objects; import org.apache.commons.io.file.PathFilter; import org.apache.commons.io.file.PathVisitor; import org.apache.commons.io.function.IOSupplier; /** * 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 toDefaultFileVisitResult(final boolean accept) { return accept ? FileVisitResult.CONTINUE : FileVisitResult.TERMINATE; } /** * What to do when this filter accepts. */ private final FileVisitResult onAccept; /** * What to do when this filter rejects. */ private final FileVisitResult onReject; /** * Constructs a new instance. */ public AbstractFileFilter() { this(FileVisitResult.CONTINUE, FileVisitResult.TERMINATE); } /** * Constructs a new instance. * * @param onAccept What to do on acceptance. * @param onReject What to do on rejection. * @since 2.12.0. */ protected AbstractFileFilter(final FileVisitResult onAccept, final FileVisitResult onReject) { this.onAccept = onAccept; this.onReject = onReject; } /** * 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)); } void append(final List list, final StringBuilder buffer) { for (int i = 0; i < list.size(); i++) { if (i > 0) { buffer.append(","); } buffer.append(list.get(i)); } } void append(final Object[] array, final StringBuilder buffer) { for (int i = 0; i < array.length; i++) { if (i > 0) { buffer.append(","); } buffer.append(array[i]); } } FileVisitResult get(final IOSupplier supplier) { try { return supplier.get(); } catch (final IOException e) { return handle(e); } } /** * 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); } /** * Converts a boolean into a FileVisitResult. * * @param accept accepted or rejected. * @return a FileVisitResult. */ FileVisitResult toFileVisitResult(final boolean accept) { return accept ? onAccept : onReject; } /** * 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.16.1-src/src/main/java/org/apache/commons/io/filefilter/AgeFileFilter.java0100644 0000000 0000000 00000020065 14603604450 031172 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.time.Instant; 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 = PathUtils.current();
 * // We are interested in files older than one day
 * Instant cutoff = Instant.now().minus(Duration.ofDays(1));
 * String[] files = dir.list(new AgeFileFilter(cutoff));
 * for (String file : files) {
 *     System.out.println(file);
 * }
 * 
* *

Using NIO

*
 * Path dir = PathUtils.current();
 * // We are interested in files older than one day
 * Instant cutoff = Instant.now().minus(Duration.ofDays(1));
 * 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());
 * 
*

Deprecating Serialization

*

* Serialization is deprecated and will be removed in 3.0. *

* * @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 Instant cutoffInstant; /** * 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.toInstant(), 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 cutoffInstant The cutoff time threshold since the epoch (00:00:00 GMT, January 1, 1970). * @since 2.12.0 */ public AgeFileFilter(final Instant cutoffInstant) { this(cutoffInstant, true); } /** * Constructs a new age file filter for files on any one side of a certain cutoff. * * @param cutoffInstant The cutoff time threshold 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). * @since 2.12.0 */ public AgeFileFilter(final Instant cutoffInstant, final boolean acceptOlder) { this.acceptOlder = acceptOlder; this.cutoffInstant = cutoffInstant; } /** * 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(Instant.ofEpochMilli(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(Instant.ofEpochMilli(cutoffMillis), acceptOlder); } /** * 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) { return acceptOlder != FileUtils.isFileNewer(file, cutoffInstant); } /** * 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) { return get(() -> toFileVisitResult(acceptOlder != PathUtils.isNewer(file, cutoffInstant))); } /** * Provide a String representation of this file filter. * * @return a String representation */ @Override public String toString() { final String condition = acceptOlder ? "<=" : ">"; return super.toString() + "(" + condition + cutoffInstant + ")"; } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/filefilter/AndFileFilter.java0100644 0000000 0000000 00000013646 14603604450 031207 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; import java.util.stream.Stream; /** * 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}. *

Deprecating Serialization

*

* Serialization is deprecated and will be removed in 3.0. *

* * @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 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 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 of {@link 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) { return !isEmpty() && fileFilters.stream().allMatch(fileFilter -> fileFilter.accept(file)); } /** * {@inheritDoc} */ @Override public boolean accept(final File file, final String name) { return !isEmpty() && fileFilters.stream().allMatch(fileFilter -> fileFilter.accept(file, name)); } /** * {@inheritDoc} * @since 2.9.0 */ @Override public FileVisitResult accept(final Path file, final BasicFileAttributes attributes) { return isEmpty() ? FileVisitResult.TERMINATE : toDefaultFileVisitResult(fileFilters.stream().allMatch(fileFilter -> fileFilter.accept(file, attributes) == FileVisitResult.CONTINUE)); } /** * {@inheritDoc} */ @Override public void addFileFilter(final IOFileFilter fileFilter) { 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) { Stream.of(Objects.requireNonNull(fileFilters, "fileFilters")).forEach(this::addFileFilter); } /** * {@inheritDoc} */ @Override public List getFileFilters() { return Collections.unmodifiableList(fileFilters); } private boolean isEmpty() { return fileFilters.isEmpty(); } /** * {@inheritDoc} */ @Override public boolean removeFileFilter(final IOFileFilter ioFileFilter) { return fileFilters.remove(ioFileFilter); } /** * {@inheritDoc} */ @Override public void setFileFilters(final List fileFilters) { this.fileFilters.clear(); this.fileFilters.addAll(fileFilters); } /** * Builds 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("("); append(fileFilters, buffer); buffer.append(")"); return buffer.toString(); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/filefilter/CanExecuteFileFilter.java0100644 0000000 0000000 00000006146 14603604450 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 {@link 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 = FileUtils.current();
 * 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 = FileUtils.current();
 * String[] files = dir.list(CanExecuteFileFilter.CANNOT_EXECUTE);
 * for (int i = 0; i < files.length; i++) {
 *     System.out.println(files[i]);
 * }
 * 
*

Deprecating Serialization

*

* Serialization is deprecated and will be removed in 3.0. *

* * @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 != null && 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(file != null && Files.isExecutable(file)); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/filefilter/CanReadFileFilter.java0100644 0000000 0000000 00000006654 14603604450 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.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 {@link 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 = FileUtils.current();
 * 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 = FileUtils.current();
 * 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 = FileUtils.current();
 * String[] files = dir.list(CanReadFileFilter.READ_ONLY);
 * for (String file : files) {
 *     System.out.println(file);
 * }
 * 
*

Deprecating Serialization

*

* Serialization is deprecated and will be removed in 3.0. *

* * @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 != null && 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(file != null && Files.isReadable(file)); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/filefilter/CanWriteFileFilter.java0100644 0000000 0000000 00000006165 14603604450 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 {@link 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 = FileUtils.current();
 * 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 = FileUtils.current();
 * 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}. *

*

Deprecating Serialization

*

* Serialization is deprecated and will be removed in 3.0. *

* * @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 != null && 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(file != null && Files.isWritable(file)); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/filefilter/ConditionalFileFilter.java0100644 0000000 0000000 00000003643 14603604450 032744 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.16.1-src/src/main/java/org/apache/commons/io/filefilter/DelegateFileFilter.java0100644 0000000 0000000 00000006502 14603604450 032210 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; import java.util.Objects; /** * This class turns a Java FileFilter or FilenameFilter into an IO FileFilter. *

Deprecating Serialization

*

* Serialization is deprecated and will be removed in 3.0. *

* * @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 transient final FileFilter fileFilter; /** The Filename filter */ private transient final FilenameFilter fileNameFilter; /** * Constructs a delegate file filter around an existing FileFilter. * * @param fileFilter the filter to decorate */ public DelegateFileFilter(final FileFilter fileFilter) { Objects.requireNonNull(fileFilter, "filter"); this.fileFilter = fileFilter; this.fileNameFilter = null; } /** * Constructs a delegate file filter around an existing FilenameFilter. * * @param fileNameFilter the filter to decorate */ public DelegateFileFilter(final FilenameFilter fileNameFilter) { Objects.requireNonNull(fileNameFilter, "filter"); this.fileNameFilter = fileNameFilter; 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.16.1-src/src/main/java/org/apache/commons/io/filefilter/DirectoryFileFilter.java0100644 0000000 0000000 00000007062 14603604450 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 {@link 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 = FileUtils.current();
 * String[] files = dir.list(DirectoryFileFilter.INSTANCE);
 * for (String file : files) {
 *     System.out.println(file);
 * }
 * 
* *

Using NIO

* *
 * final Path dir = PathUtils.current();
 * 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());
 * 
*

Deprecating Serialization

*

* Serialization is deprecated and will be removed in 3.0. *

* * @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 != null && 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(file != null && Files.isDirectory(file)); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/filefilter/EmptyFileFilter.java0100644 0000000 0000000 00000010476 14603604450 031601 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.stream.Stream; import org.apache.commons.io.IOUtils; /** * This filter accepts files or directories that are empty. *

* If the {@link 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 = FileUtils.current();
 * 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 = FileUtils.current();
 * String[] files = dir.list(EmptyFileFilter.NOT_EMPTY);
 * for (String file : files) {
 *     System.out.println(file);
 * }
 * 
* *

Using NIO

*
 * final Path dir = PathUtils.current();
 * 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());
 * 
*

Deprecating Serialization

*

* Serialization is deprecated and will be removed in 3.0. *

* * @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 == null) { return true; } 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) { if (file == null) { return toFileVisitResult(true); } return get(() -> { if (Files.isDirectory(file)) { try (Stream stream = Files.list(file)) { return toFileVisitResult(!stream.findFirst().isPresent()); } } return toFileVisitResult(Files.size(file) == 0); }); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/filefilter/FalseFileFilter.java0100644 0000000 0000000 00000006226 14603604450 031533 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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. *

Deprecating Serialization

*

* Serialization is deprecated and will be removed in 3.0. *

* * @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 and(final IOFileFilter fileFilter) { // FALSE AND expression <=> FALSE return INSTANCE; } @Override public IOFileFilter negate() { return TrueFileFilter.INSTANCE; } @Override public IOFileFilter or(final IOFileFilter fileFilter) { // FALSE OR expression <=> expression return fileFilter; } @Override public String toString() { return TO_STRING; } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/filefilter/FileEqualsFileFilter.java0100644 0000000 0000000 00000003673 14603604450 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.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)); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/filefilter/FileFileFilter.java0100644 0000000 0000000 00000006576 14603604450 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.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 {@link 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 = FileUtils.current();
 * String[] files = dir.list(FileFileFilter.INSTANCE);
 * for (String file : files) {
 *     System.out.println(file);
 * }
 * 
* *

Using NIO

*
 * final Path dir = PathUtils.current();
 * 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());
 * 
*

Deprecating Serialization

*

* Serialization is deprecated and will be removed in 3.0. *

* * @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 != null && 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(file != null && Files.isRegularFile(file)); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/filefilter/FileFilterUtils.java0100644 0000000 0000000 00000063475 14603604450 031612 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.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 most * 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 CVS_FILTER = notFileFilter( and(directoryFileFilter(), nameFileFilter("CVS"))); /* Constructed on demand and then cached */ private static final IOFileFilter SVN_FILTER = 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 cutoffMillis the time threshold * @return an appropriately configured age file filter * @see AgeFileFilter * @since 1.2 */ public static IOFileFilter ageFileFilter(final long cutoffMillis) { return new AgeFileFilter(cutoffMillis); } /** * Returns a filter that filters files based on a cutoff time. * * @param cutoffMillis 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 cutoffMillis, final boolean acceptOlder) { return new AgeFileFilter(cutoffMillis, 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 {@link IOFileFilter} that wraps the * {@link 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 {@link IOFileFilter} that wraps the * {@link 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 NullPointerException 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) { Objects.requireNonNull(filter, "filter"); 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} * 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} 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 NullPointerException 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 (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 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 a bug in 1.0) */ public static IOFileFilter makeCVSAware(final IOFileFilter filter) { return filter == null ? CVS_FILTER : and(filter, CVS_FILTER); } /** * 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 ? SVN_FILTER : and(filter, SVN_FILTER); } /** * 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 ioCase 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 ioCase) { return new NameFileFilter(name, ioCase); } /** * 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 ioCase 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 ioCase) { return new PrefixFileFilter(prefix, ioCase); } /** * 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 ioCase 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 ioCase) { return new SuffixFileFilter(suffix, ioCase); } /** * Create a List of file filters. * * @param filters The file filters * @return The list of file filters * @throws NullPointerException if the filters are null or contain a * null value. * @since 2.0 */ public static List toList(final IOFileFilter... filters) { return Stream.of(Objects.requireNonNull(filters, "filters")).map(Objects::requireNonNull).collect(Collectors.toList()); } /** * 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.16.1-src/src/main/java/org/apache/commons/io/filefilter/HiddenFileFilter.java0100644 0000000 0000000 00000007220 14603604450 031667 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 {@link 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 = FileUtils.current();
 * 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 = FileUtils.current();
 * String[] files = dir.list(HiddenFileFilter.VISIBLE);
 * for (String file : files) {
 *     System.out.println(file);
 * }
 * 
* *

Using NIO

*
 * final Path dir = PathUtils.current();
 * 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());
 * 
*

Deprecating Serialization

*

* Serialization is deprecated and will be removed in 3.0. *

* * @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 == null || 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) { return get(() -> toFileVisitResult(file == null || Files.isHidden(file))); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/filefilter/IOFileFilter.java0100644 0000000 0000000 00000007112 14603604450 031003 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.PathMatcher; import java.nio.file.attribute.BasicFileAttributes; import org.apache.commons.io.file.PathFilter; /** * An interface which brings the {@link FileFilter}, {@link FilenameFilter}, {@link PathFilter}, and {@link PathMatcher} interfaces together. * * @since 1.0 */ public interface IOFileFilter extends FileFilter, FilenameFilter, PathFilter, PathMatcher { /** * An empty String array. */ String[] EMPTY_STRING_ARRAY = {}; /** * Tests if a 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); /** * Tests if a 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 a 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.toDefaultFileVisitResult(path != null && accept(path.toFile())); } /** * Constructs 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); } /** * Tests if a Path should be accepted by this filter. * * @param path the Path to check. * @return true if this path matches the test. * @since 2.14.0 */ @Override default boolean matches(final Path path) { return accept(path, null) != FileVisitResult.TERMINATE; } /** * Constructs a new "not" filter with this filter. * * @return a new filter. * @since 2.9.0 */ default IOFileFilter negate() { return new NotFileFilter(this); } /** * Constructs 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.16.1-src/src/main/java/org/apache/commons/io/filefilter/MagicNumberFileFilter.java0100644 0000000 0000000 00000026546 14603604450 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.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 java.util.Objects; import org.apache.commons.io.RandomAccessFileMode; import org.apache.commons.io.RandomAccessFiles; /** *

* 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 = FileUtils.current();
 * 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 = FileUtils.current();
 * MagicNumberFileFilter tarFileFilter =
 *     MagicNumberFileFilter("ustar", 257);
 * String[] tarFiles = dir.list(tarFileFilter);
 * for (String tarFile : tarFiles) {
 *     System.out.println(tarFile);
 * }
 * 
*

Using NIO

*
 * final Path dir = PathUtils.current();
 * 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());
 * 
*

Deprecating Serialization

*

* Serialization is deprecated and will be removed in 3.0. *

* *

Deprecating Serialization

*

* Serialization is deprecated and will be removed in 3.0. *

* * @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 magicNumbers 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} * contains no bytes, or {@code offset} * is a negative number. */ public MagicNumberFileFilter(final byte[] magicNumbers, final long offset) { Objects.requireNonNull(magicNumbers, "magicNumbers"); if (magicNumbers.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 = magicNumbers.clone(); 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 * the empty String, or {@code offset} is * a negative number. */ public MagicNumberFileFilter(final String magicNumber, final long offset) { Objects.requireNonNull(magicNumber, "magicNumber"); 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 (RandomAccessFile randomAccessFile = RandomAccessFileMode.READ_ONLY.create(file)) { return Arrays.equals(magicNumbers, RandomAccessFiles.read(randomAccessFile, byteOffset, magicNumbers.length)); } catch (final IOException ignored) { // 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 (FileChannel fileChannel = FileChannel.open(file)) { final ByteBuffer byteBuffer = ByteBuffer.allocate(this.magicNumbers.length); fileChannel.position(byteOffset); final int read = fileChannel.read(byteBuffer); if (read != magicNumbers.length) { return FileVisitResult.TERMINATE; } return toFileVisitResult(Arrays.equals(this.magicNumbers, byteBuffer.array())); } } catch (final IOException ignored) { // 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("("); // TODO perhaps use hex if value is not printable builder.append(new String(magicNumbers, Charset.defaultCharset())); builder.append(","); builder.append(this.byteOffset); builder.append(")"); return builder.toString(); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/filefilter/NameFileFilter.java0100644 0000000 0000000 00000016007 14603604450 031357 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 java.util.stream.Stream; import org.apache.commons.io.IOCase; import org.apache.commons.io.file.PathUtils; /** * 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 = FileUtils.current();
 * String[] files = dir.list(new NameFileFilter("Test"));
 * for (String file : files) {
 *     System.out.println(file);
 * }
 * 
* *

Using NIO

*
 * final Path dir = PathUtils.current();
 * 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());
 * 
*

Deprecating Serialization

*

* Serialization is deprecated and will be removed in 3.0. *

* * @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 ioCase; /** * 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 ioCase how to handle case sensitivity, null means case-sensitive * @throws NullPointerException if the name list is null * @throws ClassCastException if the list does not contain Strings */ public NameFileFilter(final List names, final IOCase ioCase) { Objects.requireNonNull(names, "names"); this.names = names.toArray(EMPTY_STRING_ARRAY); this.ioCase = toIOCase(ioCase); } /** * 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); } /** * Constructs a new name file filter specifying case-sensitivity. * * @param name the name to allow, must not be null * @param ioCase how to handle case sensitivity, null means case-sensitive * @throws NullPointerException if the name is null */ public NameFileFilter(final String name, final IOCase ioCase) { Objects.requireNonNull(name, "name"); this.names = new String[] {name}; this.ioCase = toIOCase(ioCase); } /** * 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 ioCase how to handle case sensitivity, null means case-sensitive * @throws NullPointerException if the names array is null */ public NameFileFilter(final String[] names, final IOCase ioCase) { Objects.requireNonNull(names, "names"); this.names = names.clone(); this.ioCase = toIOCase(ioCase); } /** * 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 file != null && 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 path the File to check * * @return true if the file name matches * @since 2.9.0 */ @Override public FileVisitResult accept(final Path path, final BasicFileAttributes attributes) { return toFileVisitResult(acceptBaseName(PathUtils.getFileNameString(path))); } private boolean acceptBaseName(final String baseName) { return Stream.of(names).anyMatch(testName -> ioCase.checkEquals(baseName, testName)); } private IOCase toIOCase(final IOCase ioCase) { return IOCase.value(ioCase, IOCase.SENSITIVE); } /** * 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("("); append(names, buffer); buffer.append(")"); return buffer.toString(); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/filefilter/NotFileFilter.java0100644 0000000 0000000 00000006365 14603604450 031245 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.Objects; /** * This filter produces a logical NOT of the filters specified. *

Deprecating Serialization

*

* Serialization is deprecated and will be removed in 3.0. *

* * @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 NullPointerException if the filter is null */ public NotFileFilter(final IOFileFilter filter) { Objects.requireNonNull(filter, "filter"); 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.16.1-src/src/main/java/org/apache/commons/io/filefilter/OrFileFilter.java0100644 0000000 0000000 00000013420 14603604450 031053 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; import java.util.stream.Stream; /** * 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}. *

Deprecating Serialization

*

* Serialization is deprecated and will be removed in 3.0. *

* * @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 {@link 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 {@link 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) { return fileFilters.stream().anyMatch(fileFilter -> fileFilter.accept(file)); } /** * {@inheritDoc} */ @Override public boolean accept(final File file, final String name) { return fileFilters.stream().anyMatch(fileFilter -> fileFilter.accept(file, name)); } /** * {@inheritDoc} */ @Override public FileVisitResult accept(final Path file, final BasicFileAttributes attributes) { return toDefaultFileVisitResult(fileFilters.stream().anyMatch(fileFilter -> fileFilter.accept(file, attributes) == 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) { Stream.of(Objects.requireNonNull(fileFilters, "fileFilters")).forEach(this::addFileFilter); } /** * {@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("("); append(fileFilters, buffer); buffer.append(")"); return buffer.toString(); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/filefilter/PathEqualsFileFilter.java0100644 0000000 0000000 00000003544 14603604450 032550 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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)); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/filefilter/PathMatcherFileFilter.java0100644 0000000 0000000 00000003210 14603604450 032667 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.Path; import java.nio.file.PathMatcher; import java.util.Objects; /** * Delegates matching to a {@link PathMatcher}. * * @since 2.14.0 */ public class PathMatcherFileFilter extends AbstractFileFilter { private final PathMatcher pathMatcher; /** * Constructs a new instance to perform matching with a PathMatcher. * * @param pathMatcher The PathMatcher delegate. */ public PathMatcherFileFilter(final PathMatcher pathMatcher) { this.pathMatcher = Objects.requireNonNull(pathMatcher, "pathMatcher"); } @Override public boolean accept(final File file) { return file != null && matches(file.toPath()); } @Override public boolean matches(final Path path) { return pathMatcher.matches(path); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/filefilter/PathVisitorFileFilter.java0100644 0000000 0000000 00000005406 14603604450 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.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) { return get(() -> Files.isDirectory(path) ? pathVisitor.postVisitDirectory(path, null) : visitFile(path, attributes)); } @Override public FileVisitResult visitFile(final Path path, final BasicFileAttributes attributes) throws IOException { return pathVisitor.visitFile(path, attributes); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/filefilter/PrefixFileFilter.java0100644 0000000 0000000 00000016431 14603604450 031735 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 java.util.stream.Stream; import org.apache.commons.io.IOCase; import org.apache.commons.io.file.PathUtils; /** * 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 = FileUtils.current();
 * String[] files = dir.list(new PrefixFileFilter("Test"));
 * for (String file : files) {
 *     System.out.println(file);
 * }
 * 
* *

Using NIO

*
 * final Path dir = PathUtils.current();
 * 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());
 * 
*

Deprecating Serialization

*

* Serialization is deprecated and will be removed in 3.0. *

* * @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 isCase; /** * Constructs a new Prefix file filter for a list of prefixes. * * @param prefixes the prefixes to allow, must not be null * @throws NullPointerException 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 ioCase how to handle case sensitivity, null means case-sensitive * @throws NullPointerException 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 ioCase) { Objects.requireNonNull(prefixes, "prefixes"); this.prefixes = prefixes.toArray(EMPTY_STRING_ARRAY); this.isCase = IOCase.value(ioCase, IOCase.SENSITIVE); } /** * 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 ioCase 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 ioCase) { Objects.requireNonNull(prefix, "prefix"); this.prefixes = new String[] {prefix}; this.isCase = IOCase.value(ioCase, IOCase.SENSITIVE); } /** * 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 ioCase 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 ioCase) { Objects.requireNonNull(prefixes, "prefixes"); this.prefixes = prefixes.clone(); this.isCase = IOCase.value(ioCase, IOCase.SENSITIVE); } /** * 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) { return toFileVisitResult(accept(PathUtils.getFileName(file, Path::toFile))); } private boolean accept(final String name) { return Stream.of(prefixes).anyMatch(prefix -> isCase.checkStartsWith(name, prefix)); } /** * 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("("); append(prefixes, buffer); buffer.append(")"); return buffer.toString(); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/filefilter/RegexFileFilter.java0100644 0000000 0000000 00000014767 14603604450 031564 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.Objects; import java.util.function.Function; import java.util.regex.Pattern; import org.apache.commons.io.IOCase; import org.apache.commons.io.file.PathUtils; /** * Filters files using supplied regular expression(s). *

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

*

Using Classic IO

*

* e.g. * *

 * File dir = FileUtils.current();
 * 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 = PathUtils.current();
 * 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());
 * 
*

Deprecating Serialization

*

* Serialization is deprecated and will be removed in 3.0. *

* * @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) { Objects.requireNonNull(pattern, "pattern"); return Pattern.compile(pattern, flags); } /** * Converts IOCase to Pattern compilation flags. * * @param ioCase case-sensitivity. * @return Pattern compilation flags. */ private static int toFlags(final IOCase ioCase) { return IOCase.isCaseSensitive(ioCase) ? 0 : Pattern.CASE_INSENSITIVE; } /** The regular expression pattern that will be used to match file names. */ private final Pattern pattern; /** How convert a path to a string. */ private transient final Function pathToString; /** * Constructs a new regular expression filter for a compiled regular expression * * @param pattern regular expression to match. * @throws NullPointerException if the pattern is null. */ @SuppressWarnings("unchecked") public RegexFileFilter(final Pattern pattern) { this(pattern, (Function & Serializable) PathUtils::getFileNameString); } /** * 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 NullPointerException if the pattern is null. * @since 2.10.0 */ public RegexFileFilter(final Pattern pattern, final Function pathToString) { Objects.requireNonNull(pattern, "pattern"); this.pattern = pattern; this.pathToString = pathToString != null ? pathToString : Objects::toString; } /** * Constructs a new regular expression filter. * * @param pattern regular string expression to match * @throws NullPointerException 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 ioCase how to handle case sensitivity, null means case-sensitive * @throws IllegalArgumentException if the pattern is null */ public RegexFileFilter(final String pattern, final IOCase ioCase) { this(compile(pattern, toFlags(ioCase))); } /** * 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) { final String result = pathToString.apply(path); return toFileVisitResult(result != null && pattern.matcher(result).matches()); } /** * Returns a debug string. * * @since 2.10.0 */ @Override public String toString() { return "RegexFileFilter [pattern=" + pattern + "]"; } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/filefilter/SizeFileFilter.java0100644 0000000 0000000 00000012426 14603604450 031412 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 = FileUtils.current();
 * String[] files = dir.list(new SizeFileFilter(1024 * 1024));
 * for (String file : files) {
 *     System.out.println(file);
 * }
 * 
* *

Using NIO

*
 * final Path dir = PathUtils.current();
 * 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());
 * 
*

Deprecating Serialization

*

* Serialization is deprecated and will be removed in 3.0. *

* * @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 != null ? file.length() : 0); } 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) { return get(() -> toFileVisitResult(accept(Files.size(file)))); } /** * 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))); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/filefilter/SuffixFileFilter.java0100644 0000000 0000000 00000016455 14603604450 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 java.util.stream.Stream; import org.apache.commons.io.IOCase; import org.apache.commons.io.file.PathUtils; /** * 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 = FileUtils.current();
 * String[] files = dir.list(new SuffixFileFilter(".java"));
 * for (String file : files) {
 *     System.out.println(file);
 * }
 * 
* *

Using NIO

*
 * final Path dir = PathUtils.current();
 * 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());
 * 
*

Deprecating Serialization

*

* Serialization is deprecated and will be removed in 3.0. *

* * @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 ioCase; /** * 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 ioCase 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 ioCase) { Objects.requireNonNull(suffixes, "suffixes"); this.suffixes = suffixes.toArray(EMPTY_STRING_ARRAY); this.ioCase = IOCase.value(ioCase, IOCase.SENSITIVE); } /** * 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 NullPointerException 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 ioCase how to handle case sensitivity, null means case-sensitive * @throws NullPointerException if the suffix is null * @since 1.4 */ public SuffixFileFilter(final String suffix, final IOCase ioCase) { Objects.requireNonNull(suffix, "suffix"); this.suffixes = new String[] {suffix}; this.ioCase = IOCase.value(ioCase, IOCase.SENSITIVE); } /** * 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 ioCase how to handle case sensitivity, null means case-sensitive * @throws NullPointerException if the suffix array is null * @since 1.4 */ public SuffixFileFilter(final String[] suffixes, final IOCase ioCase) { Objects.requireNonNull(suffixes, "suffixes"); this.suffixes = suffixes.clone(); this.ioCase = IOCase.value(ioCase, IOCase.SENSITIVE); } /** * 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 path 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 path, final BasicFileAttributes attributes) { return toFileVisitResult(accept(PathUtils.getFileNameString(path))); } private boolean accept(final String name) { return Stream.of(suffixes).anyMatch(suffix -> ioCase.checkEndsWith(name, suffix)); } /** * 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("("); append(suffixes, buffer); buffer.append(")"); return buffer.toString(); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/filefilter/SymbolicLinkFileFilter.java0100644 0000000 0000000 00000012503 14603604450 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 {@link 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 = FileUtils.current();
 * String[] files = dir.list(SymbolicLinkFileFilter.INSTANCE);
 * for (String file : files) {
 *     System.out.println(file);
 * }
 * 
* *

Using NIO

*
 * final Path dir = PathUtils.current();
 * final AccumulatorPathVisitor visitor = AccumulatorPathVisitor.withLongCounters(SymbolicLinkFileFilter.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());
 * 
*

Deprecating Serialization

*

* Serialization is deprecated and will be removed in 3.0. *

* * @since 2.11.0 * @see FileFilterUtils#fileFileFilter() */ public class SymbolicLinkFileFilter extends AbstractFileFilter implements Serializable { /* * Note to developers: The unit test needs to create symbolic links to files. However, on * Windows, this can't be done without admin privileges. This class is designed to allow a * unit test to works around this by doing two things: 1) This separates the class logic from * the call to identify a symbolic link, and 2) It allows the unit test to override that * symbolic link call on Windows only. * This means we can write unit tests that will run on all machines. On Windows, the unit test * can't create a symbolic link without admin privileges, so the unit tests won't * completely test all the necessary behavior on Windows, but they will still test the class * logic. Be careful not to break this, but be aware of it when writing unit tests. You can * still maintain this class and its unit tests on Windows. The one method that won't get * tested on Windows is not likely to change, and will be tested properly when it gets run * on Apache servers. */ /** * Singleton instance of file filter. */ public static final SymbolicLinkFileFilter INSTANCE = new SymbolicLinkFileFilter(); private static final long serialVersionUID = 1L; /** * Restrictive constructor. */ protected SymbolicLinkFileFilter() { } /** * Constructs a new instance. * * @param onAccept What to do on acceptance. * @param onReject What to do on rejection. * @since 2.12.0. */ public SymbolicLinkFileFilter(final FileVisitResult onAccept, final FileVisitResult onReject) { super(onAccept, onReject); } /** * Checks to see if the file is a symbolic link. * * @param file the File to check * @return true if the file exists and is a symbolic link to either another file or a directory, * false otherwise. */ @Override public boolean accept(final File file) { return isSymbolicLink(file.toPath()); } /** * Checks to see if the file is a symbolic link. * * @param path the File Path to check * @return {@code onAccept} from {@link #SymbolicLinkFileFilter(FileVisitResult, FileVisitResult)} if the file exists and is a symbolic link to either * another file or a directory; returns {@code onReject} otherwise. */ @Override public FileVisitResult accept(final Path path, final BasicFileAttributes attributes) { return toFileVisitResult(isSymbolicLink(path)); } /** * Delegates to {@link Files#isSymbolicLink(Path)} for testing. *

* Using package access for unit tests. To facilitate unit testing, all calls to test if the file is a symbolic should go through this method. (See the unit * test for why.) *

* * @param filePath The filePath to test * @return true if the file exists and is a symbolic link to either a file or directory, false otherwise. */ boolean isSymbolicLink(final Path filePath) { return Files.isSymbolicLink(filePath); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/filefilter/TrueFileFilter.java0100644 0000000 0000000 00000006170 14603604450 031416 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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. *

Deprecating Serialization

*

* Serialization is deprecated and will be removed in 3.0. *

* * @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 and(final IOFileFilter fileFilter) { // TRUE AND expression <=> expression return fileFilter; } @Override public IOFileFilter negate() { return FalseFileFilter.INSTANCE; } @Override public IOFileFilter or(final IOFileFilter fileFilter) { // TRUE OR expression <=> true return INSTANCE; } @Override public String toString() { return TO_STRING; } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/filefilter/WildcardFileFilter.java0100644 0000000 0000000 00000024624 14603604450 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.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 java.util.stream.Stream; import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOCase; import org.apache.commons.io.build.AbstractSupplier; import org.apache.commons.io.file.PathUtils; /** * 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. *

*

* To build an instance, use {@link Builder}. *

*

* For example: *

*

Using Classic IO

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

Using NIO

* *
 * final Path dir = PathUtils.current();
 * final AccumulatorPathVisitor visitor = AccumulatorPathVisitor.withLongCounters(
 *     WildcardFileFilter.builder().setWildcards("*test*.java~*~").get());
 * //
 * // 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());
 * 
*

Deprecating Serialization

*

* Serialization is deprecated and will be removed in 3.0. *

* * @since 1.3 */ public class WildcardFileFilter extends AbstractFileFilter implements Serializable { /** * Builds a new {@link WildcardFileFilter} instance. * * @since 2.12.0 */ public static class Builder extends AbstractSupplier { /** The wildcards that will be used to match file names. */ private String[] wildcards; /** Whether the comparison is case-sensitive. */ private IOCase ioCase = IOCase.SENSITIVE; @Override public WildcardFileFilter get() { return new WildcardFileFilter(ioCase, wildcards); } /** * Sets how to handle case sensitivity, null means case-sensitive. * * @param ioCase how to handle case sensitivity, null means case-sensitive. * @return this */ public Builder setIoCase(final IOCase ioCase) { this.ioCase = IOCase.value(ioCase, IOCase.SENSITIVE); return this; } /** * Sets the list of wildcards to match, not null. * * @param wildcards the list of wildcards to match, not null. * @return this */ public Builder setWildcards(final List wildcards) { setWildcards(requireWildcards(wildcards).toArray(EMPTY_STRING_ARRAY)); return this; } /** * Sets the wildcards to match, not null. * * @param wildcards the wildcards to match, not null. * @return this */ public Builder setWildcards(final String... wildcards) { this.wildcards = requireWildcards(wildcards); return this; } } private static final long serialVersionUID = -7426486598995782105L; /** * Constructs a new {@link Builder}. * * @return a new {@link Builder}. * @since 2.12.0 */ public static Builder builder() { return new Builder(); } private static T requireWildcards(final T wildcards) { return Objects.requireNonNull(wildcards, "wildcards"); } /** The wildcards that will be used to match file names. */ private final String[] wildcards; /** Whether the comparison is case-sensitive. */ private final IOCase ioCase; /** * Constructs a new wildcard filter for an array of wildcards specifying case-sensitivity. * * @param wildcards the array of wildcards to match, not null * @param ioCase how to handle case sensitivity, null means case-sensitive * @throws NullPointerException if the pattern array is null */ private WildcardFileFilter(final IOCase ioCase, final String... wildcards) { this.wildcards = requireWildcards(wildcards).clone(); this.ioCase = IOCase.value(ioCase, IOCase.SENSITIVE); } /** * Constructs 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 * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated public WildcardFileFilter(final List wildcards) { this(wildcards, IOCase.SENSITIVE); } /** * Constructs a new wildcard filter for a list of wildcards specifying case-sensitivity. * * @param wildcards the list of wildcards to match, not null * @param ioCase 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 * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated public WildcardFileFilter(final List wildcards, final IOCase ioCase) { this(ioCase, requireWildcards(wildcards).toArray(EMPTY_STRING_ARRAY)); } /** * Constructs a new case-sensitive wildcard filter for a single wildcard. * * @param wildcard the wildcard to match * @throws IllegalArgumentException if the pattern is null * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated public WildcardFileFilter(final String wildcard) { this(IOCase.SENSITIVE, requireWildcards(wildcard)); } /** * Constructs a new case-sensitive wildcard filter for an array of wildcards. * * @param wildcards the array of wildcards to match * @throws NullPointerException if the pattern array is null * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated public WildcardFileFilter(final String... wildcards) { this(IOCase.SENSITIVE, wildcards); } /** * Constructs a new wildcard filter for a single wildcard specifying case-sensitivity. * * @param wildcard the wildcard to match, not null * @param ioCase how to handle case sensitivity, null means case-sensitive * @throws NullPointerException if the pattern is null * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated public WildcardFileFilter(final String wildcard, final IOCase ioCase) { this(ioCase, wildcard); } /** * Constructs a new wildcard filter for an array of wildcards specifying case-sensitivity. * * @param wildcards the array of wildcards to match, not null * @param ioCase how to handle case sensitivity, null means case-sensitive * @throws NullPointerException if the pattern array is null * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated public WildcardFileFilter(final String[] wildcards, final IOCase ioCase) { this(ioCase, wildcards); } /** * 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 path 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 path, final BasicFileAttributes attributes) { return toFileVisitResult(accept(PathUtils.getFileNameString(path))); } private boolean accept(final String name) { return Stream.of(wildcards).anyMatch(wildcard -> FilenameUtils.wildcardMatch(name, wildcard, ioCase)); } /** * 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("("); append(wildcards, buffer); buffer.append(")"); return buffer.toString(); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/filefilter/WildcardFilter.java0100644 0000000 0000000 00000013624 14603604450 031432 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 java.util.stream.Stream; import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.file.PathUtils; /** * 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 = FileUtils.current();
 * FileFilter fileFilter = new WildcardFilter("*test*.java~*~");
 * File[] files = dir.listFiles(fileFilter);
 * for (String file : files) {
 *     System.out.println(file);
 * }
 * 
* *

Using NIO

*
 * final Path dir = PathUtils.current();
 * 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());
 * 
*

Deprecating Serialization

*

* Serialization is deprecated and will be removed in 3.0. *

* * @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; /** * Constructs a new case-sensitive wildcard filter for a list of wildcards. * * @param wildcards the list of wildcards to match * @throws NullPointerException if the pattern list is null * @throws ClassCastException if the list does not contain Strings */ public WildcardFilter(final List wildcards) { Objects.requireNonNull(wildcards, "wildcards"); this.wildcards = wildcards.toArray(EMPTY_STRING_ARRAY); } /** * Constructs a new case-sensitive wildcard filter for a single wildcard. * * @param wildcard the wildcard to match * @throws NullPointerException if the pattern is null */ public WildcardFilter(final String wildcard) { Objects.requireNonNull(wildcard, "wildcard"); this.wildcards = new String[] { wildcard }; } /** * Constructs a new case-sensitive wildcard filter for an array of wildcards. * * @param wildcards the array of wildcards to match * @throws NullPointerException if the pattern array is null */ public WildcardFilter(final String... wildcards) { Objects.requireNonNull(wildcards, "wildcards"); this.wildcards = wildcards.clone(); } /** * 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; } return Stream.of(wildcards).anyMatch(wildcard -> FilenameUtils.wildcardMatch(file.getName(), wildcard)); } /** * 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; } return Stream.of(wildcards).anyMatch(wildcard -> FilenameUtils.wildcardMatch(name, wildcard)); } /** * Checks to see if the file name matches one of the wildcards. * @param path 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 path, final BasicFileAttributes attributes) { if (Files.isDirectory(path)) { return FileVisitResult.TERMINATE; } return toDefaultFileVisitResult( Stream.of(wildcards).anyMatch(wildcard -> FilenameUtils.wildcardMatch(PathUtils.getFileNameString(path), wildcard))); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/filefilter/package-info.java0100644 0000000 0000000 00000013362 14603604450 031056 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Provides the an interface {@link org.apache.commons.io.filefilter.IOFileFilter 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:
DirectoryFilterOnly accept directories
PrefixFileFilterFilter based on a prefix
SuffixFileFilterFilter based on a suffix
NameFileFilterFilter based on a file name
WildcardFileFilterFilter based on wildcards
AgeFileFilterFilter based on last modified time of file
SizeFileFilterFilter based on file size
* * * * * * * * * * * * * * * * * * * * * * * * * *
And there are five 'boolean' filters:
TrueFileFilterAccept all files
FalseFileFilterAccept no files
NotFileFilterApplies a logical NOT to an existing filter
AndFileFilterCombines two filters using a logical AND
OrFileFilterCombines 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.

*/ package org.apache.commons.io.filefilter; commons-io-2.16.1-src/src/main/java/org/apache/commons/io/function/Constants.java0100644 0000000 0000000 00000003514 14603604450 030204 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; /** * Defines package-private constants. */ final class Constants { /** * No-op singleton. */ @SuppressWarnings("rawtypes") static final IOBiConsumer IO_BI_CONSUMER = (t, u) -> {/* No-op */}; /** * No-op singleton. */ static final IORunnable IO_RUNNABLE = () -> {/* No-op */}; /** * No-op singleton. */ @SuppressWarnings("rawtypes") static final IOBiFunction IO_BI_FUNCTION = (t, u) -> null; /** * No-op singleton. */ @SuppressWarnings("rawtypes") static final IOFunction IO_FUNCTION_ID = t -> t; /** * Always false. */ static final IOPredicate IO_PREDICATE_FALSE = t -> false; /** * Always true. */ static final IOPredicate IO_PREDICATE_TRUE = t -> true; /** * No-op singleton. */ @SuppressWarnings("rawtypes") static final IOTriConsumer IO_TRI_CONSUMER = (t, u, v) -> {/* No-op */}; private Constants() { // We don't want instances } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/function/Erase.java0100644 0000000 0000000 00000013715 14603604450 027273 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; /** * Erases {@link IOException} for the compiler but still throws that exception at runtime. * * @since 2.16.0 */ public final class Erase { /** * Delegates to the given {@link IOBiConsumer} but erases its {@link IOException} for the compiler, while still throwing * the exception at runtime. * * @param See delegate. * @param See delegate. * @param consumer See delegate. * @param t See delegate. * @param u See delegate. * @see IOBiConsumer */ static void accept(final IOBiConsumer consumer, final T t, final U u) { try { consumer.accept(t, u); } catch (final IOException ex) { rethrow(ex); // throws IOException } } /** * Delegates to the given {@link IOConsumer} but erases its {@link IOException} for the compiler, while still throwing * the exception at runtime. * * @param See delegate. * @param consumer See delegate. * @param t See delegate. * @see IOConsumer */ static void accept(final IOConsumer consumer, final T t) { try { consumer.accept(t); } catch (final IOException ex) { rethrow(ex); // throws IOException } } /** * Delegates to the given {@link IOBiFunction} but erases its {@link IOException} for the compiler, while still throwing * the exception at runtime. * * @param See delegate. * @param See delegate. * @param See delegate. * @param mapper See delegate. * @param t See delegate. * @param u See delegate. * @return See delegate. * @see IOBiFunction */ static R apply(final IOBiFunction mapper, final T t, final U u) { try { return mapper.apply(t, u); } catch (final IOException e) { throw rethrow(e); // throws IOException } } /** * Delegates to the given {@link IOFunction} but erases its {@link IOException} for the compiler, while still throwing * the exception at runtime. * * @param See delegate. * @param See delegate. * @param mapper See delegate. * @param t See delegate. * @return See delegate. * @see IOFunction */ static R apply(final IOFunction mapper, final T t) { try { return mapper.apply(t); } catch (final IOException e) { throw rethrow(e); // throws IOException } } /** * Delegates to the given {@link IOComparator} but erases its {@link IOException} for the compiler, while still throwing * the exception at runtime. * * @param See delegate. * @param comparator See delegate. * @param t See delegate. * @param u See delegate. * @return See delegate. * @see IOComparator */ static int compare(final IOComparator comparator, final T t, final T u) { try { return comparator.compare(t, u); } catch (final IOException e) { throw rethrow(e); // throws IOException } } /** * Delegates to the given {@link IOSupplier} but erases its {@link IOException} for the compiler, while still throwing * the exception at runtime. * * @param See delegate. * @param supplier See delegate. * @return See delegate. * @see IOSupplier */ static T get(final IOSupplier supplier) { try { return supplier.get(); } catch (final IOException e) { throw rethrow(e); // throws IOException } } /** * Throws the given throwable. * * @param The throwable cast type. * @param throwable The throwable to rethrow. * @return nothing because we throw. * @throws T Always thrown. */ @SuppressWarnings("unchecked") public static RuntimeException rethrow(final Throwable throwable) throws T { throw (T) throwable; } /** * Delegates to the given {@link IORunnable} but erases its {@link IOException} for the compiler, while still throwing * the exception at runtime. * * @param runnable See delegate. * @see IORunnable */ static void run(final IORunnable runnable) { try { runnable.run(); } catch (final IOException e) { throw rethrow(e); // throws IOException } } /** * Delegates to the given {@link IOPredicate} but erases its {@link IOException} for the compiler, while still throwing * the exception at runtime. * * @param See delegate. * @param predicate See delegate. * @param t See delegate. * @return See delegate. * @see IOPredicate */ static boolean test(final IOPredicate predicate, final T t) { try { return predicate.test(t); } catch (final IOException e) { throw rethrow(e); // throws IOException } } /** No instances. */ private Erase() { // No instances. } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/function/IOBaseStream.java0100644 0000000 0000000 00000011314 14603604450 030503 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.Closeable; import java.io.IOException; import java.io.UncheckedIOException; import java.util.stream.BaseStream; import java.util.stream.Stream; /** * Like {@link BaseStream} but throws {@link IOException}. * * @param the type of the stream elements. * @param the type of the IO stream extending {@code IOBaseStream}. * @param the type of the stream extending {@code BaseStream}. * @since 2.12.0 */ public interface IOBaseStream, B extends BaseStream> extends Closeable { /** * Constructs a {@link BaseStream} for this instance that throws {@link UncheckedIOException} instead of * {@link IOException}. * * @return an {@link UncheckedIOException} {@link BaseStream}. */ @SuppressWarnings("unchecked") default BaseStream asBaseStream() { return new UncheckedIOBaseStream<>((S) this); } /** * Like {@link BaseStream#close()}. * * @see BaseStream#close() */ @Override default void close() { unwrap().close(); } /** * Like {@link BaseStream#isParallel()}. * * @return See {@link BaseStream#isParallel() delegate}. * @see BaseStream#isParallel() */ @SuppressWarnings("resource") // for unwrap() default boolean isParallel() { return unwrap().isParallel(); } /** * Like {@link BaseStream#iterator()}. * * @return See {@link BaseStream#iterator() delegate}. * @see BaseStream#iterator() */ @SuppressWarnings("resource") // for unwrap() default IOIterator iterator() { return IOIteratorAdapter.adapt(unwrap().iterator()); } /** * Like {@link BaseStream#onClose(Runnable)}. * * @param closeHandler See {@link BaseStream#onClose(Runnable) delegate}. * @return See {@link BaseStream#onClose(Runnable) delegate}. * @throws IOException if an I/O error occurs. * @see BaseStream#onClose(Runnable) */ @SuppressWarnings({"unused", "resource"}) // throws IOException, unwrap() default S onClose(final IORunnable closeHandler) throws IOException { return wrap(unwrap().onClose(() -> Erase.run(closeHandler))); } /** * Like {@link BaseStream#parallel()}. * * @return See {@link BaseStream#parallel() delegate}. * @see BaseStream#parallel() */ @SuppressWarnings({"resource", "unchecked"}) // for unwrap(), this default S parallel() { return isParallel() ? (S) this : wrap(unwrap().parallel()); } /** * Like {@link BaseStream#sequential()}. * * @return See {@link BaseStream#sequential() delegate}. * @see BaseStream#sequential() */ @SuppressWarnings({"resource", "unchecked"}) // for unwrap(), this default S sequential() { return isParallel() ? wrap(unwrap().sequential()) : (S) this; } /** * Like {@link BaseStream#spliterator()}. * * @return See {@link BaseStream#spliterator() delegate}. * @see BaseStream#spliterator() */ @SuppressWarnings("resource") // for unwrap() default IOSpliterator spliterator() { return IOSpliteratorAdapter.adapt(unwrap().spliterator()); } /** * Like {@link BaseStream#unordered()}. * * @return See {@link BaseStream#unordered() delegate}. * @see java.util.stream.BaseStream#unordered() */ @SuppressWarnings("resource") // for unwrap() default S unordered() { return wrap(unwrap().unordered()); } /** * Unwraps this instance and returns the underlying {@link Stream}. *

* Implementations may not have anything to unwrap and that behavior is undefined for now. *

* * @return the underlying stream. */ B unwrap(); /** * Wraps a {@link Stream}. * * @param delegate The delegate. * @return An IO stream. */ S wrap(B delegate); } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/function/IOBaseStreamAdapter.java0100644 0000000 0000000 00000003131 14603604450 032002 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.util.Objects; import java.util.stream.BaseStream; /** * Abstracts an {@link IOBaseStream} implementation. * * Keep package-private for now. * * @param the type of the stream elements. * @param the type of the stream extending {@code IOBaseStream}. */ abstract class IOBaseStreamAdapter, B extends BaseStream> implements IOBaseStream { /** * The underlying base stream. */ private final B delegate; /** * Constructs an instance. * * @param delegate the delegate. */ IOBaseStreamAdapter(final B delegate) { this.delegate = Objects.requireNonNull(delegate, "delegate"); } @Override public B unwrap() { return delegate; } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/function/IOBiConsumer.java0100644 0000000 0000000 00000006135 14603604450 030530 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.io.UncheckedIOException; import java.util.Objects; import java.util.function.BiConsumer; /** * Like {@link BiConsumer} but throws {@link IOException}. * * @param the type of the first argument to the operation * @param the type of the second argument to the operation * * @see BiConsumer * @since 2.12.0 */ @FunctionalInterface public interface IOBiConsumer { /** * Returns the no-op singleton. * * @param the type of the first argument to the operation * @param the type of the second argument to the operation * @return The no-op singleton. */ @SuppressWarnings("unchecked") static IOBiConsumer noop() { return Constants.IO_BI_CONSUMER; } /** * Performs this operation on the given arguments. * * @param t the first input argument * @param u the second input argument * @throws IOException if an I/O error occurs. */ void accept(T t, U u) throws IOException; /** * Creates a composed {@link IOBiConsumer} 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 {@link IOBiConsumer} that performs in sequence this operation followed by the {@code after} * operation * @throws NullPointerException if {@code after} is null */ default IOBiConsumer andThen(final IOBiConsumer after) { Objects.requireNonNull(after); return (t, u) -> { accept(t, u); after.accept(t, u); }; } /** * Creates a {@link BiConsumer} for this instance that throws {@link UncheckedIOException} instead of * {@link IOException}. * * @return an UncheckedIOException BiConsumer. * @throws UncheckedIOException Wraps an {@link IOException}. * @since 2.12.0 */ default BiConsumer asBiConsumer() { return (t, u) -> Uncheck.accept(this, t, u); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/function/IOBiFunction.java0100644 0000000 0000000 00000005603 14603604450 030521 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.io.UncheckedIOException; import java.util.Objects; import java.util.function.BiFunction; import java.util.function.Function; /** * Like {@link BiFunction} but throws {@link IOException}. * *

* This is a functional interface whose functional method is * {@link #apply(Object, Object)}. *

* * @param the type of the first argument to the function * @param the type of the second argument to the function * @param the type of the result of the function * * @see Function * @since 2.12.0 */ @FunctionalInterface public interface IOBiFunction { /** * Creates a composed function 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 */ default IOBiFunction andThen(final IOFunction after) { Objects.requireNonNull(after); return (final T t, final U u) -> after.apply(apply(t, u)); } /** * Applies this function to the given arguments. * * @param t the first function argument * @param u the second function argument * @return the function result * @throws IOException if an I/O error occurs. */ R apply(T t, U u) throws IOException; /** * Creates a {@link BiFunction} for this instance that throws {@link UncheckedIOException} instead of * {@link IOException}. * * @return an UncheckedIOException BiFunction. */ default BiFunction asBiFunction() { return (t, u) -> Uncheck.apply(this, t, u); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/function/IOBinaryOperator.java0100644 0000000 0000000 00000005667 14603604450 031433 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.io.UncheckedIOException; import java.util.Objects; import java.util.function.BinaryOperator; /** * Like {@link BinaryOperator} but throws {@link IOException}. * * @param the type of the operands and result of the operator. * * @see IOBiFunction * @see BinaryOperator * @since 2.12.0 */ @FunctionalInterface public interface IOBinaryOperator extends IOBiFunction { /** * Creates a {@link IOBinaryOperator} which returns the greater of two elements according to the specified * {@code Comparator}. * * @param the type of the input arguments of the comparator * @param comparator a {@code Comparator} for comparing the two values * @return a {@code BinaryOperator} which returns the greater of its operands, according to the supplied * {@code Comparator} * @throws NullPointerException if the argument is null */ static IOBinaryOperator maxBy(final IOComparator comparator) { Objects.requireNonNull(comparator); return (a, b) -> comparator.compare(a, b) >= 0 ? a : b; } /** * Creates a {@link IOBinaryOperator} which returns the lesser of two elements according to the specified * {@code Comparator}. * * @param the type of the input arguments of the comparator * @param comparator a {@code Comparator} for comparing the two values * @return a {@code BinaryOperator} which returns the lesser of its operands, according to the supplied * {@code Comparator} * @throws NullPointerException if the argument is null */ static IOBinaryOperator minBy(final IOComparator comparator) { Objects.requireNonNull(comparator); return (a, b) -> comparator.compare(a, b) <= 0 ? a : b; } /** * Creates a {@link BinaryOperator} for this instance that throws {@link UncheckedIOException} instead of * {@link IOException}. * * @return an unchecked BiFunction. */ default BinaryOperator asBinaryOperator() { return (t, u) -> Uncheck.apply(this, t, u); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/function/IOComparator.java0100644 0000000 0000000 00000004201 14603604450 030561 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.io.UncheckedIOException; import java.util.Comparator; /** * Like {@link Comparator} but throws {@link IOException}. * * @param the type of objects that may be compared by this comparator * * @see Comparator * @since 2.12.0 */ @FunctionalInterface public interface IOComparator { /** * Creates a {@link Comparator} for this instance that throws {@link UncheckedIOException} instead of * {@link IOException}. * * @return an UncheckedIOException BiFunction. */ default Comparator asComparator() { return (t, u) -> Uncheck.compare(this, t, u); } /** * Like {@link Comparator#compare(Object, Object)} but throws {@link IOException}. * * @param o1 the first object to be compared. * @param o2 the second object to be compared. * @return a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater than * the second. * @throws NullPointerException if an argument is null and this comparator does not permit null arguments * @throws ClassCastException if the arguments' types prevent them from being compared by this comparator. * @throws IOException if an I/O error occurs. */ int compare(T o1, T o2) throws IOException; } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/function/IOConsumer.java0100644 0000000 0000000 00000013615 14603604450 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.function; import java.io.IOException; import java.io.UncheckedIOException; import java.util.Objects; import java.util.function.Consumer; import java.util.stream.Stream; import org.apache.commons.io.IOExceptionList; import org.apache.commons.io.IOIndexedException; /** * Like {@link Consumer} but throws {@link IOException}. * * @param the type of the input to the operations. * @since 2.7 */ @FunctionalInterface public interface IOConsumer { /** * Consider private. */ IOConsumer NOOP_IO_CONSUMER = t -> {/* noop */}; /** * Performs an action for each element of the collection gathering any exceptions. * * @param action The action to apply to each input element. * @param iterable The input to stream. * @param The element type. * @throws IOExceptionList if any I/O errors occur. * @since 2.12.0 */ static void forAll(final IOConsumer action, final Iterable iterable) throws IOExceptionList { IOStreams.forAll(IOStreams.of(iterable), action); } /** * Performs an action for each element of the collection gathering any exceptions. * * @param action The action to apply to each input element. * @param stream The input to stream. * @param The element type. * @throws IOExceptionList if any I/O errors occur. * @since 2.12.0 */ static void forAll(final IOConsumer action, final Stream stream) throws IOExceptionList { IOStreams.forAll(stream, action, IOIndexedException::new); } /** * Performs an action for each element of the array, gathering any exceptions. * * @param action The action to apply to each input element. * @param array The input to stream. * @param The element type. * @throws IOExceptionList if any I/O errors occur. * @since 2.12.0 */ @SafeVarargs static void forAll(final IOConsumer action, final T... array) throws IOExceptionList { IOStreams.forAll(IOStreams.of(array), action); } /** * Performs an action for each element of the collection, stopping at the first exception. * * @param The element type. * @param iterable The input to stream. * @param action The action to apply to each input element. * @throws IOException if an I/O error occurs. * @since 2.12.0 */ static void forEach(final Iterable iterable, final IOConsumer action) throws IOException { IOStreams.forEach(IOStreams.of(iterable), action); } /** * Performs an action for each element of the stream, stopping at the first exception. * * @param The element type. * @param stream The input to stream. * @param action The action to apply to each input element. * @throws IOException if an I/O error occurs. * @since 2.12.0 */ static void forEach(final Stream stream, final IOConsumer action) throws IOException { IOStreams.forEach(stream, action); } /** * Performs an action for each element of this array, stopping at the first exception. * * @param The element type. * @param array The input to stream. * @param action The action to apply to each input element. * @throws IOException if an I/O error occurs. * @since 2.12.0 */ static void forEach(final T[] array, final IOConsumer action) throws IOException { IOStreams.forEach(IOStreams.of(array), action); } /** * Returns the constant no-op consumer. * * @param Type consumer type. * @return a constant no-op 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 {@link 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 {@link 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); }; } /** * Creates a {@link Consumer} for this instance that throws {@link UncheckedIOException} instead of {@link IOException}. * * @return an UncheckedIOException Consumer. * @since 2.12.0 */ default Consumer asConsumer() { return t -> Uncheck.accept(this, t); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/function/IOFunction.java0100644 0000000 0000000 00000021021 14603604450 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.function; import java.io.IOException; import java.io.UncheckedIOException; 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 { /** * 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 */ @SuppressWarnings("unchecked") static IOFunction identity() { return Constants.IO_FUNCTION_ID; } /** * 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 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} 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)); } /** * Applies this function to the given argument. * * @param t the function argument * @return the function result * @throws IOException if an I/O error occurs. */ R apply(final T t) throws IOException; /** * Creates a {@link Function} for this instance that throws {@link UncheckedIOException} instead of {@link IOException}. * * @return an UncheckedIOException Function. * @since 2.12.0 */ default Function asFunction() { return t -> Uncheck.apply(this, t); } /** * 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 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 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()); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/function/IOIntSupplier.java0100644 0000000 0000000 00000003055 14603604450 030736 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.io.UncheckedIOException; import java.util.function.IntSupplier; import java.util.function.Supplier; /** * Like {@link IntSupplier} but throws {@link IOException}. * * @since 2.14.0 */ @FunctionalInterface public interface IOIntSupplier { /** * Creates a {@link Supplier} for this instance that throws {@link UncheckedIOException} instead of {@link IOException}. * * @return an UncheckedIOException Supplier. */ default IntSupplier asIntSupplier() { return () -> Uncheck.getAsInt(this); } /** * Gets a result. * * @return a result * @throws IOException if an I/O error occurs. */ int getAsInt() throws IOException; } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/function/IOIterator.java0100644 0000000 0000000 00000006151 14603604450 030251 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.io.UncheckedIOException; import java.util.Iterator; import java.util.NoSuchElementException; import java.util.Objects; import java.util.function.Consumer; /** * Like {@link Iterator} but throws {@link IOException}. * * @param the type of elements returned by this iterator. * @since 2.12.0 */ public interface IOIterator { /** * Adapts the given Iterator as an IOIterator. * * @param the type of the stream elements. * @param iterator The iterator to adapt * @return A new IOIterator */ static IOIterator adapt(final Iterator iterator) { return IOIteratorAdapter.adapt(iterator); } /** * Creates an {@link Iterator} for this instance that throws {@link UncheckedIOException} instead of * {@link IOException}. * * @return an {@link UncheckedIOException} {@link Iterator}. */ default Iterator asIterator() { return new UncheckedIOIterator<>(this); } /** * Like {@link Iterator#forEachRemaining(Consumer)}. * * @param action See delegate. * @throws IOException if an I/O error occurs. */ default void forEachRemaining(final IOConsumer action) throws IOException { Objects.requireNonNull(action); while (hasNext()) { action.accept(next()); } } /** * Like {@link Iterator#hasNext()}. * * @return See delegate. * @throws IOException if an I/O error occurs. */ boolean hasNext() throws IOException; /** * Like {@link Iterator#next()}. * * @return See delegate. * @throws IOException if an I/O error occurs. * @throws NoSuchElementException if the iteration has no more elements */ E next() throws IOException; /** * Like {@link Iterator#remove()}. * * @throws IOException if an I/O error occurs. */ @SuppressWarnings("unused") default void remove() throws IOException { unwrap().remove(); } /** * Unwraps this instance and returns the underlying {@link Iterator}. *

* Implementations may not have anything to unwrap and that behavior is undefined for now. *

* @return the underlying Iterator. */ Iterator unwrap(); } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/function/IOIteratorAdapter.java0100644 0000000 0000000 00000003223 14603604450 031547 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.Iterator; import java.util.Objects; /** * Adapts an {@link Iterator} as an {@link IOIterator}. * * @param the type of the stream elements. */ final class IOIteratorAdapter implements IOIterator { static IOIteratorAdapter adapt(final Iterator delegate) { return new IOIteratorAdapter<>(delegate); } private final Iterator delegate; IOIteratorAdapter(final Iterator delegate) { this.delegate = Objects.requireNonNull(delegate, "delegate"); } @Override public boolean hasNext() throws IOException { return delegate.hasNext(); } @Override public E next() throws IOException { return delegate.next(); } @Override public Iterator unwrap() { return delegate; } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/function/IOLongSupplier.java0100644 0000000 0000000 00000003061 14603604450 031100 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.io.UncheckedIOException; import java.util.function.LongSupplier; import java.util.function.Supplier; /** * Like {@link LongSupplier} but throws {@link IOException}. * * @since 2.14.0 */ @FunctionalInterface public interface IOLongSupplier { /** * Creates a {@link Supplier} for this instance that throws {@link UncheckedIOException} instead of {@link IOException}. * * @return an UncheckedIOException Supplier. */ default LongSupplier asSupplier() { return () -> Uncheck.getAsLong(this); } /** * Gets a result. * * @return a result * @throws IOException if an I/O error occurs. */ long getAsLong() throws IOException; } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/function/IOPredicate.java0100644 0000000 0000000 00000011747 14603604450 030367 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.io.UncheckedIOException; import java.util.Objects; import java.util.function.Predicate; /** * Like {@link Predicate} but throws {@link IOException}. * * @param the type of the input to the predicate * @since 2.12.0 */ @FunctionalInterface public interface IOPredicate { /** * Always false. * * @param the type of the input to the predicate * @return a constant predicate that tests always false. */ @SuppressWarnings("unchecked") static IOPredicate alwaysFalse() { return (IOPredicate) Constants.IO_PREDICATE_FALSE; } /** * Always true. * * @param the type of the input to the predicate * @return a constant predicate that tests always true. */ @SuppressWarnings("unchecked") static IOPredicate alwaysTrue() { return (IOPredicate) Constants.IO_PREDICATE_TRUE; } /** * Creates a predicate that tests if two arguments are equal using {@link Objects#equals(Object, Object)}. * * @param the type of arguments to the predicate * @param target the object to compare for equality, may be {@code null} * @return a predicate that tests if two arguments are equal using {@link Objects#equals(Object, Object)} */ static IOPredicate isEqual(final Object target) { return null == target ? Objects::isNull : object -> target.equals(object); } /** * Creates a composed predicate that represents a short-circuiting logical AND of this predicate and another. When * evaluating the composed predicate, if this predicate is {@code false}, then the {@code other} predicate is not * evaluated. * *

* Any exceptions thrown during evaluation of either predicate are relayed to the caller; if evaluation of this * predicate throws an exception, the {@code other} predicate will not be evaluated. *

* * @param other a predicate that will be logically-ANDed with this predicate * @return a composed predicate that represents the short-circuiting logical AND of this predicate and the {@code other} * predicate * @throws NullPointerException if other is null */ default IOPredicate and(final IOPredicate other) { Objects.requireNonNull(other); return t -> test(t) && other.test(t); } /** * Creates a {@link Predicate} for this instance that throws {@link UncheckedIOException} instead of * {@link IOException}. * * @return an UncheckedIOException Predicate. */ default Predicate asPredicate() { return t -> Uncheck.test(this, t); } /** * Creates a predicate that represents the logical negation of this predicate. * * @return a predicate that represents the logical negation of this predicate */ default IOPredicate negate() { return t -> !test(t); } /** * Creates a composed predicate that represents a short-circuiting logical OR of this predicate and another. When * evaluating the composed predicate, if this predicate is {@code true}, then the {@code other} predicate is not * evaluated. * *

* Any exceptions thrown during evaluation of either predicate are relayed to the caller; if evaluation of this * predicate throws an exception, the {@code other} predicate will not be evaluated. *

* * @param other a predicate that will be logically-ORed with this predicate * @return a composed predicate that represents the short-circuiting logical OR of this predicate and the {@code other} * predicate * @throws NullPointerException if other is null */ default IOPredicate or(final IOPredicate other) { Objects.requireNonNull(other); return t -> test(t) || other.test(t); } /** * Evaluates this predicate on the given argument. * * @param t the input argument * @return {@code true} if the input argument matches the predicate, otherwise {@code false} * @throws IOException if an I/O error occurs. */ boolean test(T t) throws IOException; } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/function/IOQuadFunction.java0100644 0000000 0000000 00000005546 14603604450 031067 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.Function; /** * Represents a function that accepts four arguments and produces a result. This is the four-arity specialization of * {@link IOFunction}. * *

* This is a functional interface whose functional method is * {@link #apply(Object, Object, Object, Object)}. *

* * @param the type of the first argument to the function * @param the type of the second argument to the function * @param the type of the third argument to the function * @param the type of the fourth argument to the function * @param the type of the result of the function * * @see Function * @since 2.12.0 */ @FunctionalInterface public interface IOQuadFunction { /** * Creates a composed function 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 */ default IOQuadFunction andThen(final IOFunction after) { Objects.requireNonNull(after); return (final T t, final U u, final V v, final W w) -> after.apply(apply(t, u, v, w)); } /** * Applies this function to the given arguments. * * @param t the first function argument * @param u the second function argument * @param v the third function argument * @param w the fourth function argument * @return the function result * @throws IOException if an I/O error occurs. */ R apply(T t, U u, V v, W w) throws IOException; } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/function/IORunnable.java0100644 0000000 0000000 00000003261 14603604450 030225 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.io.UncheckedIOException; /** * Like {@link Runnable} but throws {@link IOException}. * * @since 2.12.0 */ @FunctionalInterface public interface IORunnable { /** * Returns the constant no-op runnable. * * @return a constant no-op runnable. * @since 2.16.0 */ static IORunnable noop() { return Constants.IO_RUNNABLE; } /** * Creates a {@link Runnable} for this instance that throws {@link UncheckedIOException} instead of {@link IOException}. * * @return an UncheckedIOException Predicate. */ default Runnable asRunnable() { return () -> Uncheck.run(this); } /** * Like {@link Runnable#run()} but throws {@link IOException}. * * @throws IOException if an I/O error occurs. */ void run() throws IOException; } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/function/IOSpliterator.java0100644 0000000 0000000 00000011220 14603604450 030761 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.io.UncheckedIOException; import java.util.Objects; import java.util.Spliterator; import java.util.function.Consumer; /** * Like {@link Spliterator} but throws {@link IOException}. * * @param the type of elements returned by this IOSpliterator. * @since 2.12.0 */ public interface IOSpliterator { /** * Adapts the given Spliterator as an IOSpliterator. * * @param the type of the stream elements. * @param iterator The iterator to adapt * @return A new IOSpliterator */ static IOSpliterator adapt(final Spliterator iterator) { return IOSpliteratorAdapter.adapt(iterator); } /** * Constructs a {@link Spliterator} for this instance that throws {@link UncheckedIOException} instead of * {@link IOException}. * * @return an {@link UncheckedIOException} {@link Spliterator}. */ default Spliterator asSpliterator() { return new UncheckedIOSpliterator<>(this); } /** * Like {@link Spliterator#characteristics()}. * * @return a representation of characteristics */ default int characteristics() { return unwrap().characteristics(); } /** * Like {@link Spliterator#estimateSize()}. * * * @return the estimated size, or {@code Long.MAX_VALUE} if infinite, unknown, or too expensive to compute. */ default long estimateSize() { return unwrap().estimateSize(); } /** * Like {@link Spliterator#forEachRemaining(Consumer)}. * * @param action The action * @throws NullPointerException if the specified action is null */ default void forEachRemaining(final IOConsumer action) { while (tryAdvance(action)) { // NOPMD } } /** * Like {@link Spliterator#getComparator()}. * * @return a Comparator, or {@code null} if the elements are sorted in the natural order. * @throws IllegalStateException if the spliterator does not report a characteristic of {@code SORTED}. */ @SuppressWarnings("unchecked") default IOComparator getComparator() { return (IOComparator) unwrap().getComparator(); } /** * Like {@link Spliterator#getExactSizeIfKnown()}. * * @return the exact size, if known, else {@code -1}. */ default long getExactSizeIfKnown() { return unwrap().getExactSizeIfKnown(); } /** * Like {@link Spliterator#hasCharacteristics(int)}. * * @param characteristics the characteristics to check for * @return {@code true} if all the specified characteristics are present, else {@code false} */ default boolean hasCharacteristics(final int characteristics) { return unwrap().hasCharacteristics(characteristics); } /** * Like {@link Spliterator#tryAdvance(Consumer)}. * * @param action The action * @return {@code false} if no remaining elements existed upon entry to this method, else {@code true}. * @throws NullPointerException if the specified action is null */ default boolean tryAdvance(final IOConsumer action) { return unwrap().tryAdvance(Objects.requireNonNull(action, "action").asConsumer()); } /** * Like {@link Spliterator#trySplit()}. * * @return a {@code Spliterator} covering some portion of the elements, or {@code null} if this spliterator cannot be * split */ default IOSpliterator trySplit() { return adapt(unwrap().trySplit()); } /** * Unwraps this instance and returns the underlying {@link Spliterator}. *

* Implementations may not have anything to unwrap and that behavior is undefined for now. *

* * @return the underlying Spliterator. */ Spliterator unwrap(); } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/function/IOSpliteratorAdapter.java0100644 0000000 0000000 00000002723 14603604450 032272 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.util.Objects; import java.util.Spliterator; /** * Adapts an {@link Spliterator} as an {@link IOSpliterator}. * * @param the type of the stream elements. */ final class IOSpliteratorAdapter implements IOSpliterator { static IOSpliteratorAdapter adapt(final Spliterator delegate) { return new IOSpliteratorAdapter<>(delegate); } private final Spliterator delegate; IOSpliteratorAdapter(final Spliterator delegate) { this.delegate = Objects.requireNonNull(delegate, "delegate"); } @Override public Spliterator unwrap() { return delegate; } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/function/IOStream.java0100644 0000000 0000000 00000056242 14603604450 027721 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; import java.util.Objects; import java.util.Optional; import java.util.Spliterator; import java.util.Spliterators; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import java.util.function.BiFunction; import java.util.function.IntFunction; import java.util.function.ToDoubleFunction; import java.util.function.ToIntFunction; import java.util.function.ToLongFunction; import java.util.function.UnaryOperator; import java.util.stream.Collector; import java.util.stream.DoubleStream; import java.util.stream.IntStream; import java.util.stream.LongStream; import java.util.stream.Stream; import java.util.stream.StreamSupport; import org.apache.commons.io.IOExceptionList; /** * Like {@link Stream} but throws {@link IOException}. * * @param the type of the stream elements. * @since 2.12.0 */ public interface IOStream extends IOBaseStream, Stream> { /** * Constructs a new IOStream for the given Stream. * * @param the type of the stream elements. * @param stream The stream to delegate. * @return a new IOStream. */ static IOStream adapt(final Stream stream) { return IOStreamAdapter.adapt(stream); } /** * This class' version of {@link Stream#empty()}. * * @param the type of the stream elements * @return an empty sequential {@code IOStreamImpl}. * @see Stream#empty() */ static IOStream empty() { return IOStreamAdapter.adapt(Stream.empty()); } /** * Like {@link Stream#iterate(Object, UnaryOperator)} but for IO. * * @param the type of stream elements. * @param seed the initial element. * @param f a function to be applied to the previous element to produce a new element. * @return a new sequential {@code IOStream}. */ static IOStream iterate(final T seed, final IOUnaryOperator f) { Objects.requireNonNull(f); final Iterator iterator = new Iterator() { @SuppressWarnings("unchecked") T t = (T) IOStreams.NONE; @Override public boolean hasNext() { return true; } @Override public T next() throws NoSuchElementException { try { return t = t == IOStreams.NONE ? seed : f.apply(t); } catch (final IOException e) { final NoSuchElementException nsee = new NoSuchElementException(); nsee.initCause(e); throw nsee; } } }; return adapt(StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.ORDERED | Spliterator.IMMUTABLE), false)); } /** * Null-safe version of {@link StreamSupport#stream(java.util.Spliterator, boolean)}. * * Copied from Apache Commons Lang. * * @param the type of stream elements. * @param values the elements of the new stream, may be {@code null}. * @return the new stream on {@code values} or {@link Stream#empty()}. */ @SuppressWarnings("resource") // call to #empty() static IOStream of(final Iterable values) { return values == null ? empty() : adapt(StreamSupport.stream(values.spliterator(), false)); } /** * Null-safe version of {@link Stream#of(Object[])} for an IO stream. * * @param the type of stream elements. * @param values the elements of the new stream, may be {@code null}. * @return the new stream on {@code values} or {@link Stream#empty()}. */ @SuppressWarnings("resource") @SafeVarargs // Creating a stream from an array is safe static IOStream of(final T... values) { return values == null || values.length == 0 ? empty() : adapt(Arrays.stream(values)); } /** * Returns a sequential {@code IOStreamImpl} containing a single element. * * @param t the single element * @param the type of stream elements * @return a singleton sequential stream */ static IOStream of(final T t) { return adapt(Stream.of(t)); } /** * Like {@link Stream#allMatch(java.util.function.Predicate)} but throws {@link IOException}. * * @param predicate {@link Stream#allMatch(java.util.function.Predicate)}. * @return Like {@link Stream#allMatch(java.util.function.Predicate)}. * @throws IOException if an I/O error occurs. */ @SuppressWarnings("unused") // thrown by Erase. default boolean allMatch(final IOPredicate predicate) throws IOException { return unwrap().allMatch(t -> Erase.test(predicate, t)); } /** * Like {@link Stream#anyMatch(java.util.function.Predicate)} but throws {@link IOException}. * * @param predicate {@link Stream#anyMatch(java.util.function.Predicate)}. * @return Like {@link Stream#anyMatch(java.util.function.Predicate)}. * @throws IOException if an I/O error occurs. */ @SuppressWarnings("unused") // thrown by Erase. default boolean anyMatch(final IOPredicate predicate) throws IOException { return unwrap().anyMatch(t -> Erase.test(predicate, t)); } /** * TODO Package-private for now, needs IOCollector? * * Adding this method now and an IO version later is an issue because call sites would have to type-cast to pick one. It * would be ideal to have only one. * * Like {@link Stream#collect(Collector)}. * * Package private for now. * * @param Like {@link Stream#collect(Collector)}. * @param Like {@link Stream#collect(Collector)}. * @param collector Like {@link Stream#collect(Collector)}. * @return Like {@link Stream#collect(Collector)}. */ default R collect(final Collector collector) { return unwrap().collect(collector); } /** * Like * {@link Stream#collect(java.util.function.Supplier, java.util.function.BiConsumer, java.util.function.BiConsumer)}. * * @param Like * {@link Stream#collect(java.util.function.Supplier, java.util.function.BiConsumer, java.util.function.BiConsumer)}. * @param supplier Like * {@link Stream#collect(java.util.function.Supplier, java.util.function.BiConsumer, java.util.function.BiConsumer)}. * @param accumulator Like * {@link Stream#collect(java.util.function.Supplier, java.util.function.BiConsumer, java.util.function.BiConsumer)}. * @param combiner Like * {@link Stream#collect(java.util.function.Supplier, java.util.function.BiConsumer, java.util.function.BiConsumer)}. * @return Like * {@link Stream#collect(java.util.function.Supplier, java.util.function.BiConsumer, java.util.function.BiConsumer)}. * @throws IOException if an I/O error occurs. */ @SuppressWarnings("unused") // thrown by Erase. default R collect(final IOSupplier supplier, final IOBiConsumer accumulator, final IOBiConsumer combiner) throws IOException { return unwrap().collect(() -> Erase.get(supplier), (t, u) -> Erase.accept(accumulator, t, u), (t, u) -> Erase.accept(combiner, t, u)); } /** * Like {@link Stream#count()}. * * @return Like {@link Stream#count()}. */ default long count() { return unwrap().count(); } /** * Like {@link Stream#distinct()}. * * @return Like {@link Stream#distinct()}. */ default IOStream distinct() { return adapt(unwrap().distinct()); } /** * Like {@link Stream#filter(java.util.function.Predicate)}. * * @param predicate Like {@link Stream#filter(java.util.function.Predicate)}. * @return Like {@link Stream#filter(java.util.function.Predicate)}. * @throws IOException if an I/O error occurs. */ @SuppressWarnings("unused") // thrown by Erase. default IOStream filter(final IOPredicate predicate) throws IOException { return adapt(unwrap().filter(t -> Erase.test(predicate, t))); } /** * Like {@link Stream#findAny()}. * * @return Like {@link Stream#findAny()}. */ default Optional findAny() { return unwrap().findAny(); } /** * Like {@link Stream#findFirst()}. * * @return Like {@link Stream#findFirst()}. */ default Optional findFirst() { return unwrap().findFirst(); } /** * Like {@link Stream#flatMap(java.util.function.Function)}. * * @param Like {@link Stream#flatMap(java.util.function.Function)}. * @param mapper Like {@link Stream#flatMap(java.util.function.Function)}. * @return Like {@link Stream#flatMap(java.util.function.Function)}. * @throws IOException if an I/O error occurs. */ @SuppressWarnings("unused") // thrown by Erase. default IOStream flatMap(final IOFunction> mapper) throws IOException { return adapt(unwrap().flatMap(t -> Erase.apply(mapper, t).unwrap())); } /** * TODO Package-private for now, needs IODoubleStream? * * Adding this method now and an IO version later is an issue because call sites would have to type-cast to pick one. It * would be ideal to have only one. * * Like {@link Stream#flatMapToDouble(java.util.function.Function)}. * * @param mapper Like {@link Stream#flatMapToDouble(java.util.function.Function)}. * @return Like {@link Stream#flatMapToDouble(java.util.function.Function)}. * @throws IOException if an I/O error occurs. */ @SuppressWarnings("unused") // thrown by Erase. default DoubleStream flatMapToDouble(final IOFunction mapper) throws IOException { return unwrap().flatMapToDouble(t -> Erase.apply(mapper, t)); } /** * TODO Package-private for now, needs IOIntStream? * * Adding this method now and an IO version later is an issue because call sites would have to type-cast to pick one. It * would be ideal to have only one. * * Like {@link Stream#flatMapToInt(java.util.function.Function)}. * * @param mapper Like {@link Stream#flatMapToInt(java.util.function.Function)}. * @return Like {@link Stream#flatMapToInt(java.util.function.Function)}. * @throws IOException if an I/O error occurs. */ @SuppressWarnings("unused") // thrown by Erase. default IntStream flatMapToInt(final IOFunction mapper) throws IOException { return unwrap().flatMapToInt(t -> Erase.apply(mapper, t)); } /** * TODO Package-private for now, needs IOLongStream? * * Adding this method now and an IO version later is an issue because call sites would have to type-cast to pick one. It * would be ideal to have only one. * * Like {@link Stream#flatMapToLong(java.util.function.Function)}. * * @param mapper Like {@link Stream#flatMapToLong(java.util.function.Function)}. * @return Like {@link Stream#flatMapToLong(java.util.function.Function)}. * @throws IOException if an I/O error occurs. */ @SuppressWarnings("unused") // thrown by Erase. default LongStream flatMapToLong(final IOFunction mapper) throws IOException { return unwrap().flatMapToLong(t -> Erase.apply(mapper, t)); } /** * Performs an action for each element gathering any exceptions. * * @param action The action to apply to each element. * @throws IOExceptionList if any I/O errors occur. */ default void forAll(final IOConsumer action) throws IOExceptionList { forAll(action, (i, e) -> e); } /** * Performs an action for each element gathering any exceptions. * * @param action The action to apply to each element. * @param exSupplier The exception supplier. * @throws IOExceptionList if any I/O errors occur. */ default void forAll(final IOConsumer action, final BiFunction exSupplier) throws IOExceptionList { final AtomicReference> causeList = new AtomicReference<>(); final AtomicInteger index = new AtomicInteger(); final IOConsumer safeAction = IOStreams.toIOConsumer(action); unwrap().forEach(e -> { try { safeAction.accept(e); } catch (final IOException innerEx) { if (causeList.get() == null) { // Only allocate if required causeList.set(new ArrayList<>()); } if (exSupplier != null) { causeList.get().add(exSupplier.apply(index.get(), innerEx)); } } index.incrementAndGet(); }); IOExceptionList.checkEmpty(causeList.get(), null); } /** * Like {@link Stream#forEach(java.util.function.Consumer)} but throws {@link IOException}. * * @param action Like {@link Stream#forEach(java.util.function.Consumer)}. * @throws IOException if an I/O error occurs. */ @SuppressWarnings("unused") // thrown by Erase. default void forEach(final IOConsumer action) throws IOException { unwrap().forEach(e -> Erase.accept(action, e)); } /** * Like {@link Stream#forEachOrdered(java.util.function.Consumer)}. * * @param action Like {@link Stream#forEachOrdered(java.util.function.Consumer)}. * @throws IOException if an I/O error occurs. */ @SuppressWarnings("unused") // thrown by Erase. default void forEachOrdered(final IOConsumer action) throws IOException { unwrap().forEachOrdered(e -> Erase.accept(action, e)); } /** * Like {@link Stream#limit(long)}. * * @param maxSize Like {@link Stream#limit(long)}. * @return Like {@link Stream#limit(long)}. */ default IOStream limit(final long maxSize) { return adapt(unwrap().limit(maxSize)); } /** * Like {@link Stream#map(java.util.function.Function)}. * * @param Like {@link Stream#map(java.util.function.Function)}. * @param mapper Like {@link Stream#map(java.util.function.Function)}. * @return Like {@link Stream#map(java.util.function.Function)}. * @throws IOException if an I/O error occurs. */ @SuppressWarnings("unused") // thrown by Erase. default IOStream map(final IOFunction mapper) throws IOException { return adapt(unwrap().map(t -> Erase.apply(mapper, t))); } /** * TODO Package-private for now, needs IOToDoubleFunction? * * Adding this method now and an IO version later is an issue because call sites would have to type-cast to pick one. It * would be ideal to have only one. * * Like {@link Stream#mapToDouble(ToDoubleFunction)}. * * Package private for now. * * @param mapper Like {@link Stream#mapToDouble(ToDoubleFunction)}. * @return Like {@link Stream#mapToDouble(ToDoubleFunction)}. */ default DoubleStream mapToDouble(final ToDoubleFunction mapper) { return unwrap().mapToDouble(mapper); } /** * TODO Package-private for now, needs IOToIntFunction? * * Adding this method now and an IO version later is an issue because call sites would have to type-cast to pick one. It * would be ideal to have only one. * * Like {@link Stream#mapToInt(ToIntFunction)}. * * Package private for now. * * @param mapper Like {@link Stream#mapToInt(ToIntFunction)}. * @return Like {@link Stream#mapToInt(ToIntFunction)}. */ default IntStream mapToInt(final ToIntFunction mapper) { return unwrap().mapToInt(mapper); } /** * TODO Package-private for now, needs IOToLongFunction? * * Adding this method now and an IO version later is an issue because call sites would have to type-cast to pick one. It * would be ideal to have only one. * * Like {@link Stream#mapToLong(ToLongFunction)}. * * Package private for now. * * @param mapper Like {@link Stream#mapToLong(ToLongFunction)}. * @return Like {@link Stream#mapToLong(ToLongFunction)}. */ default LongStream mapToLong(final ToLongFunction mapper) { return unwrap().mapToLong(mapper); } /** * Like {@link Stream#max(java.util.Comparator)}. * * @param comparator Like {@link Stream#max(java.util.Comparator)}. * @return Like {@link Stream#max(java.util.Comparator)}. * @throws IOException if an I/O error occurs. */ @SuppressWarnings("unused") // thrown by Erase. default Optional max(final IOComparator comparator) throws IOException { return unwrap().max((t, u) -> Erase.compare(comparator, t, u)); } /** * Like {@link Stream#min(java.util.Comparator)}. * * @param comparator Like {@link Stream#min(java.util.Comparator)}. * @return Like {@link Stream#min(java.util.Comparator)}. * @throws IOException if an I/O error occurs. */ @SuppressWarnings("unused") // thrown by Erase. default Optional min(final IOComparator comparator) throws IOException { return unwrap().min((t, u) -> Erase.compare(comparator, t, u)); } /** * Like {@link Stream#noneMatch(java.util.function.Predicate)}. * * @param predicate Like {@link Stream#noneMatch(java.util.function.Predicate)}. * @return Like {@link Stream#noneMatch(java.util.function.Predicate)}. * @throws IOException if an I/O error occurs. */ @SuppressWarnings("unused") // thrown by Erase. default boolean noneMatch(final IOPredicate predicate) throws IOException { return unwrap().noneMatch(t -> Erase.test(predicate, t)); } /** * Like {@link Stream#peek(java.util.function.Consumer)}. * * @param action Like {@link Stream#peek(java.util.function.Consumer)}. * @return Like {@link Stream#peek(java.util.function.Consumer)}. * @throws IOException if an I/O error occurs. */ @SuppressWarnings("unused") // thrown by Erase. default IOStream peek(final IOConsumer action) throws IOException { return adapt(unwrap().peek(t -> Erase.accept(action, t))); } /** * Like {@link Stream#reduce(java.util.function.BinaryOperator)}. * * @param accumulator Like {@link Stream#reduce(java.util.function.BinaryOperator)}. * @return Like {@link Stream#reduce(java.util.function.BinaryOperator)}. * @throws IOException if an I/O error occurs. */ @SuppressWarnings("unused") // thrown by Erase. default Optional reduce(final IOBinaryOperator accumulator) throws IOException { return unwrap().reduce((t, u) -> Erase.apply(accumulator, t, u)); } /** * Like {@link Stream#reduce(Object, java.util.function.BinaryOperator)}. * * @param identity Like {@link Stream#reduce(Object, java.util.function.BinaryOperator)}. * @param accumulator Like {@link Stream#reduce(Object, java.util.function.BinaryOperator)}. * @return Like {@link Stream#reduce(Object, java.util.function.BinaryOperator)}. * @throws IOException if an I/O error occurs. */ @SuppressWarnings("unused") // thrown by Erase. default T reduce(final T identity, final IOBinaryOperator accumulator) throws IOException { return unwrap().reduce(identity, (t, u) -> Erase.apply(accumulator, t, u)); } /** * Like {@link Stream#reduce(Object, BiFunction, java.util.function.BinaryOperator)}. * * @param Like {@link Stream#reduce(Object, BiFunction, java.util.function.BinaryOperator)}. * @param identity Like {@link Stream#reduce(Object, BiFunction, java.util.function.BinaryOperator)}. * @param accumulator Like {@link Stream#reduce(Object, BiFunction, java.util.function.BinaryOperator)}. * @param combiner Like {@link Stream#reduce(Object, BiFunction, java.util.function.BinaryOperator)}. * @return Like {@link Stream#reduce(Object, BiFunction, java.util.function.BinaryOperator)}. * @throws IOException if an I/O error occurs. */ @SuppressWarnings("unused") // thrown by Erase. default U reduce(final U identity, final IOBiFunction accumulator, final IOBinaryOperator combiner) throws IOException { return unwrap().reduce(identity, (t, u) -> Erase.apply(accumulator, t, u), (t, u) -> Erase.apply(combiner, t, u)); } /** * Like {@link Stream#skip(long)}. * * @param n Like {@link Stream#skip(long)}. * @return Like {@link Stream#skip(long)}. */ default IOStream skip(final long n) { return adapt(unwrap().skip(n)); } /** * Like {@link Stream#sorted()}. * * @return Like {@link Stream#sorted()}. */ default IOStream sorted() { return adapt(unwrap().sorted()); } /** * Like {@link Stream#sorted(java.util.Comparator)}. * * @param comparator Like {@link Stream#sorted(java.util.Comparator)}. * @return Like {@link Stream#sorted(java.util.Comparator)}. * @throws IOException if an I/O error occurs. */ @SuppressWarnings("unused") // thrown by Erase. default IOStream sorted(final IOComparator comparator) throws IOException { return adapt(unwrap().sorted((t, u) -> Erase.compare(comparator, t, u))); } /** * Like {@link Stream#toArray()}. * * @return {@link Stream#toArray()}. */ default Object[] toArray() { return unwrap().toArray(); } /** * TODO Package-private for now, needs IOIntFunction? * * Adding this method now and an IO version later is an issue because call sites would have to type-cast to pick one. It * would be ideal to have only one. * * Like {@link Stream#toArray(IntFunction)}. * * Package private for now. * * @param Like {@link Stream#toArray(IntFunction)}. * @param generator Like {@link Stream#toArray(IntFunction)}. * @return Like {@link Stream#toArray(IntFunction)}. */ default A[] toArray(final IntFunction generator) { return unwrap().toArray(generator); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/function/IOStreamAdapter.java0100644 0000000 0000000 00000003021 14603604450 031205 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.util.stream.Stream; /** * Adapts an {@link Stream} as an {@link IOStream}. * * Keep package-private for now. * * @param the type of the stream elements. */ final class IOStreamAdapter extends IOBaseStreamAdapter, Stream> implements IOStream { @SuppressWarnings("resource") static IOStream adapt(final Stream delegate) { return delegate != null ? new IOStreamAdapter<>(delegate) : IOStream.empty(); } private IOStreamAdapter(final Stream delegate) { super(delegate); } @Override public IOStream wrap(final Stream delegate) { return unwrap() == delegate ? this : adapt(delegate); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/function/IOStreams.java0100644 0000000 0000000 00000006341 14603604450 030077 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.BiFunction; import java.util.stream.Stream; import java.util.stream.StreamSupport; import org.apache.commons.io.IOExceptionList; import org.apache.commons.io.IOIndexedException; /** * Keep this code package-private for now. */ final class IOStreams { static final Object NONE = new Object(); static void forAll(final Stream stream, final IOConsumer action) throws IOExceptionList { forAll(stream, action, (i, e) -> e); } @SuppressWarnings("resource") // adapt() static void forAll(final Stream stream, final IOConsumer action, final BiFunction exSupplier) throws IOExceptionList { IOStream.adapt(stream).forAll(action, IOIndexedException::new); } @SuppressWarnings("unused") // IOStreams.rethrow() throws static void forEach(final Stream stream, final IOConsumer action) throws IOException { final IOConsumer actualAction = toIOConsumer(action); of(stream).forEach(e -> Erase.accept(actualAction, e)); } /** * Null-safe version of {@link StreamSupport#stream(java.util.Spliterator, boolean)}. * * Copied from Apache Commons Lang. * * @param the type of stream elements. * @param values the elements of the new stream, may be {@code null}. * @return the new stream on {@code values} or {@link Stream#empty()}. */ static Stream of(final Iterable values) { return values == null ? Stream.empty() : StreamSupport.stream(values.spliterator(), false); } static Stream of(final Stream stream) { return stream == null ? Stream.empty() : stream; } /** * Null-safe version of {@link Stream#of(Object[])}. * * Copied from Apache Commons Lang. * * @param the type of stream elements. * @param values the elements of the new stream, may be {@code null}. * @return the new stream on {@code values} or {@link Stream#empty()}. */ @SafeVarargs // Creating a stream from an array is safe static Stream of(final T... values) { return values == null ? Stream.empty() : Stream.of(values); } static IOConsumer toIOConsumer(final IOConsumer action) { return action != null ? action : IOConsumer.noop(); } private IOStreams() { // no instances } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/function/IOSupplier.java0100644 0000000 0000000 00000003067 14603604450 030266 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.io.UncheckedIOException; 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 { /** * Creates a {@link Supplier} for this instance that throws {@link UncheckedIOException} instead of {@link IOException}. * * @return an UncheckedIOException Supplier. * @since 2.12.0 */ default Supplier asSupplier() { return () -> Uncheck.get(this); } /** * Gets a result. * * @return a result * @throws IOException if an I/O error occurs. */ T get() throws IOException; } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/function/IOTriConsumer.java0100644 0000000 0000000 00000005574 14603604450 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.function; import java.io.IOException; import java.util.Objects; import java.util.function.BiConsumer; /** * Like {@link BiConsumer} but throws {@link IOException}. * * @param the type of the first argument to the operation * @param the type of the second argument to the operation * @param the type of the third argument to the operation * * @see BiConsumer * @since 2.12.0 */ @FunctionalInterface public interface IOTriConsumer { /** * Returns the no-op singleton. * * @param the type of the first argument to the operation * @param the type of the second argument to the operation * @param the type of the third argument to the operation * @return The no-op singleton. */ @SuppressWarnings("unchecked") static IOTriConsumer noop() { return Constants.IO_TRI_CONSUMER; } /** * Performs this operation on the given arguments. * * @param t the first input argument * @param u the second input argument * @param v the second third argument * @throws IOException if an I/O error occurs. */ void accept(T t, U u, V v) throws IOException; /** * Creates a composed {@link IOTriConsumer} 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 {@link IOTriConsumer} that performs in sequence this operation followed by the {@code after} * operation * @throws NullPointerException if {@code after} is null */ default IOTriConsumer andThen(final IOTriConsumer after) { Objects.requireNonNull(after); return (t, u, v) -> { accept(t, u, v); after.accept(t, u, v); }; } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/function/IOTriFunction.java0100644 0000000 0000000 00000005333 14603604450 030725 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.Function; /** * Represents a function that accepts three arguments and produces a result. This is the three-arity specialization of * {@link IOFunction}. * * * * @param the type of the first argument to the function * @param the type of the second argument to the function * @param the type of the third argument to the function * @param the type of the result of the function * * @see Function * @since 2.12.0 */ @FunctionalInterface public interface IOTriFunction { /** * Creates a composed function 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 */ default IOTriFunction andThen(final IOFunction after) { Objects.requireNonNull(after); return (final T t, final U u, final V v) -> after.apply(apply(t, u, v)); } /** * Applies this function to the given arguments. * * @param t the first function argument * @param u the second function argument * @param v the third function argument * @return the function result * @throws IOException if an I/O error occurs. */ R apply(T t, U u, V v) throws IOException; } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/function/IOUnaryOperator.java0100644 0000000 0000000 00000003473 14603604450 031276 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.io.UncheckedIOException; import java.util.function.UnaryOperator; /** * Like {@link UnaryOperator} but throws {@link IOException}. * * @param the type of the operand and result of the operator. * * @see UnaryOperator * @see IOFunction * @since 2.12.0 */ @FunctionalInterface public interface IOUnaryOperator extends IOFunction { /** * Creates a unary operator that always returns its input argument. * * @param the type of the input and output of the operator. * @return a unary operator that always returns its input argument. */ static IOUnaryOperator identity() { return t -> t; } /** * Creates a {@link UnaryOperator} for this instance that throws {@link UncheckedIOException} instead of * {@link IOException}. * * @return an unchecked BiFunction. */ default UnaryOperator asUnaryOperator() { return t -> Uncheck.apply(this, t); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/function/Uncheck.java0100644 0000000 0000000 00000026562 14603604450 027620 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.io.UncheckedIOException; import java.util.function.Supplier; /** * Unchecks calls by throwing {@link UncheckedIOException} instead of {@link IOException}. * * @since 2.12.0 */ public final class Uncheck { /** * Accepts an IO consumer with the given arguments. * * @param the first input type. * @param the second input type. * @param t the first input argument. * @param u the second input argument. * @param consumer Consumes the value. * @throws UncheckedIOException if an I/O error occurs. */ public static void accept(final IOBiConsumer consumer, final T t, final U u) { try { consumer.accept(t, u); } catch (final IOException e) { throw wrap(e); } } /** * Accepts an IO consumer with the given argument. * * @param the input type. * @param t the input argument. * @param consumer Consumes the value. * @throws UncheckedIOException if an I/O error occurs. */ public static void accept(final IOConsumer consumer, final T t) { try { consumer.accept(t); } catch (final IOException e) { throw wrap(e); } } /** * Accepts an IO consumer with the given arguments. * * @param the first input type. * @param the second input type. * @param the third input type. * @param t the first input argument. * @param u the second input argument. * @param v the third input argument. * @param consumer Consumes the value. * @throws UncheckedIOException if an I/O error occurs. */ public static void accept(final IOTriConsumer consumer, final T t, final U u, final V v) { try { consumer.accept(t, u, v); } catch (final IOException e) { throw wrap(e); } } /** * Applies an IO function with the given arguments. * * @param the first function argument type. * @param the second function argument type. * @param the return type. * @param function the function. * @param t the first function argument. * @param u the second function argument. * @return the function result. * @throws UncheckedIOException if an I/O error occurs. */ public static R apply(final IOBiFunction function, final T t, final U u) { try { return function.apply(t, u); } catch (final IOException e) { throw wrap(e); } } /** * Applies an IO function with the given arguments. * * @param function the function. * @param the first function argument type. * @param the return type. * @param t the first function argument. * @return the function result. * @throws UncheckedIOException if an I/O error occurs. */ public static R apply(final IOFunction function, final T t) { try { return function.apply(t); } catch (final IOException e) { throw wrap(e); } } /** * Applies an IO quad-function with the given arguments. * * @param function the function. * @param the first function argument type. * @param the second function argument type. * @param the third function argument type. * @param the fourth function argument type. * @param the return type. * @param t the first function argument. * @param u the second function argument. * @param v the third function argument. * @param w the fourth function argument. * @return the function result. * @throws UncheckedIOException if an I/O error occurs. */ public static R apply(final IOQuadFunction function, final T t, final U u, final V v, final W w) { try { return function.apply(t, u, v, w); } catch (final IOException e) { throw wrap(e); } } /** * Applies an IO tri-function with the given arguments. * * @param the first function argument type. * @param the second function argument type. * @param the third function argument type. * @param the return type. * @param function the function. * @param t the first function argument. * @param u the second function argument. * @param v the third function argument. * @return the function result. * @throws UncheckedIOException if an I/O error occurs. */ public static R apply(final IOTriFunction function, final T t, final U u, final V v) { try { return function.apply(t, u, v); } catch (final IOException e) { throw wrap(e); } } /** * Compares the arguments with the comparator. * * @param the first function argument type. * @param comparator the function. * @param t the first function argument. * @param u the second function argument. * @return the comparator result. * @throws UncheckedIOException if an I/O error occurs. */ public static int compare(final IOComparator comparator, final T t, final T u) { try { return comparator.compare(t, u); } catch (final IOException e) { throw wrap(e); } } /** * Gets the result from an IO supplier. * * @param the return type of the operations. * @param supplier Supplies the return value. * @return result from the supplier. * @throws UncheckedIOException if an I/O error occurs. */ public static T get(final IOSupplier supplier) { try { return supplier.get(); } catch (final IOException e) { throw wrap(e); } } /** * Gets the result from an IO supplier. * * @param the return type of the operations. * @param supplier Supplies the return value. * @param message The UncheckedIOException message if an I/O error occurs. * @return result from the supplier. * @throws UncheckedIOException if an I/O error occurs. */ public static T get(final IOSupplier supplier, final Supplier message) { try { return supplier.get(); } catch (final IOException e) { throw wrap(e, message); } } /** * Gets the result from an IO int supplier. * * @param supplier Supplies the return value. * @return result from the supplier. * @throws UncheckedIOException if an I/O error occurs. * @since 2.14.0 */ public static int getAsInt(final IOIntSupplier supplier) { try { return supplier.getAsInt(); } catch (final IOException e) { throw wrap(e); } } /** * Gets the result from an IO int supplier. * * @param supplier Supplies the return value. * @param message The UncheckedIOException message if an I/O error occurs. * @return result from the supplier. * @throws UncheckedIOException if an I/O error occurs. * @since 2.14.0 */ public static int getAsInt(final IOIntSupplier supplier, final Supplier message) { try { return supplier.getAsInt(); } catch (final IOException e) { throw wrap(e, message); } } /** * Gets the result from an IO long supplier. * * @param supplier Supplies the return value. * @return result from the supplier. * @throws UncheckedIOException if an I/O error occurs. * @since 2.14.0 */ public static long getAsLong(final IOLongSupplier supplier) { try { return supplier.getAsLong(); } catch (final IOException e) { throw wrap(e); } } /** * Gets the result from an IO long supplier. * * @param supplier Supplies the return value. * @param message The UncheckedIOException message if an I/O error occurs. * @return result from the supplier. * @throws UncheckedIOException if an I/O error occurs. * @since 2.14.0 */ public static long getAsLong(final IOLongSupplier supplier, final Supplier message) { try { return supplier.getAsLong(); } catch (final IOException e) { throw wrap(e, message); } } /** * Runs an IO runnable. * * @param runnable The runnable to run. * @throws UncheckedIOException if an I/O error occurs. */ public static void run(final IORunnable runnable) { try { runnable.run(); } catch (final IOException e) { throw wrap(e); } } /** * Runs an IO runnable. * * @param runnable The runnable to run. * @param message The UncheckedIOException message if an I/O error occurs. * @throws UncheckedIOException if an I/O error occurs. * @since 2.14.0 */ public static void run(final IORunnable runnable, final Supplier message) { try { runnable.run(); } catch (final IOException e) { throw wrap(e, message); } } /** * Tests an IO predicate. * * @param the type of the input to the predicate. * @param predicate the predicate. * @param t the input to the predicate. * @return {@code true} if the input argument matches the predicate, otherwise {@code false}. */ public static boolean test(final IOPredicate predicate, final T t) { try { return predicate.test(t); } catch (final IOException e) { throw wrap(e); } } /** * Constructs a new {@link UncheckedIOException} for the given exception. * * @param e The exception to wrap. * @return a new {@link UncheckedIOException}. */ private static UncheckedIOException wrap(final IOException e) { return new UncheckedIOException(e); } /** * Constructs a new {@link UncheckedIOException} for the given exception and detail message. * * @param e The exception to wrap. * @param message The UncheckedIOException message if an I/O error occurs. * @return a new {@link UncheckedIOException}. */ private static UncheckedIOException wrap(final IOException e, final Supplier message) { return new UncheckedIOException(message.get(), e); } /** * No instances needed. */ private Uncheck() { // no instances needed. } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/function/UncheckedIOBaseStream.java0100644 0000000 0000000 00000005014 14603604450 032315 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.io.UncheckedIOException; import java.util.Iterator; import java.util.Spliterator; import java.util.stream.BaseStream; /** * An {@link BaseStream} for a {@link IOBaseStream} that throws {@link UncheckedIOException} instead of * {@link IOException}. * * Keep package-private for now. * * @param the type of the stream elements. * @param the type of the IO stream extending {@code IOBaseStream}. * @param the type of the stream extending {@code BaseStream}. */ final class UncheckedIOBaseStream, B extends BaseStream> implements BaseStream { private final S delegate; UncheckedIOBaseStream(final S delegate) { this.delegate = delegate; } @Override public void close() { delegate.close(); } @Override public boolean isParallel() { return delegate.isParallel(); } @Override public Iterator iterator() { return delegate.iterator().asIterator(); } @SuppressWarnings("resource") @Override public B onClose(final Runnable closeHandler) { return Uncheck.apply(delegate::onClose, () -> closeHandler.run()).unwrap(); } @SuppressWarnings("resource") @Override public B parallel() { return delegate.parallel().unwrap(); } @SuppressWarnings("resource") @Override public B sequential() { return delegate.sequential().unwrap(); } @Override public Spliterator spliterator() { return delegate.spliterator().unwrap(); } @SuppressWarnings("resource") @Override public B unordered() { return delegate.unordered().unwrap(); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/function/UncheckedIOIterator.java0100644 0000000 0000000 00000003406 14603604450 032063 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.io.UncheckedIOException; import java.util.Iterator; import java.util.Objects; /** * An {@link Iterator} for a {@link IOIterator} that throws {@link UncheckedIOException} instead of {@link IOException}. * * Keep package-private for now. * * @param the type of elements returned by this iterator. */ final class UncheckedIOIterator implements Iterator { private final IOIterator delegate; /** * Constructs a new instance. * * @param delegate The delegate */ UncheckedIOIterator(final IOIterator delegate) { this.delegate = Objects.requireNonNull(delegate, "delegate"); } @Override public boolean hasNext() { return Uncheck.get(delegate::hasNext); } @Override public E next() { return Uncheck.get(delegate::next); } @Override public void remove() { Uncheck.run(delegate::remove); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/function/UncheckedIOSpliterator.java0100644 0000000 0000000 00000004745 14603604450 032611 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.io.UncheckedIOException; import java.util.Comparator; import java.util.Objects; import java.util.Spliterator; import java.util.function.Consumer; /** * A {@link Spliterator} for an {@link IOSpliterator} that throws {@link UncheckedIOException} instead of * {@link IOException}. * * Keep package-private for now. * * @param the type of elements returned by this iterator. */ final class UncheckedIOSpliterator implements Spliterator { private final IOSpliterator delegate; UncheckedIOSpliterator(final IOSpliterator delegate) { this.delegate = Objects.requireNonNull(delegate, "delegate"); } @Override public int characteristics() { return delegate.characteristics(); } @Override public long estimateSize() { return delegate.estimateSize(); } @Override public void forEachRemaining(final Consumer action) { Uncheck.accept(delegate::forEachRemaining, action::accept); } @Override public Comparator getComparator() { return delegate.getComparator().asComparator(); } @Override public long getExactSizeIfKnown() { return delegate.getExactSizeIfKnown(); } @Override public boolean hasCharacteristics(final int characteristics) { return delegate.hasCharacteristics(characteristics); } @Override public boolean tryAdvance(final Consumer action) { return Uncheck.apply(delegate::tryAdvance, action::accept); } @Override public Spliterator trySplit() { return Uncheck.get(delegate::trySplit).unwrap(); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/function/package-info.java0100644 0000000 0000000 00000001664 14603604450 030560 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Provides IO-only related functional interfaces for lambda expressions and method references. */ package org.apache.commons.io.function; commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/AbstractCharacterFilterReader.java0100644 0000000 0000000 00000005625 14603604450 033420 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.16.1-src/src/main/java/org/apache/commons/io/input/AutoCloseInputStream.java0100644 0000000 0000000 00000012333 14603604450 031633 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.build.AbstractStreamBuilder; /** * 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. *

*

* To build an instance, use {@link Builder}. *

* * @since 1.4 * @see Builder */ public class AutoCloseInputStream extends ProxyInputStream { // @formatter:off /** * Builds a new {@link AutoCloseInputStream} instance. * *

* For example: *

*
{@code
     * AutoCloseInputStream s = AutoCloseInputStream.builder()
     *   .setPath(path)
     *   .get();}
     * 
*
{@code
     * AutoCloseInputStream s = AutoCloseInputStream.builder()
     *   .setInputStream(inputStream)
     *   .get();}
     * 
* * @see #get() * @since 2.13.0 */ // @formatter:on public static class Builder extends AbstractStreamBuilder { /** * Builds a new {@link AutoCloseInputStream}. *

* You must set input that supports {@link #getInputStream()}, otherwise, this method throws an exception. *

*

* This builder use the following aspects: *

*
    *
  • {@link #getInputStream()}
  • *
* * @return a new instance. * @throws IllegalStateException if the {@code origin} is {@code null}. * @throws UnsupportedOperationException if the origin cannot be converted to an {@link InputStream}. * @throws IOException if an I/O error occurs. * @see #getInputStream() */ @SuppressWarnings("resource") // Caller closes @Override public AutoCloseInputStream get() throws IOException { return new AutoCloseInputStream(getInputStream()); } } /** * Constructs a new {@link Builder}. * * @return a new {@link Builder}. * @since 2.12.0 */ public static Builder builder() { return new Builder(); } /** * Constructs an automatically closing proxy for the given input stream. * * @param in underlying input stream * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated public AutoCloseInputStream(final InputStream in) { super(in); } /** * 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(); } } /** * 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.INSTANCE; } /** * 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.16.1-src/src/main/java/org/apache/commons/io/input/BOMInputStream.java0100644 0000000 0000000 00000040673 14603604450 030362 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 java.util.Objects; import org.apache.commons.io.ByteOrderMark; import org.apache.commons.io.IOUtils; import org.apache.commons.io.build.AbstractStreamBuilder; /** * 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 predefined 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}
  • *
*

* To build an instance, use {@link Builder}. *

*

Example 1 - Detecting and excluding a UTF-8 BOM

* *
 * BOMInputStream bomIn = BOMInputStream.builder().setInputStream(in).get();
 * if (bomIn.hasBOM()) {
 *     // has a UTF-8 BOM
 * }
 * 
* *

Example 2 - Detecting a UTF-8 BOM without excluding it

* *
 * boolean include = true;
 * BOMInputStream bomIn = BOMInputStream.builder()
 *     .setInputStream(in)
 *     .setInclude(include)
 *     .get();
 * if (bomIn.hasBOM()) {
 *     // has a UTF-8 BOM
 * }
 * 
* *

Example 3 - Detecting Multiple BOMs

* *
 * BOMInputStream bomIn = BOMInputStream.builder()
 *   .setInputStream(in)
 *   .setByteOrderMarks(ByteOrderMark.UTF_16LE, ByteOrderMark.UTF_16BE, ByteOrderMark.UTF_32LE, ByteOrderMark.UTF_32BE)
 *   .get();
 * 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
 * }
 * 
*

* To build an instance, use {@link Builder}. *

* * @see Builder * @see org.apache.commons.io.ByteOrderMark * @see Wikipedia - Byte Order Mark * @since 2.0 */ public class BOMInputStream extends ProxyInputStream { // @formatter:off /** * Builds a new {@link BOMInputStream}. * *

Using NIO

*
{@code
     * BOMInputStream s = BOMInputStream.builder()
     *   .setPath(Paths.get("MyFile.xml"))
     *   .setByteOrderMarks(ByteOrderMark.UTF_8)
     *   .setInclude(false)
     *   .get();}
     * 
*

Using IO

*
{@code
     * BOMInputStream s = BOMInputStream.builder()
     *   .setFile(new File("MyFile.xml"))
     *   .setByteOrderMarks(ByteOrderMark.UTF_8)
     *   .setInclude(false)
     *   .get();}
     * 
* * @see #get() * @since 2.12.0 */ // @formatter:on public static class Builder extends AbstractStreamBuilder { private static final ByteOrderMark[] DEFAULT = { ByteOrderMark.UTF_8 }; /** * For test access. * * @return the default byte order mark */ static ByteOrderMark getDefaultByteOrderMark() { return DEFAULT[0]; } private ByteOrderMark[] byteOrderMarks = DEFAULT; private boolean include; /** * Builds a new {@link BOMInputStream}. *

* You must set input that supports {@link #getInputStream()}, otherwise, this method throws an exception. *

*

* This builder use the following aspects: InputStream, OpenOption[], include, and ByteOrderMark[]. *

*

* This builder use the following aspects: *

*
    *
  • {@link #getInputStream()}
  • *
  • include}
  • *
  • byteOrderMarks
  • *
* * @return a new instance. * @throws IllegalStateException if the {@code origin} is {@code null}. * @throws UnsupportedOperationException if the origin cannot be converted to an {@link InputStream}. * @throws IOException if an I/O error occurs. * @see #getInputStream() */ @SuppressWarnings("resource") @Override public BOMInputStream get() throws IOException { return new BOMInputStream(getInputStream(), include, byteOrderMarks); } /** * Sets the ByteOrderMarks to detect and optionally exclude. *

* The default is {@link ByteOrderMark#UTF_8}. *

* * @param byteOrderMarks the ByteOrderMarks to detect and optionally exclude. * @return this */ public Builder setByteOrderMarks(final ByteOrderMark... byteOrderMarks) { this.byteOrderMarks = byteOrderMarks != null ? byteOrderMarks.clone() : DEFAULT; return this; } /** * Sets whether to include the UTF-8 BOM (true) or to exclude it (false). *

* The default is false. *

* * @param include true to include the UTF-8 BOM or false to exclude it. return this; * @return this */ public Builder setInclude(final boolean include) { this.include = include; return this; } } /** * Compares ByteOrderMark objects in descending length order. */ private static final Comparator ByteOrderMarkLengthComparator = Comparator.comparing(ByteOrderMark::length).reversed(); /** * Constructs a new {@link Builder}. * * @return a new {@link Builder}. * @since 2.12.0 */ public static Builder builder() { return new Builder(); } /** * BOMs are sorted from longest to shortest. */ private final List boms; private ByteOrderMark byteOrderMark; private int fbIndex; private int fbLength; private int[] firstBytes; private final boolean include; private boolean markedAtStart; private int markFbIndex; /** * Constructs a new BOM InputStream that excludes a {@link ByteOrderMark#UTF_8} BOM. * * @param delegate * the InputStream to delegate to * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated public BOMInputStream(final InputStream delegate) { this(delegate, false, Builder.DEFAULT); } /** * Constructs a new BOM InputStream that detects 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 * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated public BOMInputStream(final InputStream delegate, final boolean include) { this(delegate, include, Builder.DEFAULT); } /** * 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 * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated 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; } /** * 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 * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated public BOMInputStream(final InputStream delegate, final ByteOrderMark... boms) { this(delegate, false, boms); } /** * Find a BOM with the specified bytes. * * @return The matched BOM or null if none matched */ private ByteOrderMark find() { return boms.stream().filter(this::matches).findFirst().orElse(null); } /** * Gets 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; } /** * Gets 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(); } /** * Tests 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; } /** * Tests 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 configured to detect " + bom); } return Objects.equals(getBOM(), bom); } /** * 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); } /** * Checks 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; } /** * 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[])} 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 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; } /** * 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; } /** * 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.16.1-src/src/main/java/org/apache/commons/io/input/BoundedInputStream.java0100644 0000000 0000000 00000041167 14603604450 031324 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; import org.apache.commons.io.build.AbstractStreamBuilder; //@formatter:off /** * Reads bytes up to a maximum count and stops once reached. *

* To build an instance, see {@link AbstractBuilder}. *

*

* By default, a {@link BoundedInputStream} is unbound; so make sure to call {@link AbstractBuilder#setMaxCount(long)}. *

*

* You can find out how many bytes this stream has seen so far by calling {@link BoundedInputStream#getCount()}. This value reflects bytes read and skipped. *

*

Using a ServletInputStream

*

* A {@code ServletInputStream} can block if you try to read content that isn't there * because it doesn't know whether the content hasn't arrived yet or whether the content has finished. Initialize an {@link BoundedInputStream} with the * {@code Content-Length} sent in the {@code ServletInputStream}'s header, this stop it from blocking, providing it's been sent with a correct content * length in the first place. *

*

Using NIO

*
{@code
 * BoundedInputStream s = BoundedInputStream.builder()
 *   .setPath(Paths.get("MyFile.xml"))
 *   .setMaxCount(1024)
 *   .setPropagateClose(false)
 *   .get();
 * }
 * 
*

Using IO

*
{@code
 * BoundedInputStream s = BoundedInputStream.builder()
 *   .setFile(new File("MyFile.xml"))
 *   .setMaxCount(1024)
 *   .setPropagateClose(false)
 *   .get();
 * }
 * 
*

Counting Bytes

*

You can set the running count when building, which is most useful when starting from another stream: *

{@code
 * InputStream in = ...;
 * BoundedInputStream s = BoundedInputStream.builder()
 *   .setInputStream(in)
 *   .setCount(12)
 *   .setMaxCount(1024)
 *   .setPropagateClose(false)
 *   .get();
 * }
 * 
* @see Builder * @since 2.0 */ //@formatter:on public class BoundedInputStream extends ProxyInputStream { /** * For subclassing builders from {@link BoundedInputStream} subclassses. * * @param The subclass. */ static abstract class AbstractBuilder> extends AbstractStreamBuilder { /** The current count of bytes counted. */ private long count; /** The max count of bytes to read. */ private long maxCount = EOF; /** Flag if {@link #close()} should be propagated, {@code true} by default. */ private boolean propagateClose = true; long getCount() { return count; } long getMaxCount() { return maxCount; } boolean isPropagateClose() { return propagateClose; } /** * Sets the current number of bytes counted. *

* Useful when building from another stream to carry forward a read count. *

*

* Default is {@code 0}, negative means 0. *

* * @param count The current number of bytes counted. * @return this. */ public T setCount(final long count) { this.count = Math.max(0, count); return asThis(); } /** * Sets the maximum number of bytes to return. *

* Default is {@value IOUtils#EOF}, negative means unbound. *

* * @param maxCount The maximum number of bytes to return. * @return this. */ public T setMaxCount(final long maxCount) { this.maxCount = Math.max(EOF, maxCount); return asThis(); } /** * Sets whether the {@link #close()} method should propagate to the underling {@link InputStream}. *

* Default is {@code true}. *

* * @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. * @return this. */ public T setPropagateClose(final boolean propagateClose) { this.propagateClose = propagateClose; return asThis(); } } //@formatter:off /** * Builds a new {@link BoundedInputStream}. *

* By default, a {@link BoundedInputStream} is unbound; so make sure to call {@link AbstractBuilder#setMaxCount(long)}. *

*

* You can find out how many bytes this stream has seen so far by calling {@link BoundedInputStream#getCount()}. This value reflects bytes read and skipped. *

*

Using a ServletInputStream

*

* A {@code ServletInputStream} can block if you try to read content that isn't there * because it doesn't know whether the content hasn't arrived yet or whether the content has finished. Initialize an {@link BoundedInputStream} with the * {@code Content-Length} sent in the {@code ServletInputStream}'s header, this stop it from blocking, providing it's been sent with a correct content * length in the first place. *

*

Using NIO

*
{@code
     * BoundedInputStream s = BoundedInputStream.builder()
     *   .setPath(Paths.get("MyFile.xml"))
     *   .setMaxCount(1024)
     *   .setPropagateClose(false)
     *   .get();
     * }
     * 
*

Using IO

*
{@code
     * BoundedInputStream s = BoundedInputStream.builder()
     *   .setFile(new File("MyFile.xml"))
     *   .setMaxCount(1024)
     *   .setPropagateClose(false)
     *   .get();
     * }
     * 
*

Counting Bytes

*

You can set the running count when building, which is most useful when starting from another stream: *

{@code
     * InputStream in = ...;
     * BoundedInputStream s = BoundedInputStream.builder()
     *   .setInputStream(in)
     *   .setCount(12)
     *   .setMaxCount(1024)
     *   .setPropagateClose(false)
     *   .get();
     * }
     * 
* * @see #get() * @since 2.16.0 */ //@formatter:on public static class Builder extends AbstractBuilder { /** * Builds a new {@link BoundedInputStream}. *

* You must set input that supports {@link #getInputStream()}, otherwise, this method throws an exception. *

*

* This builder use the following aspects: *

*
    *
  • {@link #getInputStream()}
  • *
  • maxCount
  • *
  • propagateClose
  • *
* * @return a new instance. * @throws IllegalStateException if the {@code origin} is {@code null}. * @throws UnsupportedOperationException if the origin cannot be converted to an {@link InputStream}. * @throws IOException if an I/O error occurs. * @see #getInputStream() */ @SuppressWarnings("resource") @Override public BoundedInputStream get() throws IOException { return new BoundedInputStream(getInputStream(), getCount(), getMaxCount(), isPropagateClose()); } } /** * Constructs a new {@link AbstractBuilder}. * * @return a new {@link AbstractBuilder}. * @since 2.16.0 */ public static Builder builder() { return new Builder(); } /** The current count of bytes counted. */ private long count; /** The current mark. */ private long mark; /** The max count of bytes to read. */ private final long maxCount; /** * Flag if close should be propagated. * * TODO Make final in 3.0. */ private boolean propagateClose = true; /** * Constructs a new {@link BoundedInputStream} that wraps the given input stream and is unlimited. * * @param in The wrapped input stream. * @deprecated Use {@link AbstractBuilder#get()}. */ @Deprecated public BoundedInputStream(final InputStream in) { this(in, EOF); } /** * Constructs a new {@link BoundedInputStream} that wraps the given input stream and limits it to a certain size. * * @param inputStream The wrapped input stream. * @param maxCount The maximum number of bytes to return. * @deprecated Use {@link AbstractBuilder#get()}. */ @Deprecated public BoundedInputStream(final InputStream inputStream, final long maxCount) { // Some badly designed methods - e.g. the Servlet API - overload length // such that "-1" means stream finished this(inputStream, 0, maxCount, true); } /** * Constructs a new {@link BoundedInputStream} that wraps the given input stream and limits it to a certain size. * * @param inputStream The wrapped input stream. * @param count The current number of bytes read. * @param maxCount The maximum number of bytes to return. * @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. */ BoundedInputStream(final InputStream inputStream, final long count, final long maxCount, final boolean propagateClose) { // Some badly designed methods - e.g. the Servlet API - overload length // such that "-1" means stream finished // Can't throw because we start from an InputStream. super(inputStream); this.count = count; this.maxCount = maxCount; this.propagateClose = propagateClose; } /** * Adds the number of read bytes to the count. * * @param n number of bytes read, or -1 if no more bytes are available * @throws IOException Not thrown here but subclasses may throw. * @since 2.0 */ @Override protected synchronized void afterRead(final int n) throws IOException { if (n != EOF) { count += n; } } /** * {@inheritDoc} */ @Override public int available() throws IOException { if (isMaxCount()) { onMaxLength(maxCount, getCount()); return 0; } return in.available(); } /** * Invokes the delegate's {@link InputStream#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(); } } /** * Gets the count of bytes read. * * @return The count of bytes read. * @since 2.12.0 */ public synchronized long getCount() { return count; } /** * Gets the max count of bytes to read. * * @return The max count of bytes to read. * @since 2.16.0 */ public long getMaxCount() { return maxCount; } /** * Gets the max count of bytes to read. * * @return The max count of bytes to read. * @since 2.12.0 * @deprecated Use {@link #getMaxCount()}. */ @Deprecated public long getMaxLength() { return maxCount; } /** * Gets how many bytes remain to read. * * @return bytes how many bytes remain to read. * @since 2.16.0 */ public long getRemaining() { return Math.max(0, getMaxCount() - getCount()); } private boolean isMaxCount() { return maxCount >= 0 && getCount() >= maxCount; } /** * Tests 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; } /** * Invokes the delegate's {@link InputStream#mark(int)} method. * * @param readLimit read ahead limit */ @Override public synchronized void mark(final int readLimit) { in.mark(readLimit); mark = count; } /** * Invokes the delegate's {@link InputStream#markSupported()} method. * * @return true if mark is supported, otherwise false */ @Override public boolean markSupported() { return in.markSupported(); } /** * A caller has caused a request that would cross the {@code maxLength} boundary. * * @param maxLength The max count of bytes to read. * @param count The count of bytes read. * @throws IOException Subclasses may throw. * @since 2.12.0 */ @SuppressWarnings("unused") protected void onMaxLength(final long maxLength, final long count) throws IOException { // for subclasses } /** * Invokes the delegate's {@link InputStream#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 (isMaxCount()) { onMaxLength(maxCount, getCount()); return EOF; } return super.read(); } /** * Invokes the delegate's {@link InputStream#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 read(b, 0, b.length); } /** * Invokes the delegate's {@link InputStream#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 (isMaxCount()) { onMaxLength(maxCount, getCount()); return EOF; } return super.read(b, off, (int) toReadLen(len)); } /** * Invokes the delegate's {@link InputStream#reset()} method. * * @throws IOException if an I/O error occurs. */ @Override public synchronized void reset() throws IOException { in.reset(); count = mark; } /** * Sets 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. * @deprecated Use {@link AbstractBuilder#setPropagateClose(boolean)}. */ @Deprecated public void setPropagateClose(final boolean propagateClose) { this.propagateClose = propagateClose; } /** * Invokes the delegate's {@link InputStream#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 synchronized long skip(final long n) throws IOException { final long skip = super.skip(toReadLen(n)); count += skip; return skip; } private long toReadLen(final long len) { return maxCount >= 0 ? Math.min(len, maxCount - getCount()) : len; } /** * Invokes the delegate's {@link InputStream#toString()} method. * * @return the delegate's {@link InputStream#toString()} */ @Override public String toString() { return in.toString(); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/BoundedReader.java0100644 0000000 0000000 00000011124 14603604450 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(); } /** * 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; } /** * 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(); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/BrokenInputStream.java0100644 0000000 0000000 00000010251 14603604450 031152 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.function.Supplier; import org.apache.commons.io.function.Erase; /** * Always throws an exception from all {@link InputStream} methods where {@link IOException} is declared. *

* This class is mostly useful for testing error handling. *

* * @since 2.0 */ public class BrokenInputStream extends InputStream { /** * The singleton instance using a default IOException. * * @since 2.12.0 */ public static final BrokenInputStream INSTANCE = new BrokenInputStream(); /** * A supplier for the exception that is thrown by all methods of this class. */ private final Supplier exceptionSupplier; /** * Constructs a new stream that always throws an {@link IOException}. */ public BrokenInputStream() { this(() -> new IOException("Broken input stream")); } /** * Constructs a new stream that always throws the given exception. * * @param exception the exception to be thrown. * @deprecated Use {@link #BrokenInputStream(Throwable)}. */ @Deprecated public BrokenInputStream(final IOException exception) { this(() -> exception); } /** * Constructs a new stream that always throws the supplied exception. * * @param exceptionSupplier a supplier for the IOException or RuntimeException to be thrown. * @since 2.12.0 */ public BrokenInputStream(final Supplier exceptionSupplier) { this.exceptionSupplier = exceptionSupplier; } /** * Constructs a new stream that always throws the given exception. * * @param exception the exception to be thrown. * @since 2.16.0 */ public BrokenInputStream(final Throwable exception) { this(() -> exception); } /** * Throws the configured exception. * * @return nothing. * @throws IOException always throws the exception configured in a constructor. */ @Override public int available() throws IOException { throw rethrow(); } /** * Throws the configured exception. * * @throws IOException always throws the exception configured in a constructor. */ @Override public void close() throws IOException { throw rethrow(); } /** * Throws the configured exception. * * @return nothing. * @throws IOException always throws the exception configured in a constructor. */ @Override public int read() throws IOException { throw rethrow(); } /** * Throws the configured exception. * * @throws IOException always throws the exception configured in a constructor. */ @Override public synchronized void reset() throws IOException { throw rethrow(); } /** * Throws the configured exception from its supplier. * * @return Throws the configured exception from its supplier. */ private RuntimeException rethrow() { return Erase.rethrow(exceptionSupplier.get()); } /** * Throws the configured exception. * * @param n ignored. * @return nothing. * @throws IOException always throws the exception configured in a constructor. */ @Override public long skip(final long n) throws IOException { throw rethrow(); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/BrokenReader.java0100644 0000000 0000000 00000011013 14603604450 030076 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.util.function.Supplier; import org.apache.commons.io.function.Erase; /** * Always throws an exception from all {@link Reader} methods where {@link IOException} is declared. *

* This class is mostly useful for testing error handling. *

* * @since 2.7 */ public class BrokenReader extends Reader { /** * A singleton instance using a default IOException. * * @since 2.12.0 */ public static final BrokenReader INSTANCE = new BrokenReader(); /** * A supplier for the exception that is thrown by all methods of this class. */ private final Supplier exceptionSupplier; /** * Constructs a new reader that always throws an {@link IOException}. */ public BrokenReader() { this(() -> new IOException("Broken reader")); } /** * Constructs a new reader that always throws the given exception. * * @param exception the exception to be thrown. * @deprecated Use {@link #BrokenReader(Throwable)}. */ @Deprecated public BrokenReader(final IOException exception) { this(() -> exception); } /** * Constructs a new reader that always throws the supplied exception. * * @param exceptionSupplier a supplier for the IOException or RuntimeException to be thrown. * @since 2.12.0 */ public BrokenReader(final Supplier exceptionSupplier) { this.exceptionSupplier = exceptionSupplier; } /** * Constructs a new reader that always throws the given exception. * * @param exception the exception to be thrown. * @since 2.16.0 */ public BrokenReader(final Throwable exception) { this(() -> exception); } /** * Throws the configured exception. * * @throws IOException always throws the exception configured in a constructor. */ @Override public void close() throws IOException { throw rethrow(); } /** * Throws the configured exception. * * @param readAheadLimit ignored. * @throws IOException always throws the exception configured in a constructor. */ @Override public void mark(final int readAheadLimit) throws IOException { throw rethrow(); } /** * Throws the configured exception. * * @param cbuf ignored. * @param off ignored. * @param len ignored. * @return nothing. * @throws IOException always throws the exception configured in a constructor. */ @Override public int read(final char[] cbuf, final int off, final int len) throws IOException { throw rethrow(); } /** * Throws the configured exception. * * @return nothing. * @throws IOException always throws the exception configured in a constructor. */ @Override public boolean ready() throws IOException { throw rethrow(); } /** * Throws the configured exception. * * @throws IOException always throws the exception configured in a constructor. */ @Override public void reset() throws IOException { throw rethrow(); } /** * Throws the configured exception from its supplier. * * @return Throws the configured exception from its supplier. */ private RuntimeException rethrow() { return Erase.rethrow(exceptionSupplier.get()); } /** * Throws the configured exception. * * @param n ignored. * @return nothing. * @throws IOException always throws the exception configured in a constructor. */ @Override public long skip(final long n) throws IOException { throw rethrow(); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/BufferedFileChannelInputStream.java0100644 0000000 0000000 00000022702 14603604450 033551 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.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; import org.apache.commons.io.build.AbstractStreamBuilder; /** * {@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. *

* To build an instance, use {@link Builder}. *

*

* This class was ported and adapted from Apache Spark commit 933dc6cb7b3de1d8ccaf73d124d6eb95b947ed19 where it was called {@code NioBufferedFileInputStream}. *

* * @see Builder * @since 2.9.0 */ public final class BufferedFileChannelInputStream extends InputStream { // @formatter:off /** * Builds a new {@link BufferedFileChannelInputStream}. * *

* Using File IO: *

*
{@code
     * BufferedFileChannelInputStream s = BufferedFileChannelInputStream.builder()
     *   .setFile(file)
     *   .setBufferSize(4096)
     *   .get();}
     * 
*

* Using NIO Path: *

*
{@code
     * BufferedFileChannelInputStream s = BufferedFileChannelInputStream.builder()
     *   .setPath(path)
     *   .setBufferSize(4096)
     *   .get();}
     * 
* * @see #get() * @since 2.12.0 */ // @formatter:on public static class Builder extends AbstractStreamBuilder { /** * Builds a new {@link BufferedFileChannelInputStream}. *

* You must set input that supports {@link #getInputStream()}, otherwise, this method throws an exception. *

*

* This builder use the following aspects: *

*
    *
  • {@link #getInputStream()}
  • *
  • {@link #getBufferSize()}
  • *
* * @return a new instance. * @throws IllegalStateException if the {@code origin} is {@code null}. * @throws UnsupportedOperationException if the origin cannot be converted to a {@link Path}. * @throws IOException If an I/O error occurs * @see #getPath() * @see #getBufferSize() */ @Override public BufferedFileChannelInputStream get() throws IOException { return new BufferedFileChannelInputStream(getPath(), getBufferSize()); } } /** * Constructs a new {@link Builder}. * * @return a new {@link Builder}. * @since 2.12.0 */ public static Builder builder() { return new Builder(); } private final ByteBuffer byteBuffer; private final FileChannel fileChannel; /** * Constructs a new instance for the given File. * * @param file The file to stream. * @throws IOException If an I/O error occurs * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated 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 bufferSize buffer size. * @throws IOException If an I/O error occurs * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated public BufferedFileChannelInputStream(final File file, final int bufferSize) throws IOException { this(file.toPath(), bufferSize); } /** * Constructs a new instance for the given Path. * * @param path The path to stream. * @throws IOException If an I/O error occurs * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated 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 bufferSize buffer size. * @throws IOException If an I/O error occurs * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated public BufferedFileChannelInputStream(final Path path, final int bufferSize) throws IOException { Objects.requireNonNull(path, "path"); fileChannel = FileChannel.open(path, StandardOpenOption.READ); byteBuffer = ByteBuffer.allocateDirect(bufferSize); 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 (buffer.isDirect()) { cleanDirectBuffer(buffer); } } /** * In Java 8, the type of {@code sun.nio.ch.DirectBuffer.cleaner()} was {@code sun.misc.Cleaner}, and it was possible to access the method * {@code sun.misc.Cleaner.clean()} to invoke it. The type changed to {@code jdk.internal.ref.Cleaner} in later JDKs, and the {@code clean()} method is not * accessible even with reflection. However {@code sun.misc.Unsafe} added an {@code 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) { if (ByteBufferCleaner.isSupported()) { ByteBufferCleaner.clean(buffer); } } @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 * @throws IOException if an I/O error occurs. */ 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.16.1-src/src/main/java/org/apache/commons/io/input/ByteBufferCleaner.java0100644 0000000 0000000 00000010442 14603604450 031067 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.lang.reflect.Field; import java.lang.reflect.Method; import java.nio.ByteBuffer; /** * Cleans a direct {@link ByteBuffer}. Without manual intervention, direct ByteBuffers will be cleaned eventually upon * garbage collection. However, this should not be relied upon since it may not occur in a timely fashion - * especially since off heap ByeBuffers don't put pressure on the garbage collector. *

* Warning: Do not attempt to use a direct {@link ByteBuffer} that has been cleaned or bad things will happen. * Don't use this class unless you can ensure that the cleaned buffer will not be accessed anymore. *

*

* See JDK-4724038 *

*/ final class ByteBufferCleaner { private interface Cleaner { void clean(ByteBuffer buffer) throws ReflectiveOperationException; } private static final class Java8Cleaner implements Cleaner { private final Method cleanerMethod; private final Method cleanMethod; private Java8Cleaner() throws ReflectiveOperationException, SecurityException { cleanMethod = Class.forName("sun.misc.Cleaner").getMethod("clean"); cleanerMethod = Class.forName("sun.nio.ch.DirectBuffer").getMethod("cleaner"); } @Override public void clean(final ByteBuffer buffer) throws ReflectiveOperationException { final Object cleaner = cleanerMethod.invoke(buffer); if (cleaner != null) { cleanMethod.invoke(cleaner); } } } private static final class Java9Cleaner implements Cleaner { private final Object theUnsafe; private final Method invokeCleaner; private Java9Cleaner() throws ReflectiveOperationException, SecurityException { final Class unsafeClass = Class.forName("sun.misc.Unsafe"); final Field field = unsafeClass.getDeclaredField("theUnsafe"); field.setAccessible(true); theUnsafe = field.get(null); invokeCleaner = unsafeClass.getMethod("invokeCleaner", ByteBuffer.class); } @Override public void clean(final ByteBuffer buffer) throws ReflectiveOperationException { invokeCleaner.invoke(theUnsafe, buffer); } } private static final Cleaner INSTANCE = getCleaner(); /** * Releases memory held by the given {@link ByteBuffer}. * * @param buffer to release. * @throws IllegalStateException on internal failure. */ static void clean(final ByteBuffer buffer) { try { INSTANCE.clean(buffer); } catch (final Exception e) { throw new IllegalStateException("Failed to clean direct buffer.", e); } } private static Cleaner getCleaner() { try { return new Java8Cleaner(); } catch (final Exception e) { try { return new Java9Cleaner(); } catch (final Exception e1) { throw new IllegalStateException("Failed to initialize a Cleaner.", e); } } } /** * Tests if were able to load a suitable cleaner for the current JVM. Attempting to call * {@code ByteBufferCleaner#clean(ByteBuffer)} when this method returns false will result in an exception. * * @return {@code true} if cleaning is supported, {@code false} otherwise. */ static boolean isSupported() { return INSTANCE != null; } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/CharSequenceInputStream.java0100644 0000000 0000000 00000033143 14603604450 032305 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; import org.apache.commons.io.Charsets; import org.apache.commons.io.IOUtils; import org.apache.commons.io.build.AbstractStreamBuilder; import org.apache.commons.io.charset.CharsetEncoders; import org.apache.commons.io.function.Uncheck; /** * Implements an {@link InputStream} to read bytes from String, StringBuffer, StringBuilder or CharBuffer, * encoded using the specified Charset. The Charset defaults to Charset.defaultCharset(). *

* Note: Supports {@link #mark(int)} and {@link #reset()}. *

*

* To build an instance, use {@link Builder}. *

* * @see Builder * @since 2.2 */ public class CharSequenceInputStream extends InputStream { //@formatter:off /** * Builds a new {@link CharSequenceInputStream}. * *

* For example: *

*

Using a Charset

*
{@code
     * CharSequenceInputStream s = CharSequenceInputStream.builder()
     *   .setBufferSize(8192)
     *   .setCharSequence("String")
     *   .setCharset(Charset.defaultCharset())
     *   .get();}
     * 
*

Using a CharsetEncoder

*
{@code
     * CharSequenceInputStream s = CharSequenceInputStream.builder()
     *   .setBufferSize(8192)
     *   .setCharSequence("String")
     *   .setCharsetEncoder(Charset.defaultCharset().newEncoder()
     *     .onMalformedInput(CodingErrorAction.REPLACE)
     *     .onUnmappableCharacter(CodingErrorAction.REPLACE))
     *   .get();}
     * 
* * @see #get() * @since 2.13.0 */ //@formatter:on public static class Builder extends AbstractStreamBuilder { private CharsetEncoder charsetEncoder = newEncoder(getCharset()); /** * Builds a new {@link CharSequenceInputStream}. *

* You must set input that supports {@link #getCharSequence()}, otherwise, this method throws an exception. *

*

* This builder use the following aspects: *

*
    *
  • {@link #getCharSequence()}
  • *
  • {@link #getBufferSize()}
  • *
  • {@link CharsetEncoder}
  • *
* * @return a new instance. * @throws IllegalArgumentException if the buffer is not large enough to hold a complete character. */ @Override public CharSequenceInputStream get() { return Uncheck.get(() -> new CharSequenceInputStream(getCharSequence(), getBufferSize(), charsetEncoder)); } CharsetEncoder getCharsetEncoder() { return charsetEncoder; } @Override public Builder setCharset(final Charset charset) { super.setCharset(charset); charsetEncoder = newEncoder(getCharset()); return this; } /** * Sets the charset encoder. Assumes that the caller has configured the encoder. * * @param newEncoder the charset encoder. * @return this * @since 2.13.0 */ public Builder setCharsetEncoder(final CharsetEncoder newEncoder) { charsetEncoder = CharsetEncoders.toCharsetEncoder(newEncoder, () -> newEncoder(getCharsetDefault())); super.setCharset(charsetEncoder.charset()); return this; } } private static final int NO_MARK = -1; /** * Constructs a new {@link Builder}. * * @return a new {@link Builder}. * @since 2.12.0 */ public static Builder builder() { return new Builder(); } private static CharsetEncoder newEncoder(final Charset charset) { // @formatter:off return Charsets.toCharset(charset).newEncoder() .onMalformedInput(CodingErrorAction.REPLACE) .onUnmappableCharacter(CodingErrorAction.REPLACE); // @formatter:on } private final ByteBuffer bBuf; private int bBufMark; // position in bBuf private final CharBuffer cBuf; private int cBufMark; // position in cBuf private final CharsetEncoder charsetEncoder; /** * Constructs a new instance with a buffer size of {@link IOUtils#DEFAULT_BUFFER_SIZE}. * * @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. * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated public CharSequenceInputStream(final CharSequence cs, final Charset charset) { this(cs, charset, IOUtils.DEFAULT_BUFFER_SIZE); } /** * Constructs a new instance. * * @param cs the input character sequence. * @param charset the character set name to use, null maps to the default Charset. * @param bufferSize the buffer size to use. * @throws IllegalArgumentException if the buffer is not large enough to hold a complete character. * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated public CharSequenceInputStream(final CharSequence cs, final Charset charset, final int bufferSize) { // @formatter:off this(cs, bufferSize, newEncoder(charset)); // @formatter:on } private CharSequenceInputStream(final CharSequence cs, final int bufferSize, final CharsetEncoder charsetEncoder) { this.charsetEncoder = charsetEncoder; // Ensure that buffer is long enough to hold a complete character this.bBuf = ByteBuffer.allocate(ReaderInputStream.checkMinBufferSize(charsetEncoder, bufferSize)); this.bBuf.flip(); this.cBuf = CharBuffer.wrap(cs); this.cBufMark = NO_MARK; this.bBufMark = NO_MARK; try { fillBuffer(); } catch (final CharacterCodingException ex) { // Reset everything without filling the buffer // so the same exception can be thrown again later. this.bBuf.clear(); this.bBuf.flip(); this.cBuf.rewind(); } } /** * Constructs a new instance with a buffer size of {@link IOUtils#DEFAULT_BUFFER_SIZE}. * * @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. * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated public CharSequenceInputStream(final CharSequence cs, final String charset) { this(cs, charset, IOUtils.DEFAULT_BUFFER_SIZE); } /** * Constructs a new instance. * * @param cs the input character sequence. * @param charset the character set name to use, null maps to the default Charset. * @param bufferSize the buffer size to use. * @throws IllegalArgumentException if the buffer is not large enough to hold a complete character. * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated public CharSequenceInputStream(final CharSequence cs, final String charset, final int bufferSize) { this(cs, Charsets.toCharset(charset), bufferSize); } /** * Gets a lower bound on 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 { return this.bBuf.remaining(); } @Override public void close() throws IOException { // noop } /** * 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.charsetEncoder.encode(this.cBuf, this.bBuf, true); if (result.isError()) { result.throwException(); } this.bBuf.flip(); } /** * Gets the CharsetEncoder. * * @return the CharsetEncoder. */ CharsetEncoder getCharsetEncoder() { return charsetEncoder; } /** * {@inheritDoc} * @param readLimit max read limit (ignored). */ @Override public synchronized void mark(final int readLimit) { this.cBufMark = this.cBuf.position(); this.bBufMark = 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 boolean markSupported() { return true; } @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 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 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 optimizations 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.cBufMark != NO_MARK) { // if cBuf is at 0, we have not started reading anything, so skip re-encoding if (this.cBuf.position() != 0) { this.charsetEncoder.reset(); this.cBuf.rewind(); this.bBuf.rewind(); this.bBuf.limit(0); // rewind does not clear the buffer while (this.cBuf.position() < this.cBufMark) { this.bBuf.rewind(); // empty the buffer (we only refill when empty during normal processing) this.bBuf.limit(0); fillBuffer(); } } if (this.cBuf.position() != this.cBufMark) { throw new IllegalStateException("Unexpected CharBuffer position: actual=" + cBuf.position() + " " + "expected=" + this.cBufMark); } this.bBuf.position(this.bBufMark); this.cBufMark = NO_MARK; this.bBufMark = NO_MARK; } mark(0); } @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; } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/CharSequenceReader.java0100644 0000000 0000000 00000024104 14603604450 031231 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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()}. *

*

Deprecating Serialization

*

* Serialization is deprecated and will be removed in 3.0. *

* * @since 1.4 */ public class CharSequenceReader extends Reader implements Serializable { private static final long serialVersionUID = 3724187752191401220L; /** Source for reading. */ private final CharSequence charSequence; /** Reading index. */ private int idx; /** Reader mark. */ 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; } /** * Close resets the file back to the start and removes any marked position. */ @Override public void close() { idx = start; mark = 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); } /** * 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; } /** * 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(); } /** * 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; } /** * 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); } /** * Gets a String representation of the underlying * character sequence. * * @return The contents of the character sequence */ @Override public String toString() { return charSequence.subSequence(start(), end()).toString(); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/CharacterFilterReader.java0100644 0000000 0000000 00000003555 14603604450 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.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.16.1-src/src/main/java/org/apache/commons/io/input/CharacterSetFilterReader.java0100644 0000000 0000000 00000004444 14603604450 032406 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 {@link 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.16.1-src/src/main/java/org/apache/commons/io/input/ChecksumInputStream.java0100644 0000000 0000000 00000020727 14603604450 031505 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.zip.CheckedInputStream; import java.util.zip.Checksum; import org.apache.commons.io.build.AbstractStreamBuilder; /** * Automatically verifies a {@link Checksum} value once the stream is exhausted or the count threshold is reached. *

* If the {@link Checksum} does not meet the expected value when exhausted, then the input stream throws an * {@link IOException}. *

*

* If you do not need the verification or threshold feature, then use a plain {@link CheckedInputStream}. *

*

* To build an instance, use {@link Builder}. *

* * @see Builder * @since 2.16.0 */ public final class ChecksumInputStream extends CountingInputStream { // @formatter:off /** * Builds a new {@link ChecksumInputStream}. * *

* There is no default {@link Checksum}; you MUST provide one. *

*

Using NIO

*
{@code
     * ChecksumInputStream s = ChecksumInputStream.builder()
     *   .setPath(Paths.get("MyFile.xml"))
     *   .setChecksum(new CRC32())
     *   .setExpectedChecksumValue(12345)
     *   .get();
     * }
*

Using IO

*
{@code
     * ChecksumInputStream s = ChecksumInputStream.builder()
     *   .setFile(new File("MyFile.xml"))
     *   .setChecksum(new CRC32())
     *   .setExpectedChecksumValue(12345)
     *   .get();
     * }
*

Validating only part of an InputStream

*

* The following validates the first 100 bytes of the given input. *

*
{@code
     * ChecksumInputStream s = ChecksumInputStream.builder()
     *   .setPath(Paths.get("MyFile.xml"))
     *   .setChecksum(new CRC32())
     *   .setExpectedChecksumValue(12345)
     *   .setCountThreshold(100)
     *   .get();
     * }
*

* To validate input after the beginning of a stream, build an instance with an InputStream starting where you want to validate. *

*
{@code
     * InputStream inputStream = ...;
     * inputStream.read(...);
     * inputStream.skip(...);
     * ChecksumInputStream s = ChecksumInputStream.builder()
     *   .setInputStream(inputStream)
     *   .setChecksum(new CRC32())
     *   .setExpectedChecksumValue(12345)
     *   .setCountThreshold(100)
     *   .get();
     * }
* * @see #get() */ // @formatter:on public static class Builder extends AbstractStreamBuilder { /** * There is no default checksum, you MUST provide one. This avoids any issue with a default {@link Checksum} * being proven deficient or insecure in the future. */ private Checksum checksum; /** * The count threshold to limit how much input is consumed to update the {@link Checksum} before the input * stream validates its value. *

* By default, all input updates the {@link Checksum}. *

*/ private long countThreshold = -1; /** * The expected {@link Checksum} value once the stream is exhausted or the count threshold is reached. */ private long expectedChecksumValue; /** * Builds a new {@link ChecksumInputStream}. *

* You must set input that supports {@link #getInputStream()}, otherwise, this method throws an exception. *

*

* This builder use the following aspects: *

*
    *
  • {@link #getInputStream()}
  • *
  • {@link Checksum}
  • *
  • expectedChecksumValue
  • *
  • countThreshold
  • *
* * @return a new instance. * @throws IllegalStateException if the {@code origin} is {@code null}. * @throws UnsupportedOperationException if the origin cannot be converted to an {@link InputStream}. * @throws IOException if an I/O error occurs. * @see #getInputStream() */ @SuppressWarnings("resource") @Override public ChecksumInputStream get() throws IOException { return new ChecksumInputStream(getInputStream(), checksum, expectedChecksumValue, countThreshold); } /** * Sets the Checksum. * * @param checksum the Checksum. * @return this. */ public Builder setChecksum(final Checksum checksum) { this.checksum = checksum; return this; } /** * Sets the count threshold to limit how much input is consumed to update the {@link Checksum} before the input * stream validates its value. *

* By default, all input updates the {@link Checksum}. *

* * @param countThreshold the count threshold. A negative number means the threshold is unbound. * @return this. */ public Builder setCountThreshold(final long countThreshold) { this.countThreshold = countThreshold; return this; } /** * The expected {@link Checksum} value once the stream is exhausted or the count threshold is reached. * * @param expectedChecksumValue The expected Checksum value. * @return this. */ public Builder setExpectedChecksumValue(final long expectedChecksumValue) { this.expectedChecksumValue = expectedChecksumValue; return this; } } /** * Constructs a new {@link Builder}. * * @return a new {@link Builder}. */ public static Builder builder() { return new Builder(); } /** The expected checksum. */ private final long expectedChecksumValue; /** * The count threshold to limit how much input is consumed to update the {@link Checksum} before the input stream * validates its value. *

* By default, all input updates the {@link Checksum}. *

*/ private final long countThreshold; /** * Constructs a new instance. * * @param in the stream to wrap. * @param checksum a Checksum implementation. * @param expectedChecksumValue the expected checksum. * @param countThreshold the count threshold to limit how much input is consumed, a negative number means the * threshold is unbound. */ private ChecksumInputStream(final InputStream in, final Checksum checksum, final long expectedChecksumValue, final long countThreshold) { super(new CheckedInputStream(in, checksum)); this.countThreshold = countThreshold; this.expectedChecksumValue = expectedChecksumValue; } @Override protected synchronized void afterRead(final int n) throws IOException { super.afterRead(n); if ((countThreshold > 0 && getByteCount() >= countThreshold || n == EOF) && expectedChecksumValue != getChecksum().getValue()) { // Validate when past the threshold or at EOF throw new IOException("Checksum verification failed."); } } /** * Gets the current checksum value. * * @return the current checksum value. */ private Checksum getChecksum() { return ((CheckedInputStream) in).getChecksum(); } /** * Gets the byte count remaining to read. * * @return bytes remaining to read, a negative number means the threshold is unbound. */ public long getRemaining() { return countThreshold - getByteCount(); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/CircularInputStream.java0100644 0000000 0000000 00000005646 14603604450 031512 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 = IOUtils.EOF; private final byte[] repeatedContent; private final long targetByteCount; /** * Constructs 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.16.1-src/src/main/java/org/apache/commons/io/input/ClassLoaderObjectInputStream.java0100644 0000000 0000000 00000007426 14603604450 033267 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 * {@link 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(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.16.1-src/src/main/java/org/apache/commons/io/input/CloseShieldInputStream.java0100644 0000000 0000000 00000004474 14603604450 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.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 { /** * Constructs 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); } /** * Constructs 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.INSTANCE; } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/CloseShieldReader.java0100644 0000000 0000000 00000004251 14603604450 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 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 { /** * Constructs 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); } /** * Constructs 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.INSTANCE; } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/ClosedInputStream.java0100644 0000000 0000000 00000004173 14603604450 031151 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; /** * Always returns {@link IOUtils#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 { /** * The singleton instance. * * @since 2.12.0 */ public static final ClosedInputStream INSTANCE = new ClosedInputStream(); /** * The singleton instance. * * @deprecated Use {@link #INSTANCE}. */ @Deprecated public static final ClosedInputStream CLOSED_INPUT_STREAM = INSTANCE; /** * Returns -1 to indicate that the stream is closed. * * @return always -1 */ @Override public int read() { return EOF; } /** * Returns -1 to indicate that the stream is closed. * * @param b ignored. * @param off ignored. * @param len ignored. * @return always -1 */ @Override public int read(final byte[] b, final int off, final int len) throws IOException { return EOF; } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/ClosedReader.java0100644 0000000 0000000 00000003727 14603604450 030104 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 org.apache.commons.io.IOUtils; /** * Always returns {@link IOUtils#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 { /** * The singleton instance. * * @since 2.12.0 */ public static final ClosedReader INSTANCE = new ClosedReader(); /** * The singleton instance. * * @deprecated {@link #INSTANCE}. */ @Deprecated public static final ClosedReader CLOSED_READER = INSTANCE; @Override public void close() throws IOException { // noop } /** * 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; } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/CountingInputStream.java0100644 0000000 0000000 00000011441 14603604450 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.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. *

* @deprecated Use {@link BoundedInputStream} (unbounded by default). */ @Deprecated 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); } /** * Adds the number of read bytes to the count. * * @param n number of bytes read, or -1 if no more bytes are available * @throws IOException Not thrown here but subclasses may throw. * @since 2.0 */ @Override protected synchronized void afterRead(final int n) throws IOException { if (n != EOF) { count += n; } } /** * Gets 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 count; } /** * Gets number of bytes that have passed through this stream. *

* 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 * @deprecated Use {@link #getByteCount()}. */ @Deprecated 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; } /** * Resets 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 = count; count = 0; return tmp; } /** * Resets the byte count back to 0. *

* 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 * @deprecated Use {@link #resetByteCount()}. */ @Deprecated 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; } /** * 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); count += skip; return skip; } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/DemuxInputStream.java0100644 0000000 0000000 00000004476 14603604450 031030 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.16.1-src/src/main/java/org/apache/commons/io/input/InfiniteCircularInputStream.java0100644 0000000 0000000 00000003066 14603604450 033172 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 { /** * Constructs 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.16.1-src/src/main/java/org/apache/commons/io/input/MarkShieldInputStream.java0100644 0000000 0000000 00000004061 14603604450 031757 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 is not desirable to allow marking of the stream. *

* * @since 2.8.0 */ public class MarkShieldInputStream extends ProxyInputStream { /** * Constructs 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(); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/MemoryMappedFileInputStream.java0100644 0000000 0000000 00000017567 14603604450 033152 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.channels.FileChannel.MapMode; import java.nio.file.Path; import java.nio.file.StandardOpenOption; import org.apache.commons.io.build.AbstractStreamBuilder; /** * An {@link InputStream} that utilizes memory mapped files to improve performance. A sliding window of the file is * mapped to memory to avoid mapping the entire file to memory at one time. The size of the sliding buffer is * configurable. *

* For most operating systems, mapping a file into memory is more expensive than reading or writing a few tens of * kilobytes of data. From the standpoint of performance. it is generally only worth mapping relatively large files into * memory. *

*

* Note: Use of this class does not necessarily obviate the need to use a {@link BufferedInputStream}. Depending on the * use case, the use of buffering may still further improve performance. For example: *

*

* To build an instance, use {@link Builder}. *

*
{@code
 * BufferedInputStream s = new BufferedInputStream(new GzipInputStream(
 *   MemoryMappedFileInputStream.builder()
 *     .setPath(path)
 *     .setBufferSize(256 * 1024)
 *     .get()));}
 * 
*

* should outperform: *

*
 * new GzipInputStream(new MemoryMappedFileInputStream(path))
 * 
*
{@code
 * GzipInputStream s = new GzipInputStream(
 *   MemoryMappedFileInputStream.builder()
 *     .setPath(path)
 *     .setBufferSize(256 * 1024)
 *     .get());}
 * 
* * @see Builder * @since 2.12.0 */ public final class MemoryMappedFileInputStream extends InputStream { // @formatter:off /** * Builds a new {@link MemoryMappedFileInputStream}. * *

* For example: *

*
{@code
     * MemoryMappedFileInputStream s = MemoryMappedFileInputStream.builder()
     *   .setPath(path)
     *   .setBufferSize(256 * 1024)
     *   .get();}
     * 
* * @see #get() * @since 2.12.0 */ // @formatter:on public static class Builder extends AbstractStreamBuilder { /** * Constructs a new {@link Builder}. */ public Builder() { setBufferSizeDefault(DEFAULT_BUFFER_SIZE); setBufferSize(DEFAULT_BUFFER_SIZE); } /** * Builds a new {@link MemoryMappedFileInputStream}. *

* You must set input that supports {@link #getPath()}, otherwise, this method throws an exception. *

*

* This builder use the following aspects: *

*
    *
  • {@link #getPath()}
  • *
  • {@link #getBufferSize()}
  • *
* * @return a new instance. * @throws IllegalStateException if the {@code origin} is {@code null}. * @throws UnsupportedOperationException if the origin cannot be converted to a {@link Path}. * @throws IOException if an I/O error occurs. * @see #getPath() * @see #getBufferSize() */ @Override public MemoryMappedFileInputStream get() throws IOException { return new MemoryMappedFileInputStream(getPath(), getBufferSize()); } } /** * Default size of the sliding memory mapped buffer. We use 256K, equal to 65536 pages (given a 4K page size). * Increasing the value beyond the default size will generally not provide any increase in throughput. */ private static final int DEFAULT_BUFFER_SIZE = 256 * 1024; private static final ByteBuffer EMPTY_BUFFER = ByteBuffer.wrap(new byte[0]).asReadOnlyBuffer(); /** * Constructs a new {@link Builder}. * * @return a new {@link Builder}. * @since 2.12.0 */ public static Builder builder() { return new Builder(); } private final int bufferSize; private final FileChannel channel; private ByteBuffer buffer = EMPTY_BUFFER; private boolean closed; /** * The starting position (within the file) of the next sliding buffer. */ private long nextBufferPosition; /** * Constructs a new instance. * * @param file The path of the file to open. * @param bufferSize Size of the sliding buffer. * @throws IOException If an I/O error occurs. */ private MemoryMappedFileInputStream(final Path file, final int bufferSize) throws IOException { this.bufferSize = bufferSize; this.channel = FileChannel.open(file, StandardOpenOption.READ); } @Override public int available() throws IOException { return buffer.remaining(); } private void cleanBuffer() { if (ByteBufferCleaner.isSupported() && buffer.isDirect()) { ByteBufferCleaner.clean(buffer); } } @Override public void close() throws IOException { if (!closed) { cleanBuffer(); buffer = null; channel.close(); closed = true; } } private void ensureOpen() throws IOException { if (closed) { throw new IOException("Stream closed"); } } int getBufferSize() { return bufferSize; } private void nextBuffer() throws IOException { final long remainingInFile = channel.size() - nextBufferPosition; if (remainingInFile > 0) { final long amountToMap = Math.min(remainingInFile, bufferSize); cleanBuffer(); buffer = channel.map(MapMode.READ_ONLY, nextBufferPosition, amountToMap); nextBufferPosition += amountToMap; } else { buffer = EMPTY_BUFFER; } } @Override public int read() throws IOException { ensureOpen(); if (!buffer.hasRemaining()) { nextBuffer(); if (!buffer.hasRemaining()) { return EOF; } } return Short.toUnsignedInt(buffer.get()); } @Override public int read(final byte[] b, final int off, final int len) throws IOException { ensureOpen(); if (!buffer.hasRemaining()) { nextBuffer(); if (!buffer.hasRemaining()) { return EOF; } } final int numBytes = Math.min(buffer.remaining(), len); buffer.get(b, off, numBytes); return numBytes; } @Override public long skip(final long n) throws IOException { ensureOpen(); if (n <= 0) { return 0; } if (n <= buffer.remaining()) { buffer.position((int) (buffer.position() + n)); return n; } final long remainingInFile = channel.size() - nextBufferPosition; final long skipped = buffer.remaining() + Math.min(remainingInFile, n - buffer.remaining()); nextBufferPosition += skipped - buffer.remaining(); nextBuffer(); return skipped; } } ././@LongLink0100644 0000000 0000000 00000000151 14603604450 011632 Lustar 0000000 0000000 commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/MessageDigestCalculatingInputStream.javacommons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/MessageDigestCalculatingInputStream.0100644 0000000 0000000 00000024177 14603604450 033777 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; import java.security.Provider; import java.util.Objects; import org.apache.commons.io.build.AbstractStreamBuilder; /** * 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 {@link MessageDigest}, for example, a SHA-512 sum. *

* To build an instance, use {@link Builder}. *

*

* See the MessageDigest section in the Java * Cryptography Architecture Standard Algorithm Name Documentation for information about standard algorithm names. *

*

* Note: Neither {@link ObservableInputStream}, nor {@link MessageDigest}, are thread safe, so is {@link MessageDigestCalculatingInputStream}. *

* * @see Builder * @deprecated Use {@link MessageDigestInputStream}. */ @Deprecated public class MessageDigestCalculatingInputStream extends ObservableInputStream { // @formatter:off /** * Builds a new {@link MessageDigestCalculatingInputStream}. * *

* For example: *

*
{@code
     * MessageDigestCalculatingInputStream s = MessageDigestCalculatingInputStream.builder()
     *   .setPath(path)
     *   .setMessageDigest("SHA-512")
     *   .get();}
     * 
* * @see #get() * @since 2.12.0 */ // @formatter:on public static class Builder extends AbstractStreamBuilder { private MessageDigest messageDigest; /** * Constructs a new {@link Builder}. */ public Builder() { try { this.messageDigest = getDefaultMessageDigest(); } catch (final NoSuchAlgorithmException e) { // Should not happen. throw new IllegalStateException(e); } } /** * Builds a new {@link MessageDigestCalculatingInputStream}. *

* You must set input that supports {@link #getInputStream()}, otherwise, this method throws an exception. *

*

* This builder use the following aspects: *

*
    *
  • {@link #getPath()}
  • *
  • {@link MessageDigest}
  • *
* * @return a new instance. * @throws NullPointerException if messageDigest is null. * @throws IllegalStateException if the {@code origin} is {@code null}. * @throws UnsupportedOperationException if the origin cannot be converted to an {@link InputStream}. * @throws IOException if an I/O error occurs. * @see #getInputStream() */ @SuppressWarnings("resource") @Override public MessageDigestCalculatingInputStream get() throws IOException { return new MessageDigestCalculatingInputStream(getInputStream(), messageDigest); } /** * Sets the message digest. *

* The MD5 cryptographic algorithm is weak and should not be used. *

* * @param messageDigest the message digest. */ public void setMessageDigest(final MessageDigest messageDigest) { this.messageDigest = messageDigest; } /** * Sets the name of the name of the message digest algorithm. *

* The MD5 cryptographic algorithm is weak and should not be used. *

* * @param algorithm the name of the algorithm. See the MessageDigest section in the * Java Cryptography * Architecture Standard Algorithm Name Documentation for information about standard algorithm names. * @throws NoSuchAlgorithmException if no Provider supports a MessageDigestSpi implementation for the specified algorithm. */ public void setMessageDigest(final String algorithm) throws NoSuchAlgorithmException { this.messageDigest = MessageDigest.getInstance(algorithm); } } /** * Maintains the message digest. */ public static class MessageDigestMaintainingObserver extends Observer { private final MessageDigest messageDigest; /** * Constructs an MessageDigestMaintainingObserver for the given MessageDigest. * * @param messageDigest the message digest to use * @throws NullPointerException if messageDigest is null. */ public MessageDigestMaintainingObserver(final MessageDigest messageDigest) { this.messageDigest = Objects.requireNonNull(messageDigest, "messageDigest"); } @Override public void data(final byte[] input, final int offset, final int length) throws IOException { messageDigest.update(input, offset, length); } @Override public void data(final int input) throws IOException { messageDigest.update((byte) input); } } /** * The default message digest algorithm. *

* The MD5 cryptographic algorithm is weak and should not be used. *

*/ private static final String DEFAULT_ALGORITHM = "MD5"; /** * Constructs a new {@link Builder}. * * @return a new {@link Builder}. * @since 2.12.0 */ public static Builder builder() { return new Builder(); } /** * Gets a MessageDigest object that implements the default digest algorithm. * * @return a Message Digest object that implements the default algorithm. * @throws NoSuchAlgorithmException if no Provider supports a MessageDigestSpi implementation. * @see Provider */ static MessageDigest getDefaultMessageDigest() throws NoSuchAlgorithmException { return MessageDigest.getInstance(DEFAULT_ALGORITHM); } private final MessageDigest messageDigest; /** * Constructs a new instance, which calculates a signature on the given stream, using a {@link MessageDigest} with the "MD5" algorithm. *

* The MD5 algorithm is weak and should not be used. *

* * @param inputStream the stream to calculate the message digest for * @throws NoSuchAlgorithmException if no Provider supports a MessageDigestSpi implementation for the specified algorithm. * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}. */ @Deprecated public MessageDigestCalculatingInputStream(final InputStream inputStream) throws NoSuchAlgorithmException { this(inputStream, getDefaultMessageDigest()); } /** * Constructs a new instance, which calculates a signature on the given stream, using the given {@link MessageDigest}. *

* The MD5 cryptographic algorithm is weak and should not be used. *

* * @param inputStream the stream to calculate the message digest for * @param messageDigest the message digest to use * @throws NullPointerException if messageDigest is null. * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}. */ @Deprecated public MessageDigestCalculatingInputStream(final InputStream inputStream, final MessageDigest messageDigest) { super(inputStream, new MessageDigestMaintainingObserver(messageDigest)); this.messageDigest = messageDigest; } /** * Constructs a new instance, which calculates a signature on the given stream, using a {@link MessageDigest} with the given algorithm. *

* The MD5 cryptographic algorithm is weak and should not be used. *

* * @param inputStream the stream to calculate the message digest for * @param algorithm the name of the algorithm requested. See the MessageDigest section in the * Java Cryptography * Architecture Standard Algorithm Name Documentation for information about standard algorithm names. * @throws NoSuchAlgorithmException if no Provider supports a MessageDigestSpi implementation for the specified algorithm. * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}. */ @Deprecated public MessageDigestCalculatingInputStream(final InputStream inputStream, final String algorithm) throws NoSuchAlgorithmException { this(inputStream, MessageDigest.getInstance(algorithm)); } /** * Gets 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.16.1-src/src/main/java/org/apache/commons/io/input/MessageDigestInputStream.java0100644 0000000 0000000 00000016600 14603604450 032462 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; import java.util.Objects; import org.apache.commons.io.build.AbstractStreamBuilder; /** * 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 {@link MessageDigest}, for example, a SHA-512 sum. *

* To build an instance, use {@link Builder}. *

*

* See the MessageDigest section in the Java * Cryptography Architecture Standard Algorithm Name Documentation for information about standard algorithm names. *

*

* You must specify a message digest algorithm name or instance. *

*

* Note: Neither {@link ObservableInputStream}, nor {@link MessageDigest}, are thread safe, so is {@link MessageDigestInputStream}. *

* * @see Builder * @since 2.15.0 */ public final class MessageDigestInputStream extends ObservableInputStream { // @formatter:off /** * Builds new {@link MessageDigestInputStream}. * *

* For example: *

*
{@code
     * MessageDigestInputStream s = MessageDigestInputStream.builder()
     *   .setPath(path)
     *   .setMessageDigest("SHA-512")
     *   .get();}
     * 
*

* You must specify a message digest algorithm name or instance. *

* * @see #get() */ // @formatter:on public static class Builder extends AbstractStreamBuilder { private MessageDigest messageDigest; /** * Constructs a new {@link Builder}. */ public Builder() { // empty } /** * Builds new {@link MessageDigestInputStream}. *

* You must set input that supports {@link #getInputStream()}, otherwise, this method throws an exception. *

*

* This builder use the following aspects: *

*
    *
  • {@link #getPath()}
  • *
  • {@link MessageDigest}
  • *
* * @return a new instance. * @throws NullPointerException if messageDigest is null. * @throws IllegalStateException if the {@code origin} is {@code null}. * @throws UnsupportedOperationException if the origin cannot be converted to an {@link InputStream}. * @throws IOException if an I/O error occurs. * @see #getInputStream() */ @SuppressWarnings("resource") @Override public MessageDigestInputStream get() throws IOException { return new MessageDigestInputStream(getInputStream(), messageDigest); } /** * Sets the message digest. *

* The MD5 cryptographic algorithm is weak and should not be used. *

* * @param messageDigest the message digest. * @return this */ public Builder setMessageDigest(final MessageDigest messageDigest) { this.messageDigest = messageDigest; return this; } /** * Sets the name of the name of the message digest algorithm. *

* The MD5 cryptographic algorithm is weak and should not be used. *

* * @param algorithm the name of the algorithm. See the MessageDigest section in the * Java Cryptography * Architecture Standard Algorithm Name Documentation for information about standard algorithm names. * @return this * @throws NoSuchAlgorithmException if no Provider supports a MessageDigestSpi implementation for the specified algorithm. */ public Builder setMessageDigest(final String algorithm) throws NoSuchAlgorithmException { this.messageDigest = MessageDigest.getInstance(algorithm); return this; } } /** * Maintains the message digest. */ public static class MessageDigestMaintainingObserver extends Observer { private final MessageDigest messageDigest; /** * Constructs an MessageDigestMaintainingObserver for the given MessageDigest. * * @param messageDigest the message digest to use * @throws NullPointerException if messageDigest is null. */ public MessageDigestMaintainingObserver(final MessageDigest messageDigest) { this.messageDigest = Objects.requireNonNull(messageDigest, "messageDigest"); } @Override public void data(final byte[] input, final int offset, final int length) throws IOException { messageDigest.update(input, offset, length); } @Override public void data(final int input) throws IOException { messageDigest.update((byte) input); } } /** * Constructs a new {@link Builder}. * * @return a new {@link Builder}. */ public static Builder builder() { return new Builder(); } private final MessageDigest messageDigest; /** * Constructs a new instance, which calculates a signature on the given stream, using the given {@link MessageDigest}. *

* The MD5 cryptographic algorithm is weak and should not be used. *

* * @param inputStream the stream to calculate the message digest for * @param messageDigest the message digest to use * @throws NullPointerException if messageDigest is null. */ private MessageDigestInputStream(final InputStream inputStream, final MessageDigest messageDigest) { super(inputStream, new MessageDigestMaintainingObserver(messageDigest)); this.messageDigest = messageDigest; } /** * Gets 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.16.1-src/src/main/java/org/apache/commons/io/input/NullInputStream.java0100644 0000000 0000000 00000025766 14603604450 030665 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 { /** * The singleton instance. * * @since 2.12.0 */ public static final NullInputStream INSTANCE = new NullInputStream(); 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; /** * Constructs 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); } /** * Constructs 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); } /** * Constructs 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; } /** * Returns 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; } /** * Throws {@link EOFException} if {@code throwEofException} is enabled. * * @param message The {@link EOFException} message. * @throws EOFException Thrown if {@code throwEofException} is enabled. */ private void checkThrowEof(final String message) throws EOFException { if (throwEofException) { throw new EOFException(message); } } /** * Closes 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; } /** * Gets the current position. * * @return the current position. */ public long getPosition() { return position; } /** * Gets the size this {@link InputStream} emulates. * * @return The size of the input stream to emulate. */ public long getSize() { return size; } /** * 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 handleEof() throws EOFException { eof = true; checkThrowEof("handleEof()"); return EOF; } /** * Marks 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; } /** * Tests whether mark is supported. * * @return Whether mark is supported or not. */ @Override public boolean markSupported() { return markSupported; } /** * Returns 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; } /** * Processes 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 } /** * Reads 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) { checkThrowEof("read()"); return EOF; } if (position == size) { return handleEof(); } position++; return processByte(); } /** * Reads 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); } /** * Reads 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) { checkThrowEof("read(byte[], int, int)"); return EOF; } if (position == size) { return handleEof(); } position += length; int returnLength = length; if (position > size) { returnLength = length - (int) (position - size); position = size; } processBytes(bytes, 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 exceeded 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 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) { checkThrowEof("skip(long)"); return EOF; } if (position == size) { return handleEof(); } position += numberOfBytes; long returnLength = numberOfBytes; if (position > size) { returnLength = numberOfBytes - (position - size); position = size; } return returnLength; } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/NullReader.java0100644 0000000 0000000 00000024700 14603604450 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 { /** * The singleton instance. * * @since 2.12.0 */ public static final NullReader INSTANCE = new NullReader(); 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; /** * Constructs 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); } /** * Constructs 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); } /** * Constructs 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; } /** * 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; } /** * 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; } /** * 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; } /** * 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; } /** * 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 } /** * 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 exceeded 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; } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/ObservableInputStream.java0100644 0000000 0000000 00000024610 14603604450 032022 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; import org.apache.commons.io.function.IOConsumer; /** * 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 MessageDigestInputStream */ public class ObservableInputStream extends ProxyInputStream { /** * Abstracts observer callback for {@link 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; /** * Constructs a new ObservableInputStream for the given InputStream. * * @param inputStream the input stream to observe. */ public ObservableInputStream(final InputStream inputStream) { this(inputStream, new ArrayList<>()); } /** * Constructs 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; } /** * Constructs 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 { IOUtils.consume(this); } private void forEachObserver(final IOConsumer action) throws IOException { IOConsumer.forAll(action, observers); } /** * Gets a copy of currently registered observers. * * @return a copy of the list of currently registered observers. * @since 2.9.0 */ public List getObservers() { return new ArrayList<>(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 { forEachObserver(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 { forEachObserver(observer -> 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 { forEachObserver(observer -> 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 { forEachObserver(observer -> 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 { forEachObserver(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.16.1-src/src/main/java/org/apache/commons/io/input/ProxyInputStream.java0100644 0000000 0000000 00000021054 14603604450 031056 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 a {@link FilterInputStream}, by passing all method calls on to the proxied stream, not changing which methods are called. *

* It is an alternative base class to {@link FilterInputStream} to increase reusability, because {@link FilterInputStream} changes the methods being called, * such as read(byte[]) to read(byte[], int, int). *

*

* In addition, this class allows you to: *

*
    *
  • notify a subclass that n bytes are about to be read through {@link #beforeRead(int)}
  • *
  • notify a subclass that n bytes were read through {@link #afterRead(int)}
  • *
  • notify a subclass that an exception was caught through {@link #handleIOException(IOException)}
  • *
  • {@link #unwrap()} itself
  • *
*

* This class does not add any state (no additional instance variables). *

*/ 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' } /** * Invoked by the {@code 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 in a subclass. */ @SuppressWarnings("unused") // Possibly thrown from subclasses. protected void afterRead(final int n) throws IOException { // no-op default } /** * 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; } } /** * Invoked by the {@code 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 in a subclass. */ @SuppressWarnings("unused") // Possibly thrown from subclasses. protected void beforeRead(final int n) throws IOException { // no-op default } /** * 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); } /** * Handles any IOExceptions thrown; by default, throws the given exception. *

* 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; } /** * 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 markSupported()} method. * * @return true if mark is supported, otherwise false */ @Override public boolean markSupported() { return in.markSupported(); } /** * 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 b 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[] b) throws IOException { try { beforeRead(IOUtils.length(b)); final int n = in.read(b); afterRead(n); return n; } catch (final IOException e) { handleIOException(e); return EOF; } } /** * 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 * @throws IOException if an I/O error occurs. */ @Override public int read(final byte[] b, final int off, final int len) throws IOException { try { beforeRead(len); final int n = in.read(b, off, len); afterRead(n); return n; } catch (final IOException e) { handleIOException(e); return EOF; } } /** * 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 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 { try { return in.skip(n); } catch (final IOException e) { handleIOException(e); return 0; } } /** * Unwraps this instance by returning the underlying InputStream. *

* Use with caution; useful to query the underlying InputStream. *

* @return the underlying InputStream. * @since 2.16.0 */ public InputStream unwrap() { return in; } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/ProxyReader.java0100644 0000000 0000000 00000020623 14603604450 030006 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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' } /** * 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 } /** * 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 } /** * 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); } } /** * 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; } /** * 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 markSupported()} method. * @return true if mark is supported, otherwise false */ @Override public boolean markSupported() { return in.markSupported(); } /** * 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 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 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 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; } } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/QueueInputStream.java0100644 0000000 0000000 00000015766 14603604450 031036 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.PipedInputStream; import java.io.PipedOutputStream; import java.time.Duration; import java.util.Objects; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import org.apache.commons.io.build.AbstractStreamBuilder; import org.apache.commons.io.output.QueueOutputStream; /** * Simple alternative to JDK {@link java.io.PipedInputStream}; queue input stream provides what's written in queue output stream. *

* To build an instance, use {@link Builder}. *

*

* 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 {@link QueueInputStream} has no effect. The methods in this class can be called after the stream has been closed without generating an * {@link IOException}. *

* * @see Builder * @see QueueOutputStream * @since 2.9.0 */ public class QueueInputStream extends InputStream { // @formatter:off /** * Builds a new {@link QueueInputStream}. * *

* For example: *

*
{@code
     * QueueInputStream s = QueueInputStream.builder()
     *   .setBlockingQueue(new LinkedBlockingQueue<>())
     *   .setTimeout(Duration.ZERO)
     *   .get();}
     * 
* * @see #get() * @since 2.12.0 */ // @formatter:on public static class Builder extends AbstractStreamBuilder { private BlockingQueue blockingQueue = new LinkedBlockingQueue<>(); private Duration timeout = Duration.ZERO; /** * Builds a new {@link QueueInputStream}. *

* This builder use the following aspects: *

*
    *
  • {@link #setBlockingQueue(BlockingQueue)}
  • *
  • timeout
  • *
* * @return a new instance. */ @Override public QueueInputStream get() { return new QueueInputStream(blockingQueue, timeout); } /** * Sets backing queue for the stream. * * @param blockingQueue backing queue for the stream. * @return this */ public Builder setBlockingQueue(final BlockingQueue blockingQueue) { this.blockingQueue = blockingQueue != null ? blockingQueue : new LinkedBlockingQueue<>(); return this; } /** * Sets the polling timeout. * * @param timeout the polling timeout. * @return this. */ public Builder setTimeout(final Duration timeout) { if (timeout != null && timeout.toNanos() < 0) { throw new IllegalArgumentException("timeout must not be negative"); } this.timeout = timeout != null ? timeout : Duration.ZERO; return this; } } /** * Constructs a new {@link Builder}. * * @return a new {@link Builder}. * @since 2.12.0 */ public static Builder builder() { return new Builder(); } private final BlockingQueue blockingQueue; private final long timeoutNanos; /** * Constructs a new instance with no limit to its internal queue size and zero timeout. */ public QueueInputStream() { this(new LinkedBlockingQueue<>()); } /** * Constructs a new instance with given queue and zero timeout. * * @param blockingQueue backing queue for the stream. * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}. */ @Deprecated public QueueInputStream(final BlockingQueue blockingQueue) { this(blockingQueue, Duration.ZERO); } /** * Constructs a new instance with given queue and timeout. * * @param blockingQueue backing queue for the stream. * @param timeout how long to wait before giving up when polling the queue. */ private QueueInputStream(final BlockingQueue blockingQueue, final Duration timeout) { this.blockingQueue = Objects.requireNonNull(blockingQueue, "blockingQueue"); this.timeoutNanos = Objects.requireNonNull(timeout, "timeout").toNanos(); } /** * Gets the blocking queue. * * @return the blocking queue. */ BlockingQueue getBlockingQueue() { return blockingQueue; } /** * Gets the timeout duration. * * @return the timeout duration. */ Duration getTimeout() { return Duration.ofNanos(timeoutNanos); } /** * Constructs 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 the byte read, or {@code -1} if a timeout occurs before a queue element is available. * @throws IllegalStateException if thread is interrupted while waiting. */ @Override public int read() { try { final Integer value = blockingQueue.poll(timeoutNanos, TimeUnit.NANOSECONDS); return value == null ? EOF : 0xFF & value; } catch (final InterruptedException e) { Thread.currentThread().interrupt(); // throw runtime unchecked exception to maintain signature backward-compatibility of // this read method, which does not declare IOException throw new IllegalStateException(e); } } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/RandomAccessFileInputStream.java0100644 0000000 0000000 00000017650 14603604450 033106 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.File; import java.io.IOException; import java.io.InputStream; import java.io.RandomAccessFile; import java.util.Objects; import org.apache.commons.io.RandomAccessFileMode; import org.apache.commons.io.build.AbstractOrigin; import org.apache.commons.io.build.AbstractStreamBuilder; /** * Streams data from a {@link RandomAccessFile} starting at its current position. *

* To build an instance, use {@link Builder}. *

* * @see Builder * @since 2.8.0 */ public class RandomAccessFileInputStream extends InputStream { // @formatter:off /** * Builds a new {@link RandomAccessFileInputStream}. * *

* For example: *

*
{@code
     * RandomAccessFileInputStream s = RandomAccessFileInputStream.builder()
     *   .setPath(path)
     *   .setCloseOnClose(true)
     *   .get();}
     * 
* * @see #get() * @since 2.12.0 */ // @formatter:on public static class Builder extends AbstractStreamBuilder { private RandomAccessFile randomAccessFile; private boolean closeOnClose; /** * Builds a new {@link RandomAccessFileInputStream}. *

* You must set input that supports {@link RandomAccessFile} or {@link File}, otherwise, this method throws an exception. Only set one of * RandomAccessFile or an origin that can be converted to a File. *

*

* This builder use the following aspects: *

*
    *
  • {@link RandomAccessFile}
  • *
  • {@link File}
  • *
  • closeOnClose
  • *
* * @return a new instance. * @throws IllegalStateException if the {@code origin} is {@code null}. * @throws IllegalStateException if both RandomAccessFile and origin are set. * @throws UnsupportedOperationException if the origin cannot be converted to a {@link File}. * @see AbstractOrigin#getFile() */ @SuppressWarnings("resource") // Caller closes depending on settings @Override public RandomAccessFileInputStream get() throws IOException { if (randomAccessFile != null) { if (getOrigin() != null) { throw new IllegalStateException(String.format("Only set one of RandomAccessFile (%s) or origin (%s)", randomAccessFile, getOrigin())); } return new RandomAccessFileInputStream(randomAccessFile, closeOnClose); } return new RandomAccessFileInputStream(RandomAccessFileMode.READ_ONLY.create(checkOrigin().getFile()), closeOnClose); } /** * Sets whether to close the underlying file when this stream is closed. * * @param closeOnClose Whether to close the underlying file when this stream is closed. * @return this */ public Builder setCloseOnClose(final boolean closeOnClose) { this.closeOnClose = closeOnClose; return this; } /** * Sets the RandomAccessFile to stream. * * @param randomAccessFile the RandomAccessFile to stream. * @return this */ public Builder setRandomAccessFile(final RandomAccessFile randomAccessFile) { this.randomAccessFile = randomAccessFile; return this; } } /** * Constructs a new {@link Builder}. * * @return a new {@link Builder}. * @since 2.12.0 */ public static Builder builder() { return new Builder(); } 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. * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated 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. * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated 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); } @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) { randomAccessFile.seek(newPos); } return randomAccessFile.getFilePointer() - filePointer; } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/ReadAheadInputStream.java0100644 0000000 0000000 00000046643 14603604450 031546 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.FilterInputStream; 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; import org.apache.commons.io.build.AbstractStreamBuilder; /** * 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. *

* To build an instance, use {@link Builder}. *

*

* This class was ported and adapted from Apache Spark commit 933dc6cb7b3de1d8ccaf73d124d6eb95b947ed19. *

* * @see Builder * @since 2.9.0 */ public class ReadAheadInputStream extends FilterInputStream { // @formatter:off /** * Builds a new {@link ReadAheadInputStream}. * *

* For example: *

*
{@code
     * ReadAheadInputStream s = ReadAheadInputStream.builder()
     *   .setPath(path)
     *   .setExecutorService(Executors.newSingleThreadExecutor(ReadAheadInputStream::newThread))
     *   .get();}
     * 
* * @see #get() * @since 2.12.0 */ // @formatter:on public static class Builder extends AbstractStreamBuilder { private ExecutorService executorService; /** * Builds a new {@link ReadAheadInputStream}. *

* You must set input that supports {@link #getInputStream()}, otherwise, this method throws an exception. *

*

* This builder use the following aspects: *

*
    *
  • {@link #getInputStream()}
  • *
  • {@link #getBufferSize()}
  • *
  • {@link ExecutorService}
  • *
* * @return a new instance. * @throws IllegalStateException if the {@code origin} is {@code null}. * @throws UnsupportedOperationException if the origin cannot be converted to an {@link InputStream}. * @throws IOException if an I/O error occurs. * @see #getInputStream() * @see #getBufferSize() */ @SuppressWarnings("resource") @Override public ReadAheadInputStream get() throws IOException { return new ReadAheadInputStream(getInputStream(), getBufferSize(), executorService != null ? executorService : newExecutorService(), executorService == null); } /** * Sets the executor service for the read-ahead thread. * * @param executorService the executor service for the read-ahead thread. * @return this */ public Builder setExecutorService(final ExecutorService executorService) { this.executorService = executorService; return this; } } private static final ThreadLocal BYTE_ARRAY_1 = ThreadLocal.withInitial(() -> new byte[1]); /** * Constructs a new {@link Builder}. * * @return a new {@link Builder}. * @since 2.12.0 */ public static Builder builder() { return new Builder(); } /** * Constructs a new daemon thread. * * @param r the thread's runnable. * @return a new daemon thread. */ private static Thread newDaemonThread(final Runnable r) { final Thread thread = new Thread(r, "commons-io-read-ahead"); thread.setDaemon(true); return thread; } /** * Constructs a new daemon executor service. * * @return a new daemon executor service. */ private static ExecutorService newExecutorService() { return Executors.newSingleThreadExecutor(ReadAheadInputStream::newDaemonThread); } 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(); private final ExecutorService executorService; private final boolean shutdownExecutorService; private final Condition asyncReadComplete = stateChangeLock.newCondition(); /** * Constructs an instance with the specified buffer size and read-ahead threshold * * @param inputStream The underlying input stream. * @param bufferSizeInBytes The buffer size. * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated public ReadAheadInputStream(final InputStream inputStream, final int bufferSizeInBytes) { this(inputStream, bufferSizeInBytes, newExecutorService(), true); } /** * Constructs 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. * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated public ReadAheadInputStream(final InputStream inputStream, final int bufferSizeInBytes, final ExecutorService executorService) { this(inputStream, bufferSizeInBytes, executorService, false); } /** * Constructs 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 shut down the given ExecutorService on close. */ private ReadAheadInputStream(final InputStream inputStream, final int bufferSizeInBytes, final ExecutorService executorService, final boolean shutdownExecutorService) { super(Objects.requireNonNull(inputStream, "inputStream")); if (bufferSizeInBytes <= 0) { throw new IllegalArgumentException("bufferSizeInBytes should be greater than 0, but the value is " + bufferSizeInBytes); } this.executorService = Objects.requireNonNull(executorService, "executorService"); 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) { super.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 { super.close(); } catch (final IOException ignored) { // TODO Rethrow as UncheckedIOException? } } } 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 = BYTE_ARRAY_1.get(); oneByteArray[0] = 0; return read(oneByteArray, 0, 1) == EOF ? EOF : 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 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. * * @throws IOException if an I/O error occurs. */ 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 = in.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(); final 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. * @throws IOException if an I/O error occurs. */ 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 = in.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 { try { isWaiting.set(false); } finally { stateChangeLock.unlock(); } } checkReadException(); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/ReaderInputStream.java0100644 0000000 0000000 00000042330 14603604450 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 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; import org.apache.commons.io.Charsets; import org.apache.commons.io.IOUtils; import org.apache.commons.io.build.AbstractStreamBuilder; import org.apache.commons.io.charset.CharsetEncoders; /** * {@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): *

*

* To build an instance, use {@link Builder}. *

*
 * InputStream inputStream = ...
 * Charset cs = ...
 * InputStreamReader reader = new InputStreamReader(inputStream, cs);
 * ReaderInputStream in2 = ReaderInputStream.builder()
 *   .setReader(reader)
 *   .setCharset(cs)
 *   .get();
 * 
*

* {@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. *

*

* The {@link #available()} method of this class always returns 0. The methods {@link #mark(int)} and {@link #reset()} are not supported. *

*

* Instances of {@link ReaderInputStream} are not thread safe. *

* * @see Builder * @see org.apache.commons.io.output.WriterOutputStream * @since 2.0 */ public class ReaderInputStream extends InputStream { // @formatter:off /** * Builds a new {@link ReaderInputStream}. * *

* For example: *

*
{@code
     * ReaderInputStream s = ReaderInputStream.builder()
     *   .setPath(path)
     *   .setCharsetEncoder(Charset.defaultCharset().newEncoder())
     *   .get();}
     * 
* * @see #get() * @since 2.12.0 */ // @formatter:on public static class Builder extends AbstractStreamBuilder { private CharsetEncoder charsetEncoder = newEncoder(getCharset()); /** * Builds a new {@link ReaderInputStream}. * *

* You must set input that supports {@link #getReader()}, otherwise, this method throws an exception. *

*

* This builder use the following aspects: *

*
    *
  • {@link #getReader()}
  • *
  • {@link #getBufferSize()}
  • *
  • {@link #getCharset()}
  • *
  • {@link CharsetEncoder}
  • *
* * @return a new instance. * @throws UnsupportedOperationException if the origin cannot provide a Reader. * @throws IllegalStateException if the {@code origin} is {@code null}. * @see #getReader() * @see CharsetEncoder * @see #getBufferSize() */ @SuppressWarnings("resource") @Override public ReaderInputStream get() throws IOException { return new ReaderInputStream(getReader(), charsetEncoder, getBufferSize()); } CharsetEncoder getCharsetEncoder() { return charsetEncoder; } @Override public Builder setCharset(final Charset charset) { super.setCharset(charset); charsetEncoder = newEncoder(getCharset()); return this; } /** * Sets the charset encoder. Assumes that the caller has configured the encoder. * * @param newEncoder the charset encoder, null resets to a default encoder. * @return this */ public Builder setCharsetEncoder(final CharsetEncoder newEncoder) { charsetEncoder = CharsetEncoders.toCharsetEncoder(newEncoder, () -> newEncoder(getCharsetDefault())); super.setCharset(charsetEncoder.charset()); return this; } } /** * Constructs a new {@link Builder}. * * @return a new {@link Builder}. * @since 2.12.0 */ public static Builder builder() { return new Builder(); } static int checkMinBufferSize(final CharsetEncoder charsetEncoder, final int bufferSize) { final float minRequired = minBufferSize(charsetEncoder); if (bufferSize < minRequired) { throw new IllegalArgumentException(String.format("Buffer size %,d must be at least %s for a CharsetEncoder %s.", bufferSize, minRequired, charsetEncoder.charset().displayName())); } return bufferSize; } static float minBufferSize(final CharsetEncoder charsetEncoder) { return charsetEncoder.maxBytesPerChar() * 2; } private static CharsetEncoder newEncoder(final Charset charset) { // @formatter:off return Charsets.toCharset(charset).newEncoder() .onMalformedInput(CodingErrorAction.REPLACE) .onUnmappableCharacter(CodingErrorAction.REPLACE); // @formatter:on } private final Reader reader; private final CharsetEncoder charsetEncoder; /** * 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; /** * Constructs a new {@link ReaderInputStream} that uses the default character encoding with a default input buffer size of * {@value IOUtils#DEFAULT_BUFFER_SIZE} characters. * * @param reader the target {@link Reader} * @deprecated Use {@link ReaderInputStream#builder()} instead */ @Deprecated public ReaderInputStream(final Reader reader) { this(reader, Charset.defaultCharset()); } /** * Constructs a new {@link ReaderInputStream} with a default input buffer size of {@value IOUtils#DEFAULT_BUFFER_SIZE} characters. * *

* The encoder created for the specified charset will use {@link CodingErrorAction#REPLACE} for malformed input and unmappable characters. *

* * @param reader the target {@link Reader} * @param charset the charset encoding * @deprecated Use {@link ReaderInputStream#builder()} instead, will be protected for subclasses. */ @Deprecated public ReaderInputStream(final Reader reader, final Charset charset) { this(reader, charset, IOUtils.DEFAULT_BUFFER_SIZE); } /** * Constructs a new {@link ReaderInputStream}. * *

* The encoder created for the specified charset will use {@link CodingErrorAction#REPLACE} for malformed input and unmappable characters. *

* * @param reader the target {@link Reader}. * @param charset the charset encoding. * @param bufferSize the size of the input buffer in number of characters. * @deprecated Use {@link ReaderInputStream#builder()} instead */ @Deprecated public ReaderInputStream(final Reader reader, final Charset charset, final int bufferSize) { // @formatter:off this(reader, Charsets.toCharset(charset).newEncoder() .onMalformedInput(CodingErrorAction.REPLACE) .onUnmappableCharacter(CodingErrorAction.REPLACE), bufferSize); // @formatter:on } /** * Constructs a new {@link ReaderInputStream}. * *

* This constructor does not call {@link CharsetEncoder#reset() reset} on the provided encoder. The caller of this constructor should do this when providing * an encoder which had already been in use. *

* * @param reader the target {@link Reader} * @param charsetEncoder the charset encoder * @since 2.1 * @deprecated Use {@link ReaderInputStream#builder()} instead */ @Deprecated public ReaderInputStream(final Reader reader, final CharsetEncoder charsetEncoder) { this(reader, charsetEncoder, IOUtils.DEFAULT_BUFFER_SIZE); } /** * Constructs a new {@link ReaderInputStream}. * *

* This constructor does not call {@link CharsetEncoder#reset() reset} on the provided encoder. The caller of this constructor should do this when providing * an encoder which had already been in use. *

* * @param reader the target {@link Reader} * @param charsetEncoder the charset encoder, null defaults to the default Charset encoder. * @param bufferSize the size of the input buffer in number of characters * @since 2.1 * @deprecated Use {@link ReaderInputStream#builder()} instead */ @Deprecated public ReaderInputStream(final Reader reader, final CharsetEncoder charsetEncoder, final int bufferSize) { this.reader = reader; this.charsetEncoder = CharsetEncoders.toCharsetEncoder(charsetEncoder); this.encoderIn = CharBuffer.allocate(checkMinBufferSize(this.charsetEncoder, bufferSize)); this.encoderIn.flip(); this.encoderOut = ByteBuffer.allocate(128); this.encoderOut.flip(); } /** * Constructs a new {@link ReaderInputStream} with a default input buffer size of {@value IOUtils#DEFAULT_BUFFER_SIZE} characters. * *

* The encoder created for the specified charset will use {@link CodingErrorAction#REPLACE} for malformed input and unmappable characters. *

* * @param reader the target {@link Reader} * @param charsetName the name of the charset encoding * @deprecated Use {@link ReaderInputStream#builder()} instead */ @Deprecated public ReaderInputStream(final Reader reader, final String charsetName) { this(reader, charsetName, IOUtils.DEFAULT_BUFFER_SIZE); } /** * Constructs a new {@link ReaderInputStream}. * *

* The encoder created for the specified charset will use {@link CodingErrorAction#REPLACE} for malformed input and unmappable characters. *

* * @param reader the target {@link Reader} * @param charsetName the name of the charset encoding, null maps to the default Charset. * @param bufferSize the size of the input buffer in number of characters * @deprecated Use {@link ReaderInputStream#builder()} instead */ @Deprecated public ReaderInputStream(final Reader reader, final String charsetName, final int bufferSize) { this(reader, Charsets.toCharset(charsetName), bufferSize); } /** * Closes 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(); } /** * Fills the internal char buffer from the reader. * * @throws IOException If an I/O error occurs */ private void fillBuffer() throws IOException { if (endOfInput) { return; } 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 = charsetEncoder.encode(encoderIn, encoderOut, endOfInput); if (endOfInput) { lastCoderResult = charsetEncoder.flush(encoderOut); } if (lastCoderResult.isError()) { lastCoderResult.throwException(); } encoderOut.flip(); } /** * Gets the CharsetEncoder. * * @return the CharsetEncoder. */ CharsetEncoder getCharsetEncoder() { return charsetEncoder; } /** * Reads 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; } } } /** * Reads 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); } /** * Reads 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()) { // Data from the last read not fully copied final int c = Math.min(encoderOut.remaining(), len); encoderOut.get(array, off, c); off += c; len -= c; read += c; } else if (endOfInput) { // Already reach EOF in the last read break; } else { // Read again fillBuffer(); } } return read == 0 && endOfInput ? EOF : read; } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/ReversedLinesFileReader.java0100644 0000000 0000000 00000050340 14603604450 032236 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.Arrays; import java.util.Collections; import java.util.List; import org.apache.commons.io.Charsets; import org.apache.commons.io.FileSystem; import org.apache.commons.io.StandardLineSeparator; import org.apache.commons.io.build.AbstractStreamBuilder; /** * Reads lines in a file reversely (similar to a BufferedReader, but starting at the last line). Useful for e.g. searching in log files. *

* To build an instance, use {@link Builder}. *

* * @see Builder * @since 2.2 */ public class ReversedLinesFileReader implements Closeable { // @formatter:off /** * Builds a new {@link ReversedLinesFileReader}. * *

* For example: *

*
{@code
     * ReversedLinesFileReader r = ReversedLinesFileReader.builder()
     *   .setPath(path)
     *   .setBufferSize(4096)
     *   .setCharset(StandardCharsets.UTF_8)
     *   .get();}
     * 
* * @see #get() * @since 2.12.0 */ // @formatter:on public static class Builder extends AbstractStreamBuilder { /** * Constructs a new {@link Builder}. */ public Builder() { setBufferSizeDefault(DEFAULT_BLOCK_SIZE); setBufferSize(DEFAULT_BLOCK_SIZE); } /** * Builds a new {@link ReversedLinesFileReader}. *

* You must set input that supports {@link #getInputStream()} on this builder, otherwise, this method throws an exception. *

*

* This builder use the following aspects: *

*
    *
  • {@link #getInputStream()}
  • *
  • {@link #getBufferSize()}
  • *
  • {@link #getCharset()}
  • *
* * @return a new instance. * @throws IllegalStateException if the {@code origin} is {@code null}. * @throws UnsupportedOperationException if the origin cannot be converted to a {@link Path}. * @throws IOException if an I/O error occurs. * @see #getPath() * @see #getBufferSize() * @see #getCharset() */ @Override public ReversedLinesFileReader get() throws IOException { return new ReversedLinesFileReader(getPath(), getBufferSize(), getCharset()); } } private final class FilePart { private final long no; private final byte[] data; private byte[] leftOver; private int currentLastBytePos; /** * Constructs a new instance. * * @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; } /** * Constructs the buffer containing any leftover bytes. */ private void createLeftOver() { final int lineLengthBytes = currentLastBytePos + 1; if (lineLengthBytes > 0) { // create left over for next block leftOver = Arrays.copyOf(data, 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() { //NOPMD Bug in PMD 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 = Arrays.copyOfRange(data, lineStart, lineStart + 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 = FileSystem.getCurrent().getBlockSize(); /** * Constructs a new {@link Builder}. * * @return a new {@link Builder}. * @since 2.12.0 */ public static Builder builder() { return new Builder(); } 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; /** * Constructs 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 Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated public ReversedLinesFileReader(final File file) throws IOException { this(file, DEFAULT_BLOCK_SIZE, Charset.defaultCharset()); } /** * Constructs 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 * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated public ReversedLinesFileReader(final File file, final Charset charset) throws IOException { this(file.toPath(), charset); } /** * Constructs 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 * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated public ReversedLinesFileReader(final File file, final int blockSize, final Charset charset) throws IOException { this(file.toPath(), blockSize, charset); } /** * Constructs 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 if the encoding is not supported * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated public ReversedLinesFileReader(final File file, final int blockSize, final String charsetName) throws IOException { this(file.toPath(), blockSize, charsetName); } /** * Constructs 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 * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated public ReversedLinesFileReader(final Path file, final Charset charset) throws IOException { this(file, DEFAULT_BLOCK_SIZE, charset); } /** * Constructs 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 * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated 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 || this.charset == StandardCharsets.UTF_8) { // all one byte encodings are no problem 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); } /** * Constructs 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 if the encoding is not supported * @since 2.7 * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated 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.16.1-src/src/main/java/org/apache/commons/io/input/SequenceReader.java0100644 0000000 0000000 00000007462 14603604450 030443 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.SequenceInputStream; import java.util.Arrays; import java.util.Iterator; import java.util.Objects; import org.apache.commons.io.function.Uncheck; /** * Provides the contents of multiple {@link Reader}s in sequence. *

* Like {@link SequenceInputStream} but for {@link Reader} arguments. *

* * @since 2.7 */ public class SequenceReader extends Reader { private Reader reader; private final Iterator readers; /** * Constructs 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 = Uncheck.get(this::nextReader); } /** * Constructs 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 { do { // NOPMD // empty } while (nextReader() != null); } /** * Returns the next available reader or null if done. * * @return the next available reader or null. * @throws IOException IOException If an I/O error occurs. */ private Reader nextReader() throws IOException { if (reader != null) { reader.close(); } if (readers.hasNext()) { reader = readers.next(); } else { reader = null; } return reader; } /* * (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; } 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) { nextReader(); } else { count += readLen; off += readLen; len -= readLen; if (len <= 0) { break; } } } if (count > 0) { return count; } return EOF; } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/SwappedDataInputStream.java0100644 0000000 0000000 00000017150 14603604450 032134 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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. *

* Provenance: 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 2 byte, unsigned, little endian UTF-16 code point. * * @return the UTF-16 code point 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(); } /** * Reads an 8 byte, two's complement, little-endian long. * * @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); } /** * Reads a 4 byte, IEEE 754, little-endian float. * * @return the read float * @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; } } /** * Reads a 4 byte, two's complement little-endian integer. * * @return the read int * @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 * @throws UnsupportedOperationException always */ @Override public String readLine() throws IOException, EOFException { throw UnsupportedOperationExceptions.method("readLine"); } /** * Reads an 8 byte, two's complement little-endian integer. * * @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); } /** * Reads a 2 byte, two's complement, little-endian integer. * * @return the read short * @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(); } /** * Reads a 2 byte, unsigned, little-endian integer. * * @return the read short * @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 never * @throws EOFException if an end of file is reached unexpectedly * @throws IOException if an I/O error occurs * @throws UnsupportedOperationException always */ @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 skipped or -1 if the end of stream * @throws IOException if an I/O error occurs */ @Override public int skipBytes(final int count) throws IOException { return (int) in.skip(count); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/TaggedInputStream.java0100644 0000000 0000000 00000010164 14603604450 031130 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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
 * }
 * 
*

Deprecating Serialization

*

* Serialization is deprecated and will be removed in 3.0. *

* * @see TaggedIOException * @since 2.0 */ public class TaggedInputStream extends ProxyInputStream { /** * The unique tag associated with exceptions from stream. */ private final Serializable tag = UUID.randomUUID(); /** * Constructs a tagging decorator for the given input stream. * * @param proxy input stream to be decorated */ public TaggedInputStream(final InputStream proxy) { super(proxy); } /** * 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); } /** * 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); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/TaggedReader.java0100644 0000000 0000000 00000010024 14603604450 030052 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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
 * }
 * 
*

Deprecating Serialization

*

* Serialization is deprecated and will be removed in 3.0. *

* * @see TaggedIOException * @since 2.7 */ public class TaggedReader extends ProxyReader { /** * The unique tag associated with exceptions from reader. */ private final Serializable tag = UUID.randomUUID(); /** * Constructs a tagging decorator for the given reader. * * @param proxy reader to be decorated */ public TaggedReader(final Reader proxy) { super(proxy); } /** * 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); } /** * 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); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/Tailer.java0100644 0000000 0000000 00000112012 14603604450 026754 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.Closeable; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.LinkOption; import java.nio.file.Path; import java.nio.file.attribute.FileTime; import java.time.Duration; import java.util.Arrays; import java.util.Objects; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import org.apache.commons.io.IOUtils; import org.apache.commons.io.ThreadUtils; import org.apache.commons.io.build.AbstractOrigin; import org.apache.commons.io.build.AbstractStreamBuilder; import org.apache.commons.io.file.PathUtils; import org.apache.commons.io.file.attribute.FileTimes; /** * Simple implementation of the UNIX "tail -f" functionality. *

* To build an instance, use {@link Builder}. *

*

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 a {@link Builder}
  • *
  • Using an {@link java.util.concurrent.Executor}
  • *
  • Using a {@link Thread}
  • *
*

* An example of each is shown below. *

*

2.1 Using a Builder

*
 * TailerListener listener = new MyTailerListener();
 * Tailer tailer = Tailer.builder()
 *   .setFile(file)
 *   .setTailerListener(listener)
 *   .setDelayDuration(delay)
 *   .get();
 * 
*

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 Builder * @see TailerListener * @see TailerListenerAdapter * @since 2.0 * @since 2.5 Updated behavior and documentation for {@link Thread#interrupt()}. * @since 2.12.0 Add {@link Tailable} and {@link RandomAccessResourceBridge} interfaces to tail of files accessed using * alternative libraries such as jCIFS or Apache Commons * VFS. */ public class Tailer implements Runnable, AutoCloseable { // @formatter:off /** * Builds a new {@link Tailer}. * *

* For example: *

*
{@code
     * Tailer t = Tailer.builder()
     *   .setPath(path)
     *   .setCharset(StandardCharsets.UTF_8)
     *   .setDelayDuration(Duration.ofSeconds(1))
     *   .setExecutorService(Executors.newSingleThreadExecutor(Builder::newDaemonThread))
     *   .setReOpen(false)
     *   .setStartThread(true)
     *   .setTailable(tailable)
     *   .setTailerListener(tailerListener)
     *   .setTailFromEnd(false)
     *   .get();}
     * 
* * @see #get() * @since 2.12.0 */ // @formatter:on public static class Builder extends AbstractStreamBuilder { private static final Duration DEFAULT_DELAY_DURATION = Duration.ofMillis(DEFAULT_DELAY_MILLIS); /** * Creates a new daemon thread. * * @param runnable the thread's runnable. * @return a new daemon thread. */ private static Thread newDaemonThread(final Runnable runnable) { final Thread thread = new Thread(runnable, "commons-io-tailer"); thread.setDaemon(true); return thread; } private Tailable tailable; private TailerListener tailerListener; private Duration delayDuration = DEFAULT_DELAY_DURATION; private boolean tailFromEnd; private boolean reOpen; private boolean startThread = true; private ExecutorService executorService = Executors.newSingleThreadExecutor(Builder::newDaemonThread); /** * Builds a new {@link Tailer}. * *

* This builder use the following aspects: *

*
    *
  • {@link #getBufferSize()}
  • *
  • {@link #getCharset()}
  • *
  • {@link Tailable}
  • *
  • {@link TailerListener}
  • *
  • delayDuration
  • *
  • tailFromEnd
  • *
  • reOpen
  • *
* * @return a new instance. */ @Override public Tailer get() { final Tailer tailer = new Tailer(tailable, getCharset(), tailerListener, delayDuration, tailFromEnd, reOpen, getBufferSize()); if (startThread) { executorService.submit(tailer); } return tailer; } /** * Sets the delay duration. null resets to the default delay of one second. * * @param delayDuration the delay between checks of the file for new content. * @return this */ public Builder setDelayDuration(final Duration delayDuration) { this.delayDuration = delayDuration != null ? delayDuration : DEFAULT_DELAY_DURATION; return this; } /** * Sets the executor service to use when startThread is true. * * @param executorService the executor service to use when startThread is true. * @return this */ public Builder setExecutorService(final ExecutorService executorService) { this.executorService = Objects.requireNonNull(executorService, "executorService"); return this; } /** * Sets the origin. * * @throws UnsupportedOperationException if the origin cannot be converted to a Path. */ @Override protected Builder setOrigin(final AbstractOrigin origin) { setTailable(new TailablePath(origin.getPath())); return super.setOrigin(origin); } /** * Sets the re-open behavior. * * @param reOpen whether to close/reopen the file between chunks * @return this */ public Builder setReOpen(final boolean reOpen) { this.reOpen = reOpen; return this; } /** * Sets the daemon thread startup behavior. * * @param startThread whether to create a daemon thread automatically. * @return this */ public Builder setStartThread(final boolean startThread) { this.startThread = startThread; return this; } /** * Sets the tailable. * * @param tailable the tailable. * @return this. */ public Builder setTailable(final Tailable tailable) { this.tailable = Objects.requireNonNull(tailable, "tailable"); return this; } /** * Sets the listener. * * @param tailerListener the listener. * @return this */ public Builder setTailerListener(final TailerListener tailerListener) { this.tailerListener = Objects.requireNonNull(tailerListener, "tailerListener"); return this; } /** * Sets the tail start behavior. * * @param end Set to true to tail from the end of the file, false to tail from the beginning of the file. * @return this */ public Builder setTailFromEnd(final boolean end) { this.tailFromEnd = end; return this; } } /** * Bridges random access to a {@link RandomAccessFile}. */ private static final class RandomAccessFileBridge implements RandomAccessResourceBridge { private final RandomAccessFile randomAccessFile; private RandomAccessFileBridge(final File file, final String mode) throws FileNotFoundException { randomAccessFile = new RandomAccessFile(file, mode); } @Override public void close() throws IOException { randomAccessFile.close(); } @Override public long getPointer() throws IOException { return randomAccessFile.getFilePointer(); } @Override public int read(final byte[] b) throws IOException { return randomAccessFile.read(b); } @Override public void seek(final long position) throws IOException { randomAccessFile.seek(position); } } /** * Bridges access to a resource for random access, normally a file. Allows substitution of remote files for example * using jCIFS. * * @since 2.12.0 */ public interface RandomAccessResourceBridge extends Closeable { /** * Gets the current offset in this tailable. * * @return the offset from the beginning of the tailable, in bytes, at which the next read or write occurs. * @throws IOException if an I/O error occurs. */ long getPointer() throws IOException; /** * Reads up to {@code b.length} bytes of data from this tailable into an array of bytes. This method blocks until at * least one byte of input is available. * * @param b the buffer into which the data is read. * @return the total number of bytes read into the buffer, or {@code -1} if there is no more data because the end of * this tailable has been reached. * @throws IOException If the first byte cannot be read for any reason other than end of tailable, or if the random * access tailable has been closed, or if some other I/O error occurs. */ int read(final byte[] b) throws IOException; /** * Sets the file-pointer offset, measured from the beginning of this tailable, at which the next read or write occurs. * The offset may be set beyond the end of the tailable. Setting the offset beyond the end of the tailable does not * change the tailable length. The tailable length will change only by writing after the offset has been set beyond the * end of the tailable. * * @param pos the offset position, measured in bytes from the beginning of the tailable, at which to set the tailable * pointer. * @throws IOException if {@code pos} is less than {@code 0} or if an I/O error occurs. */ void seek(final long pos) throws IOException; } /** * A tailable resource like a file. * * @since 2.12.0 */ public interface Tailable { /** * Creates a random access file stream to read. * * @param mode the access mode, by default this is for {@link RandomAccessFile}. * @return a random access file stream to read. * @throws FileNotFoundException if the tailable object does not exist. */ RandomAccessResourceBridge getRandomAccess(final String mode) throws FileNotFoundException; /** * Tests if this tailable is newer than the specified {@link FileTime}. * * @param fileTime the file time reference. * @return true if the {@link File} exists and has been modified after the given {@link FileTime}. * @throws IOException if an I/O error occurs. */ boolean isNewer(final FileTime fileTime) throws IOException; /** * Gets the last modification {@link FileTime}. * * @return See {@link java.nio.file.Files#getLastModifiedTime(Path, LinkOption...)}. * @throws IOException if an I/O error occurs. */ FileTime lastModifiedFileTime() throws IOException; /** * Gets the size of this tailable. * * @return The size, in bytes, of this tailable, or {@code 0} if the file does not exist. Some operating systems may * return {@code 0} for path names denoting system-dependent entities such as devices or pipes. * @throws IOException if an I/O error occurs. */ long size() throws IOException; } /** * A tailable for a file {@link Path}. */ private static final class TailablePath implements Tailable { private final Path path; private final LinkOption[] linkOptions; private TailablePath(final Path path, final LinkOption... linkOptions) { this.path = Objects.requireNonNull(path, "path"); this.linkOptions = linkOptions; } Path getPath() { return path; } @Override public RandomAccessResourceBridge getRandomAccess(final String mode) throws FileNotFoundException { return new RandomAccessFileBridge(path.toFile(), mode); } @Override public boolean isNewer(final FileTime fileTime) throws IOException { return PathUtils.isNewer(path, fileTime, linkOptions); } @Override public FileTime lastModifiedFileTime() throws IOException { return Files.getLastModifiedTime(path, linkOptions); } @Override public long size() throws IOException { return Files.size(path); } @Override public String toString() { return "TailablePath [file=" + path + ", linkOptions=" + Arrays.toString(linkOptions) + "]"; } } private static final int DEFAULT_DELAY_MILLIS = 1000; private static final String RAF_READ_ONLY_MODE = "r"; // The default charset used for reading files private static final Charset DEFAULT_CHARSET = Charset.defaultCharset(); /** * Constructs a new {@link Builder}. * * @return Creates a new {@link Builder}. * @since 2.12.0 */ public static Builder builder() { return new Builder(); } /** * 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 bufferSize buffer size. * @return The new tailer. * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}. */ @Deprecated public static Tailer create(final File file, final Charset charset, final TailerListener listener, final long delayMillis, final boolean end, final boolean reOpen, final int bufferSize) { //@formatter:off return builder() .setFile(file) .setTailerListener(listener) .setCharset(charset) .setDelayDuration(Duration.ofMillis(delayMillis)) .setTailFromEnd(end) .setReOpen(reOpen) .setBufferSize(bufferSize) .get(); //@formatter:on } /** * 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. * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}. */ @Deprecated public static Tailer create(final File file, final TailerListener listener) { //@formatter:off return builder() .setFile(file) .setTailerListener(listener) .get(); //@formatter:on } /** * 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. * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}. */ @Deprecated public static Tailer create(final File file, final TailerListener listener, final long delayMillis) { //@formatter:off return builder() .setFile(file) .setTailerListener(listener) .setDelayDuration(Duration.ofMillis(delayMillis)) .get(); //@formatter:on } /** * 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. * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}. */ @Deprecated public static Tailer create(final File file, final TailerListener listener, final long delayMillis, final boolean end) { //@formatter:off return builder() .setFile(file) .setTailerListener(listener) .setDelayDuration(Duration.ofMillis(delayMillis)) .setTailFromEnd(end) .get(); //@formatter:on } /** * 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. * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}. */ @Deprecated public static Tailer create(final File file, final TailerListener listener, final long delayMillis, final boolean end, final boolean reOpen) { //@formatter:off return builder() .setFile(file) .setTailerListener(listener) .setDelayDuration(Duration.ofMillis(delayMillis)) .setTailFromEnd(end) .setReOpen(reOpen) .get(); //@formatter:on } /** * 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 bufferSize buffer size. * @return The new tailer. * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}. */ @Deprecated public static Tailer create(final File file, final TailerListener listener, final long delayMillis, final boolean end, final boolean reOpen, final int bufferSize) { //@formatter:off return builder() .setFile(file) .setTailerListener(listener) .setDelayDuration(Duration.ofMillis(delayMillis)) .setTailFromEnd(end) .setReOpen(reOpen) .setBufferSize(bufferSize) .get(); //@formatter:on } /** * 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 bufferSize buffer size. * @return The new tailer. * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}. */ @Deprecated public static Tailer create(final File file, final TailerListener listener, final long delayMillis, final boolean end, final int bufferSize) { //@formatter:off return builder() .setFile(file) .setTailerListener(listener) .setDelayDuration(Duration.ofMillis(delayMillis)) .setTailFromEnd(end) .setBufferSize(bufferSize) .get(); //@formatter:on } /** * Buffer on top of RandomAccessResourceBridge. */ private final byte[] inbuf; /** * The file which will be tailed. */ private final Tailable tailable; /** * 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 Duration delayDuration; /** * Whether to tail from the end or start of file */ private final boolean tailAtEnd; /** * 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, 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 * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}. */ @Deprecated public Tailer(final File file, final Charset charset, final TailerListener listener, final long delayMillis, final boolean end, final boolean reOpen, final int bufSize) { this(new TailablePath(file.toPath()), charset, listener, Duration.ofMillis(delayMillis), end, reOpen, bufSize); } /** * 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. * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}. */ @Deprecated 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. * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}. */ @Deprecated 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. * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}. */ @Deprecated 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 * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}. */ @Deprecated 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 reOpen if true, close and reopen the file between reading chunks * @param bufferSize Buffer size * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}. */ @Deprecated public Tailer(final File file, final TailerListener listener, final long delayMillis, final boolean end, final boolean reOpen, final int bufferSize) { this(file, DEFAULT_CHARSET, listener, delayMillis, end, reOpen, bufferSize); } /** * 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 bufferSize Buffer size * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}. */ @Deprecated public Tailer(final File file, final TailerListener listener, final long delayMillis, final boolean end, final int bufferSize) { this(file, listener, delayMillis, end, false, bufferSize); } /** * Creates a Tailer for the given file, with a specified buffer size. * * @param tailable the file to follow. * @param charset the Charset to be used for reading the file * @param listener the TailerListener to use. * @param delayDuration 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 bufferSize Buffer size */ private Tailer(final Tailable tailable, final Charset charset, final TailerListener listener, final Duration delayDuration, final boolean end, final boolean reOpen, final int bufferSize) { this.tailable = Objects.requireNonNull(tailable, "tailable"); this.listener = Objects.requireNonNull(listener, "listener"); this.delayDuration = delayDuration; this.tailAtEnd = end; this.inbuf = IOUtils.byteArray(bufferSize); // Save and prepare the listener listener.init(this); this.reOpen = reOpen; this.charset = charset; } /** * Requests the tailer to complete its current loop and return. */ @Override public void close() { this.run = false; } /** * Gets the delay in milliseconds. * * @return the delay in milliseconds. * @deprecated Use {@link #getDelayDuration()}. */ @Deprecated public long getDelay() { return delayDuration.toMillis(); } /** * Gets the delay Duration. * * @return the delay Duration. * @since 2.12.0 */ public Duration getDelayDuration() { return delayDuration; } /** * Gets the file. * * @return the file * @throws IllegalStateException if constructed using a user provided {@link Tailable} implementation */ public File getFile() { if (tailable instanceof TailablePath) { return ((TailablePath) tailable).getPath().toFile(); } throw new IllegalStateException("Cannot extract java.io.File from " + tailable.getClass().getName()); } /** * Gets whether to keep on running. * * @return whether to keep on running. * @since 2.5 */ protected boolean getRun() { return run; } /** * Gets the Tailable. * * @return the Tailable * @since 2.12.0 */ public Tailable getTailable() { return tailable; } /** * Reads new lines. * * @param reader The file to read * @return The new position after the lines have been read * @throws IOException if an I/O error occurs. */ private long readLines(final RandomAccessResourceBridge reader) throws IOException { try (ByteArrayOutputStream lineBuf = new ByteArrayOutputStream(64)) { long pos = reader.getPointer(); 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.getPointer(); } reader.seek(rePos); // Ensure we can re-read if necessary if (listener instanceof TailerListenerAdapter) { ((TailerListenerAdapter) listener).endOfFileReached(); } return rePos; } } /** * Follows changes in the file, calling {@link TailerListener#handle(String)} with each new line. */ @Override public void run() { RandomAccessResourceBridge reader = null; try { FileTime last = FileTimes.EPOCH; // 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 = tailable.getRandomAccess(RAF_READ_ONLY_MODE); } catch (final FileNotFoundException e) { listener.fileNotFound(); } if (reader == null) { ThreadUtils.sleep(delayDuration); } else { // The current position in the file position = tailAtEnd ? tailable.size() : 0; last = tailable.lastModifiedFileTime(); reader.seek(position); } } while (getRun()) { final boolean newer = tailable.isNewer(last); // IO-279, must be done first // Check the file length to see if it was rotated final long length = tailable.size(); 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 (RandomAccessResourceBridge save = reader) { reader = tailable.getRandomAccess(RAF_READ_ONLY_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(); ThreadUtils.sleep(delayDuration); } 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 = tailable.lastModifiedFileTime(); } 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 = tailable.lastModifiedFileTime(); } if (reOpen && reader != null) { reader.close(); } ThreadUtils.sleep(delayDuration); if (getRun() && reOpen) { reader = tailable.getRandomAccess(RAF_READ_ONLY_MODE); reader.seek(position); } } } catch (final InterruptedException e) { Thread.currentThread().interrupt(); listener.handle(e); } catch (final Exception e) { listener.handle(e); } finally { try { IOUtils.close(reader); } catch (final IOException e) { listener.handle(e); } close(); } } /** * Requests the tailer to complete its current loop and return. * * @deprecated Use {@link #close()}. */ @Deprecated public void stop() { close(); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/TailerListener.java0100644 0000000 0000000 00000003764 14603604450 030477 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 { /** * 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 an Exception. *

* Note: this is called from the tailer thread. *

* @param ex the exception. */ void handle(Exception ex); /** * Handles a line from a Tailer. *

* Note: this is called from the tailer thread. *

* @param line the line. */ void handle(String line); /** * 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); } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/TailerListenerAdapter.java0100644 0000000 0000000 00000004505 14603604450 031772 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 { /** * 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 } /** * 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 an Exception . * @param ex the exception. */ @Override public void handle(final Exception ex) { // noop } /** * Handles a line from a Tailer. * @param line the line. */ @Override public void handle(final String line) { // noop } /** * 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 } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/TeeInputStream.java0100644 0000000 0000000 00000012225 14603604450 030452 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; /** * Constructs 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); } /** * Constructs 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 * @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; } /** * 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; } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/TeeReader.java0100644 0000000 0000000 00000013717 14603604450 027410 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; /** * Constructs 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); } /** * Constructs 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.16.1-src/src/main/java/org/apache/commons/io/input/ThrottledInputStream.java0100644 0000000 0000000 00000015654 14603604450 031717 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.InterruptedIOException; import java.time.Duration; import java.time.temporal.ChronoUnit; import java.util.concurrent.TimeUnit; import org.apache.commons.io.build.AbstractStreamBuilder; /** * Provides bandwidth throttling on a specified InputStream. It is implemented as a wrapper on top of another InputStream instance. The throttling works by * examining the number of bytes read from the underlying InputStream from the beginning, and sleep()ing for a time interval if the byte-transfer is found * exceed the specified tolerable maximum. (Thus, while the read-rate might exceed the maximum for a short interval, the average tends towards the * specified maximum, overall.) *

* To build an instance, see {@link Builder} *

*

* Inspired by Apache HBase's class of the same name. *

* * @see Builder * @since 2.16.0 */ public final class ThrottledInputStream extends CountingInputStream { // @formatter:off /** * Builds a new {@link ThrottledInputStream}. * *

Using NIO

*
{@code
     * ThrottledInputStream in = ThrottledInputStream.builder()
     *   .setPath(Paths.get("MyFile.xml"))
     *   .setMaxBytesPerSecond(100_000)
     *   .get();
     * }
     * 
*

Using IO

*
{@code
     * ThrottledInputStream in = ThrottledInputStream.builder()
     *   .setFile(new File("MyFile.xml"))
     *   .setMaxBytesPerSecond(100_000)
     *   .get();
     * }
     * 
*
{@code
     * ThrottledInputStream in = ThrottledInputStream.builder()
     *   .setInputStream(inputStream)
     *   .setMaxBytesPerSecond(100_000)
     *   .get();
     * }
     * 
* * @see #get() */ // @formatter:on public static class Builder extends AbstractStreamBuilder { /** * Effectively not throttled. */ private long maxBytesPerSecond = Long.MAX_VALUE; /** * Builds a new {@link ThrottledInputStream}. *

* You must set input that supports {@link #getInputStream()}, otherwise, this method throws an exception. *

*

* This builder use the following aspects: *

*
    *
  • {@link #getInputStream()}
  • *
  • maxBytesPerSecond
  • *
* * @return a new instance. * @throws IllegalStateException if the {@code origin} is {@code null}. * @throws UnsupportedOperationException if the origin cannot be converted to an {@link InputStream}. * @throws IOException if an I/O error occurs. * @see #getInputStream() */ @SuppressWarnings("resource") @Override public ThrottledInputStream get() throws IOException { return new ThrottledInputStream(getInputStream(), maxBytesPerSecond); } /** * Sets the maximum bytes per second. * * @param maxBytesPerSecond the maximum bytes per second. */ public void setMaxBytesPerSecond(final long maxBytesPerSecond) { this.maxBytesPerSecond = maxBytesPerSecond; } } /** * Constructs a new {@link Builder}. * * @return a new {@link Builder}. */ public static Builder builder() { return new Builder(); } static long toSleepMillis(final long bytesRead, final long maxBytesPerSec, final long elapsedMillis) { assert elapsedMillis >= 0 : "The elapsed time should be greater or equal to zero"; if (bytesRead <= 0 || maxBytesPerSec <= 0 || elapsedMillis == 0) { return 0; } // We use this class to load the single source file, so the bytesRead // and maxBytesPerSec aren't greater than Double.MAX_VALUE. // We can get the precise sleep time by using the double value. final long millis = (long) ((double) bytesRead / (double) maxBytesPerSec * 1000 - elapsedMillis); if (millis <= 0) { return 0; } return millis; } private final long maxBytesPerSecond; private final long startTime = System.currentTimeMillis(); private Duration totalSleepDuration = Duration.ZERO; private ThrottledInputStream(final InputStream proxy, final long maxBytesPerSecond) { super(proxy); assert maxBytesPerSecond > 0 : "Bandwidth " + maxBytesPerSecond + " is invalid."; this.maxBytesPerSecond = maxBytesPerSecond; } @Override protected void beforeRead(final int n) throws IOException { throttle(); } /** * Gets the read-rate from this stream, since creation. Calculated as bytesRead/elapsedTimeSinceStart. * * @return Read rate, in bytes/sec. */ private long getBytesPerSecond() { final long elapsedSeconds = (System.currentTimeMillis() - startTime) / 1000; if (elapsedSeconds == 0) { return getByteCount(); } return getByteCount() / elapsedSeconds; } private long getSleepMillis() { return toSleepMillis(getByteCount(), maxBytesPerSecond, System.currentTimeMillis() - startTime); } /** * Gets the total duration spent in sleep. * * @return Duration spent in sleep. */ Duration getTotalSleepDuration() { return totalSleepDuration; } private void throttle() throws InterruptedIOException { final long sleepMillis = getSleepMillis(); if (sleepMillis > 0) { totalSleepDuration = totalSleepDuration.plus(sleepMillis, ChronoUnit.MILLIS); try { TimeUnit.MILLISECONDS.sleep(sleepMillis); } catch (final InterruptedException e) { throw new InterruptedIOException("Thread aborted"); } } } /** {@inheritDoc} */ @Override public String toString() { return "ThrottledInputStream[bytesRead=" + getByteCount() + ", maxBytesPerSec=" + maxBytesPerSecond + ", bytesPerSec=" + getBytesPerSecond() + ", totalSleepDuration=" + totalSleepDuration + ']'; } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/TimestampedObserver.java0100644 0000000 0000000 00000006001 14603604450 031520 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 timestampedObserver = new TimestampedObserver();
 * try (ObservableInputStream inputStream = new ObservableInputStream(...),
 *     timestampedObserver)) {
 *     ...
 * }
 * System.out.printf("IO duration: %s%n", timestampedObserver.getOpenToCloseDuration());
 * 
* * @since 2.9.0 */ public class TimestampedObserver extends Observer { private volatile Instant closeInstant; private final Instant openInstant = Instant.now(); /** * Constructs a new instance. */ public TimestampedObserver() { // empty } @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 instant for when this instance was created. * * @return the instant for when this instance was created. */ public Instant getOpenInstant() { return openInstant; } /** * 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()); } /** * Tests whether {@link #closed()} has been called. * * @return whether {@link #closed()} has been called. * @since 2.12.0 */ public boolean isClosed() { return closeInstant != null; } @Override public String toString() { return "TimestampedObserver [openInstant=" + openInstant + ", closeInstant=" + closeInstant + "]"; } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/UncheckedBufferedReader.java0100644 0000000 0000000 00000014136 14603604450 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.input; import java.io.BufferedReader; import java.io.IOException; import java.io.Reader; import java.io.UncheckedIOException; import java.nio.CharBuffer; import org.apache.commons.io.build.AbstractStreamBuilder; import org.apache.commons.io.function.Uncheck; /** * A {@link BufferedReader} that throws {@link UncheckedIOException} instead of {@link IOException}. *

* To build an instance, use {@link Builder}. *

* * @see Builder * @see BufferedReader * @see IOException * @see UncheckedIOException * @since 2.12.0 */ public final class UncheckedBufferedReader extends BufferedReader { // @formatter:off /** * Builds a new {@link UncheckedBufferedReader}. * *

* Using File IO: *

*
{@code
     * UncheckedBufferedReader s = UncheckedBufferedReader.builder()
     *   .setFile(file)
     *   .setBufferSize(8192)
     *   .setCharset(Charset.defaultCharset())
     *   .get();}
     * 
*

* Using NIO Path: *

*
{@code
     * UncheckedBufferedReader s = UncheckedBufferedReader.builder()
     *   .setPath(path)
     *   .setBufferSize(8192)
     *   .setCharset(Charset.defaultCharset())
     *   .get();}
     * 
* * @see #get() */ // @formatter:on public static class Builder extends AbstractStreamBuilder { /** * Builds a new {@link UncheckedBufferedReader}. * *

* You must set input that supports {@link #getReader()} on this builder, otherwise, this method throws an exception. *

*

* This builder use the following aspects: *

*
    *
  • {@link #getReader()}
  • *
  • {@link #getBufferSize()}
  • *
* * @return a new instance. * @throws UnsupportedOperationException if the origin cannot provide a Reader. * @throws IllegalStateException if the {@code origin} is {@code null}. * @see #getReader() * @see #getBufferSize() */ @Override public UncheckedBufferedReader get() { // This an unchecked class, so this method is as well. return Uncheck.get(() -> new UncheckedBufferedReader(getReader(), getBufferSize())); } } /** * Constructs a new {@link Builder}. * * @return a new {@link Builder}. */ public static Builder builder() { return new Builder(); } /** * Constructs a buffering character-input stream that uses an input buffer of the specified size. * * @param reader A Reader * @param bufferSize Input-buffer size * * @throws IllegalArgumentException If {@code bufferSize <= 0} */ private UncheckedBufferedReader(final Reader reader, final int bufferSize) { super(reader, bufferSize); } /** * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}. */ @Override public void close() throws UncheckedIOException { Uncheck.run(super::close); } /** * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}. */ @Override public void mark(final int readAheadLimit) throws UncheckedIOException { Uncheck.accept(super::mark, readAheadLimit); } /** * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}. */ @Override public int read() throws UncheckedIOException { return Uncheck.get(super::read); } /** * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}. */ @Override public int read(final char[] cbuf) throws UncheckedIOException { return Uncheck.apply(super::read, cbuf); } /** * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}. */ @Override public int read(final char[] cbuf, final int off, final int len) throws UncheckedIOException { return Uncheck.apply(super::read, cbuf, off, len); } /** * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}. */ @Override public int read(final CharBuffer target) throws UncheckedIOException { return Uncheck.apply(super::read, target); } /** * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}. */ @Override public String readLine() throws UncheckedIOException { return Uncheck.get(super::readLine); } /** * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}. */ @Override public boolean ready() throws UncheckedIOException { return Uncheck.get(super::ready); } /** * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}. */ @Override public void reset() throws UncheckedIOException { Uncheck.run(super::reset); } /** * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}. */ @Override public long skip(final long n) throws UncheckedIOException { return Uncheck.apply(super::skip, n); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/UncheckedFilterInputStream.java0100644 0000000 0000000 00000012043 14603604450 032772 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.BufferedReader; import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; import java.io.UncheckedIOException; import org.apache.commons.io.build.AbstractStreamBuilder; import org.apache.commons.io.function.Uncheck; /** * A {@link BufferedReader} that throws {@link UncheckedIOException} instead of {@link IOException}. *

* To build an instance, use {@link Builder}. *

* * @see Builder * @see BufferedReader * @see IOException * @see UncheckedIOException * @since 2.12.0 */ public final class UncheckedFilterInputStream extends FilterInputStream { // @formatter:off /** * Builds a new {@link UncheckedFilterInputStream}. * *

* Using File IO: *

*
{@code
     * UncheckedFilterInputStream s = UncheckedFilterInputStream.builder()
     *   .setFile(file)
     *   .get();}
     * 
*

* Using NIO Path: *

*
{@code
     * UncheckedFilterInputStream s = UncheckedFilterInputStream.builder()
     *   .setPath(path)
     *   .get();}
     * 
* * @see #get() */ // @formatter:on public static class Builder extends AbstractStreamBuilder { /** * Builds a new {@link UncheckedFilterInputStream}. *

* You must set input that supports {@link #getInputStream()} on this builder, otherwise, this method throws an exception. *

*

* This builder use the following aspects: *

*
    *
  • {@link #getInputStream()}
  • *
* * @return a new instance. * @throws UnsupportedOperationException if the origin cannot provide an InputStream. * @see #getInputStream() */ @Override public UncheckedFilterInputStream get() { // This an unchecked class, so this method is as well. return Uncheck.get(() -> new UncheckedFilterInputStream(getInputStream())); } } /** * Constructs a new {@link Builder}. * * @return a new {@link Builder}. */ public static Builder builder() { return new Builder(); } /** * Constructs a {@link UncheckedFilterInputStream}. * * @param inputStream the underlying input stream, or {@code null} if this instance is to be created without an * underlying stream. */ private UncheckedFilterInputStream(final InputStream inputStream) { super(inputStream); } /** * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}. */ @Override public int available() throws UncheckedIOException { return Uncheck.get(super::available); } /** * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}. */ @Override public void close() throws UncheckedIOException { Uncheck.run(super::close); } /** * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}. */ @Override public int read() throws UncheckedIOException { return Uncheck.get(super::read); } /** * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}. */ @Override public int read(final byte[] b) throws UncheckedIOException { return Uncheck.apply(super::read, b); } /** * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}. */ @Override public int read(final byte[] b, final int off, final int len) throws UncheckedIOException { return Uncheck.apply(super::read, b, off, len); } /** * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}. */ @Override public synchronized void reset() throws UncheckedIOException { Uncheck.run(super::reset); } /** * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}. */ @Override public long skip(final long n) throws UncheckedIOException { return Uncheck.apply(super::skip, n); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/UncheckedFilterReader.java0100644 0000000 0000000 00000012744 14603604450 031731 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.FilterReader; import java.io.IOException; import java.io.Reader; import java.io.UncheckedIOException; import java.nio.CharBuffer; import org.apache.commons.io.build.AbstractStreamBuilder; import org.apache.commons.io.function.Uncheck; /** * A {@link FilterReader} that throws {@link UncheckedIOException} instead of {@link IOException}. *

* To build an instance, use {@link Builder}. *

* * @see Builder * @see FilterReader * @see IOException * @see UncheckedIOException * @since 2.12.0 */ public final class UncheckedFilterReader extends FilterReader { // @formatter:off /** * Builds a new {@link UncheckedFilterReader}. * *

* Using File IO: *

*
{@code
     * UncheckedFilterReader s = UncheckedFilterReader.builder()
     *   .setFile(file)
     *   .get();}
     * 
*

* Using NIO Path: *

*
{@code
     * UncheckedFilterReader s = UncheckedFilterReader.builder()
     *   .setPath(path)
     *   .get();}
     * 
* * @see #get() */ // @formatter:on public static class Builder extends AbstractStreamBuilder { /** * Builds a new {@link UncheckedFilterReader}. *

* You must set input that supports {@link #getReader()} on this builder, otherwise, this method throws an exception. *

*

* This builder use the following aspects: *

*
    *
  • {@link #getReader()}
  • *
* * @return a new instance. * @throws UnsupportedOperationException if the origin cannot provide a Reader. * @throws IllegalStateException if the {@code origin} is {@code null}. * @see #getReader() */ @Override public UncheckedFilterReader get() { // This an unchecked class, so this method is as well. return Uncheck.get(() -> new UncheckedFilterReader(getReader())); } } /** * Constructs a new {@link Builder}. * * @return a new {@link Builder}. */ public static Builder builder() { return new Builder(); } /** * Constructs a new filtered reader. * * @param reader a Reader object providing the underlying stream. * @throws NullPointerException if {@code reader} is {@code null}. */ private UncheckedFilterReader(final Reader reader) { super(reader); } /** * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}. */ @Override public void close() throws UncheckedIOException { Uncheck.run(super::close); } /** * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}. */ @Override public void mark(final int readAheadLimit) throws UncheckedIOException { Uncheck.accept(super::mark, readAheadLimit); } /** * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}. */ @Override public int read() throws UncheckedIOException { return Uncheck.get(super::read); } /** * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}. */ @Override public int read(final char[] cbuf) throws UncheckedIOException { return Uncheck.apply(super::read, cbuf); } /** * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}. */ @Override public int read(final char[] cbuf, final int off, final int len) throws UncheckedIOException { return Uncheck.apply(super::read, cbuf, off, len); } /** * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}. */ @Override public int read(final CharBuffer target) throws UncheckedIOException { return Uncheck.apply(super::read, target); } /** * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}. */ @Override public boolean ready() throws UncheckedIOException { return Uncheck.get(super::ready); } /** * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}. */ @Override public void reset() throws UncheckedIOException { Uncheck.run(super::reset); } /** * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}. */ @Override public long skip(final long n) throws UncheckedIOException { return Uncheck.apply(super::skip, n); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/UnixLineEndingInputStream.java0100644 0000000 0000000 00000007202 14603604450 032614 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 atEos; private boolean atSlashCr; private boolean atSlashLf; private final InputStream in; private final boolean lineFeedAtEndOfFile; /** * Constructs an input stream that filters another stream * * @param inputStream The input stream to wrap * @param ensureLineFeedAtEndOfFile true to ensure that the file ends with LF */ public UnixLineEndingInputStream(final InputStream inputStream, final boolean ensureLineFeedAtEndOfFile) { this.in = inputStream; this.lineFeedAtEndOfFile = ensureLineFeedAtEndOfFile; } /** * Closes the stream. Also closes the underlying stream. * @throws IOException upon error */ @Override public void close() throws IOException { super.close(); in.close(); } /** * Handles the end of stream condition. * * @param previousWasSlashCr Indicates if the last seen was a {@code \r}. * @return The next char to output to the stream. */ private int handleEos(final boolean previousWasSlashCr) { if (previousWasSlashCr || !lineFeedAtEndOfFile) { return EOF; } if (!atSlashLf) { atSlashLf = true; return LF; } return EOF; } /** * {@inheritDoc} */ @Override public synchronized void mark(final int readLimit) { throw UnsupportedOperationExceptions.mark(); } /** * {@inheritDoc} */ @Override public int read() throws IOException { final boolean previousWasSlashR = atSlashCr; if (atEos) { return handleEos(previousWasSlashR); } final int target = readWithUpdate(); if (atEos) { return handleEos(previousWasSlashR); } if (atSlashCr) { return LF; } if (previousWasSlashR && atSlashLf) { return read(); } return target; } /** * 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.in.read(); atEos = target == EOF; if (atEos) { return target; } atSlashCr = target == CR; atSlashLf = target == LF; return target; } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/UnsupportedOperationExceptions.java0100644 0000000 0000000 00000004420 14603604450 034012 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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. *

*/ final class UnsupportedOperationExceptions { private static final String MARK_RESET = "mark/reset"; /** * Constructs 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); } /** * Constructs 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"); } /** * Constructs 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 00000000147 14603604450 011637 Lustar 0000000 0000000 commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/UnsynchronizedBufferedInputStream.javacommons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/UnsynchronizedBufferedInputStream.ja0100644 0000000 0000000 00000040511 14603604450 034072 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.IOException; import java.io.InputStream; import org.apache.commons.io.IOUtils; import org.apache.commons.io.build.AbstractStreamBuilder; /** * An unsynchronized version of {@link BufferedInputStream}, not thread-safe. *

* Wraps an existing {@link InputStream} and buffers the input. Expensive interaction with the underlying input stream is minimized, since most * (smaller) requests can be satisfied by accessing the buffer alone. The drawback is that some extra space is required to hold the buffer and that copying * takes place when filling that buffer, but this is usually outweighed by the performance benefits. *

*

* To build an instance, use {@link Builder}. *

*

* A typical application pattern for the class looks like this: *

* *
 * UnsynchronizedBufferedInputStream s = new UnsynchronizedBufferedInputStream.Builder().
 *   .setInputStream(new FileInputStream("file.java"))
 *   .setBufferSize(8192)
 *   .get();
 * 
*

* Provenance: Apache Harmony and modified. *

* * @see Builder * @see BufferedInputStream * @since 2.12.0 */ //@NotThreadSafe public final class UnsynchronizedBufferedInputStream extends UnsynchronizedFilterInputStream { // @formatter:off /** * Builds a new {@link UnsynchronizedBufferedInputStream}. * *

* Using File IO: *

*
{@code
     * UnsynchronizedBufferedInputStream s = UnsynchronizedBufferedInputStream.builder()
     *   .setFile(file)
     *   .setBufferSize(8192)
     *   .get();}
     * 
*

* Using NIO Path: *

*
{@code
     * UnsynchronizedBufferedInputStream s = UnsynchronizedBufferedInputStream.builder()
     *   .setPath(path)
     *   .setBufferSize(8192)
     *   .get();}
     * 
* * @see #get() */ // @formatter:on public static class Builder extends AbstractStreamBuilder { /** * Builds a new {@link UnsynchronizedBufferedInputStream}. *

* You must set input that supports {@link #getInputStream()} on this builder, otherwise, this method throws an exception. *

*

* This builder use the following aspects: *

*
    *
  • {@link #getInputStream()}
  • *
  • {@link #getBufferSize()}
  • *
* * @return a new instance. * @throws IllegalStateException if the {@code origin} is {@code null}. * @throws UnsupportedOperationException if the origin cannot be converted to an {@link InputStream}. * @throws IOException if an I/O error occurs. * @see #getInputStream() * @see #getBufferSize() */ @SuppressWarnings("resource") // Caller closes. @Override public UnsynchronizedBufferedInputStream get() throws IOException { return new UnsynchronizedBufferedInputStream(getInputStream(), getBufferSize()); } } /** * The buffer containing the current bytes read from the target InputStream. */ protected volatile byte[] buffer; /** * The total number of bytes inside the byte array {@code buffer}. */ protected int count; /** * The current limit, which when passed, invalidates the current mark. */ protected int markLimit; /** * The currently marked position. -1 indicates no mark has been set or the mark has been invalidated. */ protected int markPos = IOUtils.EOF; /** * The current position within the byte array {@code buffer}. */ protected int pos; /** * Constructs a new {@code BufferedInputStream} on the {@link InputStream} {@code in}. The buffer size is specified by the parameter {@code size} and all * reads are now filtered through this stream. * * @param in the input stream the buffer reads from. * @param size the size of buffer to allocate. * @throws IllegalArgumentException if {@code size < 0}. */ private UnsynchronizedBufferedInputStream(final InputStream in, final int size) { super(in); if (size <= 0) { throw new IllegalArgumentException("Size must be > 0"); } buffer = new byte[size]; } /** * Returns the number of bytes that are available before this stream will block. This method returns the number of bytes available in the buffer plus those * available in the source stream. * * @return the number of bytes available before blocking. * @throws IOException if this stream is closed. */ @Override public int available() throws IOException { final InputStream localIn = inputStream; // 'in' could be invalidated by close() if (buffer == null || localIn == null) { throw new IOException("Stream is closed"); } return count - pos + localIn.available(); } /** * Closes this stream. The source stream is closed and any resources associated with it are released. * * @throws IOException if an error occurs while closing this stream. */ @Override public void close() throws IOException { buffer = null; final InputStream localIn = inputStream; inputStream = null; if (localIn != null) { localIn.close(); } } private int fillBuffer(final InputStream localIn, byte[] localBuf) throws IOException { if (markPos == IOUtils.EOF || pos - markPos >= markLimit) { /* Mark position not set or exceeded readLimit */ final int result = localIn.read(localBuf); if (result > 0) { markPos = IOUtils.EOF; pos = 0; count = result; } return result; } if (markPos == 0 && markLimit > localBuf.length) { /* Increase buffer size to accommodate the readLimit */ int newLength = localBuf.length * 2; if (newLength > markLimit) { newLength = markLimit; } final byte[] newbuf = new byte[newLength]; System.arraycopy(localBuf, 0, newbuf, 0, localBuf.length); // Reassign buffer, which will invalidate any local references // FIXME: what if buffer was null? localBuf = buffer = newbuf; } else if (markPos > 0) { System.arraycopy(localBuf, markPos, localBuf, 0, localBuf.length - markPos); } // Set the new position and mark position pos -= markPos; count = markPos = 0; final int bytesread = localIn.read(localBuf, pos, localBuf.length - pos); count = bytesread <= 0 ? pos : pos + bytesread; return bytesread; } byte[] getBuffer() { return buffer; } /** * Sets a mark position in this stream. The parameter {@code readLimit} indicates how many bytes can be read before a mark is invalidated. Calling * {@code reset()} will reposition the stream back to the marked position if {@code readLimit} has not been surpassed. The underlying buffer may be * increased in size to allow {@code readLimit} number of bytes to be supported. * * @param readLimit the number of bytes that can be read before the mark is invalidated. * @see #reset() */ @Override public void mark(final int readLimit) { markLimit = readLimit; markPos = pos; } /** * Indicates whether {@code BufferedInputStream} supports the {@code mark()} and {@code reset()} methods. * * @return {@code true} for BufferedInputStreams. * @see #mark(int) * @see #reset() */ @Override public boolean markSupported() { return true; } /** * Reads a single byte from this stream and returns it as an integer in the range from 0 to 255. Returns -1 if the end of the source string has been * reached. If the internal buffer does not contain any available bytes then it is filled from the source stream and the first byte is returned. * * @return the byte read or -1 if the end of the source stream has been reached. * @throws IOException if this stream is closed or another IOException occurs. */ @Override public int read() throws IOException { // Use local refs since buf and in may be invalidated by an // unsynchronized close() byte[] localBuf = buffer; final InputStream localIn = inputStream; if (localBuf == null || localIn == null) { throw new IOException("Stream is closed"); } /* Are there buffered bytes available? */ if (pos >= count && fillBuffer(localIn, localBuf) == IOUtils.EOF) { return IOUtils.EOF; /* no, fill buffer */ } // localBuf may have been invalidated by fillbuf if (localBuf != buffer) { localBuf = buffer; if (localBuf == null) { throw new IOException("Stream is closed"); } } /* Did filling the buffer fail with -1 (EOF)? */ if (count - pos > 0) { return localBuf[pos++] & 0xFF; } return IOUtils.EOF; } /** * Reads at most {@code length} bytes from this stream and stores them in byte array {@code buffer} starting at offset {@code offset}. Returns the number of * bytes actually read or -1 if no bytes were read and the end of the stream was encountered. If all the buffered bytes have been used, a mark has not been * set and the requested number of bytes is larger than the receiver's buffer size, this implementation bypasses the buffer and simply places the results * directly into {@code buffer}. * * @param dest the byte array in which to store the bytes read. * @param offset the initial position in {@code buffer} to store the bytes read from this stream. * @param length the maximum number of bytes to store in {@code buffer}. * @return the number of bytes actually read or -1 if end of stream. * @throws IndexOutOfBoundsException if {@code offset < 0} or {@code length < 0}, or if {@code offset + length} is greater than the size of {@code buffer}. * @throws IOException if the stream is already closed or another IOException occurs. */ @Override public int read(final byte[] dest, int offset, final int length) throws IOException { // Use local ref since buf may be invalidated by an unsynchronized // close() byte[] localBuf = buffer; if (localBuf == null) { throw new IOException("Stream is closed"); } // avoid int overflow if (offset > dest.length - length || offset < 0 || length < 0) { throw new IndexOutOfBoundsException(); } if (length == 0) { return 0; } final InputStream localIn = inputStream; if (localIn == null) { throw new IOException("Stream is closed"); } int required; if (pos < count) { /* There are bytes available in the buffer. */ final int copylength = count - pos >= length ? length : count - pos; System.arraycopy(localBuf, pos, dest, offset, copylength); pos += copylength; if (copylength == length || localIn.available() == 0) { return copylength; } offset += copylength; required = length - copylength; } else { required = length; } while (true) { final int read; /* * If we're not marked and the required size is greater than the buffer, simply read the bytes directly bypassing the buffer. */ if (markPos == IOUtils.EOF && required >= localBuf.length) { read = localIn.read(dest, offset, required); if (read == IOUtils.EOF) { return required == length ? IOUtils.EOF : length - required; } } else { if (fillBuffer(localIn, localBuf) == IOUtils.EOF) { return required == length ? IOUtils.EOF : length - required; } // localBuf may have been invalidated by fillBuffer() if (localBuf != buffer) { localBuf = buffer; if (localBuf == null) { throw new IOException("Stream is closed"); } } read = count - pos >= required ? required : count - pos; System.arraycopy(localBuf, pos, dest, offset, read); pos += read; } required -= read; if (required == 0) { return length; } if (localIn.available() == 0) { return length - required; } offset += read; } } /** * Resets this stream to the last marked location. * * @throws IOException if this stream is closed, no mark has been set or the mark is no longer valid because more than {@code readLimit} bytes have been * read since setting the mark. * @see #mark(int) */ @Override public void reset() throws IOException { if (buffer == null) { throw new IOException("Stream is closed"); } if (IOUtils.EOF == markPos) { throw new IOException("Mark has been invalidated"); } pos = markPos; } /** * Skips {@code amount} number of bytes in this stream. Subsequent {@code read()}'s will not return these bytes unless {@code reset()} is used. * * @param amount the number of bytes to skip. {@code skip} does nothing and returns 0 if {@code amount} is less than zero. * @return the number of bytes actually skipped. * @throws IOException if this stream is closed or another IOException occurs. */ @Override public long skip(final long amount) throws IOException { // Use local refs since buf and in may be invalidated by an // unsynchronized close() final byte[] localBuf = buffer; final InputStream localIn = inputStream; if (localBuf == null) { throw new IOException("Stream is closed"); } if (amount < 1) { return 0; } if (localIn == null) { throw new IOException("Stream is closed"); } if (count - pos >= amount) { // (int count - int pos) here is always an int so amount is also in the int range if the above test is true. // We can safely cast to int and avoid static analysis warnings. pos += (int) amount; return amount; } int read = count - pos; pos = count; if (markPos != IOUtils.EOF && amount <= markLimit) { if (fillBuffer(localIn, localBuf) == IOUtils.EOF) { return read; } if (count - pos >= amount - read) { // (int count - int pos) here is always an int so (amount - read) is also in the int range if the above test is true. // We can safely cast to int and avoid static analysis warnings. pos += (int) amount - read; return amount; } // Couldn't get all the bytes, skip what we read read += count - pos; pos = count; return read; } return read + localIn.skip(amount - read); } } ././@LongLink0100644 0000000 0000000 00000000150 14603604450 011631 Lustar 0000000 0000000 commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/UnsynchronizedByteArrayInputStream.javacommons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/UnsynchronizedByteArrayInputStream.j0100644 0000000 0000000 00000022233 14603604450 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.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Objects; import org.apache.commons.io.build.AbstractOrigin; import org.apache.commons.io.build.AbstractStreamBuilder; /** * 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. *

* To build an instance, use {@link Builder}. *

* * @see Builder * @see ByteArrayInputStream * @since 2.7 */ //@NotThreadSafe public class UnsynchronizedByteArrayInputStream extends InputStream { // @formatter:off /** * Builds a new {@link UnsynchronizedByteArrayInputStream}. * *

* Using a Byte Array: *

*
{@code
     * UnsynchronizedByteArrayInputStream s = UnsynchronizedByteArrayInputStream.builder()
     *   .setByteArray(byteArray)
     *   .setOffset(0)
     *   .setLength(byteArray.length)
     *   .get();
     * }
     * 
*

* Using File IO: *

*
{@code
     * UnsynchronizedByteArrayInputStream s = UnsynchronizedByteArrayInputStream.builder()
     *   .setFile(file)
     *   .setOffset(0)
     *   .setLength(byteArray.length)
     *   .get();
     * }
     * 
*

* Using NIO Path: *

*
{@code
     * UnsynchronizedByteArrayInputStream s = UnsynchronizedByteArrayInputStream.builder()
     *   .setPath(path)
     *   .setOffset(0)
     *   .setLength(byteArray.length)
     *   .get();
     * }
     * 
* * @see #get() */ // @formatter:on public static class Builder extends AbstractStreamBuilder { private int offset; private int length; /** * Builds a new {@link UnsynchronizedByteArrayInputStream}. *

* You must set input that supports {@code byte[]} on this builder, otherwise, this method throws an exception. *

*

* This builder use the following aspects: *

*
    *
  • {@code byte[]}
  • *
  • offset
  • *
  • length
  • *
* * @return a new instance. * @throws UnsupportedOperationException if the origin cannot provide a byte[]. * @throws IllegalStateException if the {@code origin} is {@code null}. * @see AbstractOrigin#getByteArray() */ @Override public UnsynchronizedByteArrayInputStream get() throws IOException { return new UnsynchronizedByteArrayInputStream(checkOrigin().getByteArray(), offset, length); } @Override public Builder setByteArray(final byte[] origin) { length = Objects.requireNonNull(origin, "origin").length; return super.setByteArray(origin); } /** * Sets the length. * * @param length Must be greater or equal to 0. * @return this. */ public Builder setLength(final int length) { if (length < 0) { throw new IllegalArgumentException("length cannot be negative"); } this.length = length; return this; } /** * Sets the offset. * * @param offset Must be greater or equal to 0. * @return this. */ public Builder setOffset(final int offset) { if (offset < 0) { throw new IllegalArgumentException("offset cannot be negative"); } this.offset = offset; return this; } } /** * The end of stream marker. */ public static final int END_OF_STREAM = -1; /** * Constructs a new {@link Builder}. * * @return a new {@link Builder}. */ public static Builder builder() { return new Builder(); } private static int minPosLen(final byte[] data, final int defaultValue) { requireNonNegative(defaultValue, "defaultValue"); return Math.min(defaultValue, data.length > 0 ? data.length : defaultValue); } private static int requireNonNegative(final int value, final String name) { if (value < 0) { throw new IllegalArgumentException(name + " cannot be negative"); } return value; } /** * 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; /** * Constructs a new byte array input stream. * * @param data the buffer * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}. */ @Deprecated public UnsynchronizedByteArrayInputStream(final byte[] data) { this(data, data.length, 0, 0); } /** * Constructs 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 * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}. */ @Deprecated public UnsynchronizedByteArrayInputStream(final byte[] data, final int offset) { this(data, data.length, Math.min(requireNonNegative(offset, "offset"), minPosLen(data, offset)), minPosLen(data, offset)); } /** * Constructs 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 * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}. */ @Deprecated public UnsynchronizedByteArrayInputStream(final byte[] data, final int offset, final int length) { requireNonNegative(offset, "offset"); requireNonNegative(length, "length"); this.data = Objects.requireNonNull(data, "data"); this.eod = Math.min(minPosLen(data, offset) + length, data.length); this.offset = minPosLen(data, offset); this.markedOffset = minPosLen(data, offset); } private UnsynchronizedByteArrayInputStream(final byte[] data, final int eod, final int offset, final int markedOffset) { this.data = Objects.requireNonNull(data, "data"); this.eod = eod; this.offset = offset; this.markedOffset = markedOffset; } @Override public int available() { return offset < eod ? eod - offset : 0; } @SuppressWarnings("sync-override") @Override public void mark(final int readLimit) { this.markedOffset = this.offset; } @Override public boolean markSupported() { return true; } @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; } @SuppressWarnings("sync-override") @Override public void reset() { this.offset = this.markedOffset; } @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 = Math.addExact(offset, Math.toIntExact(n)); return actualSkip; } } ././@LongLink0100644 0000000 0000000 00000000145 14603604450 011635 Lustar 0000000 0000000 commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/UnsynchronizedFilterInputStream.javacommons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/UnsynchronizedFilterInputStream.java0100644 0000000 0000000 00000021573 14603604450 034133 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.FilterInputStream; import java.io.IOException; import java.io.InputStream; import org.apache.commons.io.build.AbstractStreamBuilder; /** * An unsynchronized version of {@link FilterInputStream}, not thread-safe. *

* Wraps an existing {@link InputStream} and performs some transformation on the input data while it is being read. Transformations can be anything from a * simple byte-wise filtering input data to an on-the-fly compression or decompression of the underlying stream. Input streams that wrap another input stream * and provide some additional functionality on top of it usually inherit from this class. *

*

* To build an instance, use {@link Builder}. *

*

* Provenance: Apache Harmony and modified. *

* * @see Builder * @see FilterInputStream * @since 2.12.0 */ //@NotThreadSafe public class UnsynchronizedFilterInputStream extends InputStream { // @formatter:off /** * Builds a new {@link UnsynchronizedFilterInputStream}. * *

* Using File IO: *

*
{@code
     * UnsynchronizedFilterInputStream s = UnsynchronizedFilterInputStream.builder()
     *   .setFile(file)
     *   .get();}
     * 
*

* Using NIO Path: *

*
{@code
     * UnsynchronizedFilterInputStream s = UnsynchronizedFilterInputStream.builder()
     *   .setPath(path)
     *   .get();}
     * 
* * @see #get() */ // @formatter:on public static class Builder extends AbstractStreamBuilder { /** * Builds a new {@link UnsynchronizedFilterInputStream}. *

* You must set input that supports {@link #getInputStream()}, otherwise, this method throws an exception. *

*

* This builder use the following aspects: *

*
    *
  • {@link #getInputStream()}
  • *
* * @return a new instance. * @throws IllegalStateException if the {@code origin} is {@code null}. * @throws UnsupportedOperationException if the origin cannot be converted to an {@link InputStream}. * @throws IOException if an I/O error occurs. * @see #getInputStream() */ @SuppressWarnings("resource") // Caller closes. @Override public UnsynchronizedFilterInputStream get() throws IOException { return new UnsynchronizedFilterInputStream(getInputStream()); } } /** * Constructs a new {@link Builder}. * * @return a new {@link Builder}. */ public static Builder builder() { return new Builder(); } /** * The source input stream that is filtered. */ protected volatile InputStream inputStream; /** * Constructs a new {@code FilterInputStream} with the specified input stream as source. * * @param inputStream the non-null InputStream to filter reads on. */ UnsynchronizedFilterInputStream(final InputStream inputStream) { this.inputStream = inputStream; } /** * Returns the number of bytes that are available before this stream will block. * * @return the number of bytes available before blocking. * @throws IOException if an error occurs in this stream. */ @Override public int available() throws IOException { return inputStream.available(); } /** * Closes this stream. This implementation closes the filtered stream. * * @throws IOException if an error occurs while closing this stream. */ @Override public void close() throws IOException { inputStream.close(); } /** * Sets a mark position in this stream. The parameter {@code readLimit} indicates how many bytes can be read before the mark is invalidated. Sending * {@code reset()} will reposition this stream back to the marked position, provided that {@code readLimit} has not been surpassed. *

* This implementation sets a mark in the filtered stream. * * @param readLimit the number of bytes that can be read from this stream before the mark is invalidated. * @see #markSupported() * @see #reset() */ @SuppressWarnings("sync-override") // by design. @Override public void mark(final int readLimit) { inputStream.mark(readLimit); } /** * Indicates whether this stream supports {@code mark()} and {@code reset()}. This implementation returns whether or not the filtered stream supports * marking. * * @return {@code true} if {@code mark()} and {@code reset()} are supported, {@code false} otherwise. * @see #mark(int) * @see #reset() * @see #skip(long) */ @Override public boolean markSupported() { return inputStream.markSupported(); } /** * Reads a single byte from the filtered stream and returns it as an integer in the range from 0 to 255. Returns -1 if the end of this stream has been * reached. * * @return the byte read or -1 if the end of the filtered stream has been reached. * @throws IOException if the stream is closed or another IOException occurs. */ @Override public int read() throws IOException { return inputStream.read(); } /** * Reads bytes from this stream and stores them in the byte array {@code buffer}. Returns the number of bytes actually read or -1 if no bytes were read and * the end of this stream was encountered. This implementation reads bytes from the filtered stream. * * @param buffer the byte array in which to store the read bytes. * @return the number of bytes actually read or -1 if the end of the filtered stream has been reached while reading. * @throws IOException if this stream is closed or another IOException occurs. */ @Override public int read(final byte[] buffer) throws IOException { return read(buffer, 0, buffer.length); } /** * Reads at most {@code count} bytes from this stream and stores them in the byte array {@code buffer} starting at {@code offset}. Returns the number of * bytes actually read or -1 if no bytes have been read and the end of this stream has been reached. This implementation reads bytes from the filtered * stream. * * @param buffer the byte array in which to store the bytes read. * @param offset the initial position in {@code buffer} to store the bytes read from this stream. * @param count the maximum number of bytes to store in {@code buffer}. * @return the number of bytes actually read or -1 if the end of the filtered stream has been reached while reading. * @throws IOException if this stream is closed or another I/O error occurs. */ @Override public int read(final byte[] buffer, final int offset, final int count) throws IOException { return inputStream.read(buffer, offset, count); } /** * Resets this stream to the last marked location. This implementation resets the target stream. * * @throws IOException if this stream is already closed, no mark has been set or the mark is no longer valid because more than {@code readLimit} bytes have * been read since setting the mark. * @see #mark(int) * @see #markSupported() */ @SuppressWarnings("sync-override") // by design. @Override public void reset() throws IOException { inputStream.reset(); } /** * Skips {@code count} number of bytes in this stream. Subsequent {@code read()}'s will not return these bytes unless {@code reset()} is used. This * implementation skips {@code count} number of bytes in the filtered stream. * * @param count the number of bytes to skip. * @return the number of bytes actually skipped. * @throws IOException if this stream is closed or another IOException occurs. * @see #mark(int) * @see #reset() */ @Override public long skip(final long count) throws IOException { return inputStream.skip(count); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/WindowsLineEndingInputStream.java0100644 0000000 0000000 00000007270 14603604450 033330 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 atEos; private boolean atSlashCr; private boolean atSlashLf; private final InputStream in; private boolean injectSlashLf; private final boolean lineFeedAtEndOfFile; /** * Constructs 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.in = in; this.lineFeedAtEndOfFile = ensureLineFeedAtEndOfFile; } /** * Closes the stream. Also closes the underlying stream. * * @throws IOException upon error */ @Override public void close() throws IOException { super.close(); in.close(); } /** * Handles the end of stream condition. * * @return The next char to output to the stream */ private int handleEos() { if (!lineFeedAtEndOfFile) { return EOF; } if (!atSlashLf && !atSlashCr) { atSlashCr = true; return CR; } if (!atSlashLf) { atSlashCr = false; atSlashLf = true; return LF; } return EOF; } /** * {@inheritDoc} */ @Override public synchronized void mark(final int readLimit) { throw UnsupportedOperationExceptions.mark(); } /** * {@inheritDoc} */ @Override public int read() throws IOException { if (atEos) { return handleEos(); } if (injectSlashLf) { injectSlashLf = false; return LF; } final boolean prevWasSlashR = atSlashCr; final int target = readWithUpdate(); if (atEos) { return handleEos(); } if (target == LF && !prevWasSlashR) { injectSlashLf = true; return CR; } return target; } /** * 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.in.read(); atEos = target == EOF; if (atEos) { return target; } atSlashCr = target == CR; atSlashLf = target == LF; return target; } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/XmlStreamReader.java0100644 0000000 0000000 00000120503 14603604450 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.charset.Charset; import java.nio.charset.StandardCharsets; 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.Charsets; import org.apache.commons.io.IOUtils; import org.apache.commons.io.build.AbstractStreamBuilder; import org.apache.commons.io.function.IOConsumer; 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. *

*

* To build an instance, use {@link Builder}. *

*

* Originally developed for ROME under Apache License 2.0. *

* * @see Builder * @see org.apache.commons.io.output.XmlStreamWriter * @since 2.0 */ public class XmlStreamReader extends Reader { // @formatter:off /** * Builds a new {@link XmlStreamWriter}. * * Constructs 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. *

*

* For example: *

* *
{@code
     * XmlStreamReader r = XmlStreamReader.builder()
     *   .setPath(path)
     *   .setCharset(StandardCharsets.UTF_8)
     *   .get();
     * }
     * 
* * @see #get() * @since 2.12.0 */ // @formatter:on public static class Builder extends AbstractStreamBuilder { private boolean nullCharset = true; private boolean lenient = true; private String httpContentType; /** * Builds a new {@link XmlStreamWriter}. *

* You must set input that supports {@link #getInputStream()}, otherwise, this method throws an exception. *

*

* This builder use the following aspects: *

*
    *
  • {@link #getInputStream()}
  • *
  • {@link #getCharset()}
  • *
  • lenient
  • *
  • httpContentType
  • *
* * @return a new instance. * @throws IllegalStateException if the {@code origin} is {@code null}. * @throws UnsupportedOperationException if the origin cannot be converted to an {@link InputStream}. * @throws IOException if an I/O error occurs. * @throws XmlStreamReaderException thrown if the Charset encoding could not be determined according to the specification. * @see #getInputStream() */ @SuppressWarnings("resource") @Override public XmlStreamReader get() throws IOException { final String defaultEncoding = nullCharset ? null : getCharset().name(); // @formatter:off return httpContentType == null ? new XmlStreamReader(getInputStream(), lenient, defaultEncoding) : new XmlStreamReader(getInputStream(), httpContentType, lenient, defaultEncoding); // @formatter:on } @Override public Builder setCharset(final Charset charset) { nullCharset = charset == null; return super.setCharset(charset); } @Override public Builder setCharset(final String charset) { nullCharset = charset == null; return super.setCharset(Charsets.toCharset(charset, getCharsetDefault())); } /** * Sets the HTTP content type. * * @param httpContentType the HTTP content type. * @return this. */ public Builder setHttpContentType(final String httpContentType) { this.httpContentType = httpContentType; return this; } /** * Sets the lenient toggle. * * @param lenient the lenient toggle. * @return this. */ public Builder setLenient(final boolean lenient) { this.lenient = lenient; return this; } } private static final String UTF_8 = StandardCharsets.UTF_8.name(); private static final String US_ASCII = StandardCharsets.US_ASCII.name(); private static final String UTF_16BE = StandardCharsets.UTF_16BE.name(); private static final String UTF_16LE = StandardCharsets.UTF_16LE.name(); private static final String UTF_32BE = "UTF-32BE"; private static final String UTF_32LE = "UTF-32LE"; private static final String UTF_16 = StandardCharsets.UTF_16.name(); 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 {@code 'xml'} processing instruction. *

* See also the NT-EncName XML specification. *

*

* Note the documented pattern is: *

*
     * EncName   ::=   [A-Za-z] ([A-Za-z0-9._] | '-')*
     * 
*

* However this does not match all the aliases that are supported by Java. For example, {@code '437'}, {@code 'ISO_8859-1:1987'} and * {@code 'ebcdic-de-273+euro'}. *

*/ public static final Pattern ENCODING_PATTERN = Pattern.compile( // @formatter:off "^<\\?xml\\s+" + "(?:version\\s*=\\s*(?:(?:\"1\\.[0-9]+\")|(?:'1.[0-9]+'))\\s+)??" + "encoding\\s*=\\s*" + "((?:\"[A-Za-z0-9][A-Za-z0-9._+:-]*\")" // double-quoted + "|(?:'[A-Za-z0-9][A-Za-z0-9._+:-]*'))", // single-quoted Pattern.MULTILINE); // @formatter:on private static final String RAW_EX_1 = "Illegal encoding, BOM [{0}] XML guess [{1}] XML prolog [{2}] encoding mismatch"; private static final String RAW_EX_2 = "Illegal encoding, BOM [{0}] XML guess [{1}] XML prolog [{2}] unknown BOM"; private static final String HTTP_EX_1 = "Illegal 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 = "Illegal encoding, CT-MIME [{0}] CT-Enc [{1}] BOM [{2}] XML guess [{3}] XML prolog [{4}], encoding mismatch"; private static final String HTTP_EX_3 = "Illegal encoding, CT-MIME [{0}] CT-Enc [{1}] BOM [{2}] XML guess [{3}] XML prolog [{4}], Illegal MIME"; /** * Constructs a new {@link Builder}. * * @return a new {@link Builder}. * @since 2.12.0 */ public static Builder builder() { return new Builder(); } /** * Gets the charset parameter value, {@code null} if not present, {@code null} if httpContentType is {@code 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; } /** * Gets the MIME type or {@code null} if httpContentType is {@code 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(";"); mime = i >= 0 ? httpContentType.substring(0, i) : httpContentType; mime = mime.trim(); } return mime; } /** * Gets the encoding declared in the , {@code 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 StringBuilder prolog = new StringBuilder(); IOConsumer.forEach(bReader.lines(), l -> prolog.append(l).append(' ')); 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; } /** * Tests 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")); } /** * Tests 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; /** * Constructs 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 NullPointerException if the input is {@code null}. * @throws IOException thrown if there is a problem reading the file. * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated public XmlStreamReader(final File file) throws IOException { this(Objects.requireNonNull(file, "file").toPath()); } /** * Constructs 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 NullPointerException if the input stream is {@code null}. * @throws IOException thrown if there is a problem reading the stream. * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated public XmlStreamReader(final InputStream inputStream) throws IOException { this(inputStream, true); } /** * Constructs 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 NullPointerException if the input stream is {@code null}. * @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 specification. * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated public XmlStreamReader(final InputStream inputStream, final boolean lenient) throws IOException { this(inputStream, lenient, null); } /** * Constructs 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 NullPointerException if the input stream is {@code null}. * @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 specification. * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated @SuppressWarnings("resource") // InputStream is managed through a InputStreamReader in this instance. public XmlStreamReader(final InputStream inputStream, final boolean lenient, final String defaultEncoding) throws IOException { this.defaultEncoding = defaultEncoding; final BOMInputStream bom = new BOMInputStream(new BufferedInputStream(Objects.requireNonNull(inputStream, "inputStream"), IOUtils.DEFAULT_BUFFER_SIZE), false, BOMS); final BOMInputStream pis = new BOMInputStream(bom, true, XML_GUESS_BYTES); this.encoding = processHttpStream(bom, pis, lenient); this.reader = new InputStreamReader(pis, encoding); } /** * Constructs 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 NullPointerException if the input stream is {@code null}. * @throws IOException thrown if there is a problem reading the file. * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated public XmlStreamReader(final InputStream inputStream, final String httpContentType) throws IOException { this(inputStream, httpContentType, true); } /** * Constructs 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 NullPointerException if the input stream is {@code null}. * @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 specification. * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated public XmlStreamReader(final InputStream inputStream, final String httpContentType, final boolean lenient) throws IOException { this(inputStream, httpContentType, lenient, null); } /** * Constructs 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 NullPointerException if the input stream is {@code null}. * @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 specification. * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated @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 { this.defaultEncoding = defaultEncoding; final BOMInputStream bom = new BOMInputStream(new BufferedInputStream(Objects.requireNonNull(inputStream, "inputStream"), IOUtils.DEFAULT_BUFFER_SIZE), false, BOMS); final BOMInputStream pis = new BOMInputStream(bom, true, XML_GUESS_BYTES); this.encoding = processHttpStream(bom, pis, lenient, httpContentType); this.reader = new InputStreamReader(pis, encoding); } /** * Constructs 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 NullPointerException if the input is {@code null}. * @throws IOException thrown if there is a problem reading the file. * @since 2.11.0 * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated @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"))); } /** * Constructs 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 NullPointerException if the input is {@code null}. * @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); } /** * Constructs 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 urlConnection URLConnection to create a Reader from. * @param defaultEncoding The default encoding * @throws NullPointerException if the input is {@code null}. * @throws IOException thrown if there is a problem reading the stream of the URLConnection. */ public XmlStreamReader(final URLConnection urlConnection, final String defaultEncoding) throws IOException { Objects.requireNonNull(urlConnection, "urlConnection"); this.defaultEncoding = defaultEncoding; final boolean lenient = true; final String contentType = urlConnection.getContentType(); final InputStream inputStream = urlConnection.getInputStream(); @SuppressWarnings("resource") // managed by the InputStreamReader tracked by this instance // @formatter:off final BOMInputStream bomInput = BOMInputStream.builder() .setInputStream(new BufferedInputStream(inputStream, IOUtils.DEFAULT_BUFFER_SIZE)) .setInclude(false) .setByteOrderMarks(BOMS) .get(); @SuppressWarnings("resource") final BOMInputStream piInput = BOMInputStream.builder() .setInputStream(new BufferedInputStream(bomInput, IOUtils.DEFAULT_BUFFER_SIZE)) .setInclude(true) .setByteOrderMarks(XML_GUESS_BYTES) .get(); // @formatter:on if (urlConnection instanceof HttpURLConnection || contentType != null) { this.encoding = processHttpStream(bomInput, piInput, lenient, contentType); } else { this.encoding = processHttpStream(bomInput, piInput, lenient); } this.reader = new InputStreamReader(piInput, encoding); } /** * Calculates the HTTP encoding. * @param bomEnc BOM encoding * @param xmlGuessEnc XML Guess encoding * @param xmlEnc XML encoding * @param lenient indicates if the charset encoding detection should be relaxed. * @param httpContentType The HTTP content type * * @return the HTTP encoding * @throws IOException thrown if there is a problem reading the stream. */ String calculateHttpEncoding(final String bomEnc, final String xmlGuessEnc, final String xmlEnc, final boolean lenient, final String httpContentType) 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(); } /** * Does 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(ex.getBomEncoding(), ex.getXmlGuessEncoding(), ex.getXmlEncoding(), true, httpContentType); } 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; } /** * Gets 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 {@code null} the content-type based rules are used. *

* * @return the default encoding to use. */ public String getDefaultEncoding() { return defaultEncoding; } /** * Gets the charset encoding of the XmlStreamReader. * * @return charset encoding. */ public String getEncoding() { return encoding; } /** * Process the raw stream. * * @param bomInput BOMInputStream to detect byte order marks * @param piInput 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 processHttpStream(final BOMInputStream bomInput, final BOMInputStream piInput, final boolean lenient) throws IOException { final String bomEnc = bomInput.getBOMCharsetName(); final String xmlGuessEnc = piInput.getBOMCharsetName(); final String xmlEnc = getXmlProlog(piInput, xmlGuessEnc); try { return calculateRawEncoding(bomEnc, xmlGuessEnc, xmlEnc); } catch (final XmlStreamReaderException ex) { if (lenient) { return doLenientDetection(null, ex); } throw ex; } } /** * Processes an HTTP stream. * * @param bomInput BOMInputStream to detect byte order marks * @param piInput BOMInputStream to guess XML encoding * @param lenient indicates if the charset encoding detection should be relaxed. * @param httpContentType The HTTP content type * @return the encoding to be used * @throws IOException thrown if there is a problem reading the stream. */ private String processHttpStream(final BOMInputStream bomInput, final BOMInputStream piInput, final boolean lenient, final String httpContentType) throws IOException { final String bomEnc = bomInput.getBOMCharsetName(); final String xmlGuessEnc = piInput.getBOMCharsetName(); final String xmlEnc = getXmlProlog(piInput, xmlGuessEnc); try { return calculateHttpEncoding(bomEnc, xmlGuessEnc, xmlEnc, lenient, httpContentType); } catch (final XmlStreamReaderException ex) { if (lenient) { return doLenientDetection(httpContentType, ex); } throw ex; } } /** * Reads 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.16.1-src/src/main/java/org/apache/commons/io/input/XmlStreamReaderException.java0100644 0000000 0000000 00000011312 14603604450 032453 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; /** * The Byte-Order-Mark (BOM) encoding or null. */ private final String bomEncoding; /** * The guessed encoding. */ private final String xmlGuessEncoding; /** * The XML encoding. */ private final String xmlEncoding; /** * The MIME type in the content type. */ private final String contentTypeMime; /** * The encoding in the content type. */ private final String contentTypeEncoding; /** * Constructs 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); } /** * Constructs 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; } /** * Gets the BOM encoding found in the InputStream. * * @return the BOM encoding, null if none. */ public String getBomEncoding() { return bomEncoding; } /** * Gets 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; } /** * Gets 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; } /** * Gets the encoding found in the XML prolog of the input. * * @return the encoding of the XML prolog, null if none. */ public String getXmlEncoding() { return xmlEncoding; } /** * Gets the encoding guess based on the first bytes of the input. * * @return the encoding guess, null if it couldn't be guessed. */ public String getXmlGuessEncoding() { return xmlGuessEncoding; } } ././@LongLink0100644 0000000 0000000 00000000146 14603604450 011636 Lustar 0000000 0000000 commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/buffer/CircularBufferInputStream.javacommons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/buffer/CircularBufferInputStream.jav0100644 0000000 0000000 00000011473 14603604450 033747 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.FilterInputStream; 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 FilterInputStream { /** Internal buffer. */ protected final CircularByteBuffer buffer; /** Internal buffer size. */ protected final int bufferSize; /** Whether we've seen the input stream EOF. */ private boolean eof; /** * Constructs 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); } /** * Constructs 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. */ @SuppressWarnings("resource") // Caller closes InputStream public CircularBufferInputStream(final InputStream inputStream, final int bufferSize) { super(Objects.requireNonNull(inputStream, "inputStream")); if (bufferSize <= 0) { throw new IllegalArgumentException("Illegal bufferSize: " + bufferSize); } this.buffer = new CircularByteBuffer(bufferSize); this.bufferSize = bufferSize; this.eof = false; } @Override public void close() throws IOException { super.close(); eof = true; buffer.clear(); } /** * 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[] 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; } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/buffer/CircularByteBuffer.java0100644 0000000 0000000 00000024117 14603604450 032537 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; /** * Constructs a new instance with a reasonable default buffer size ({@link IOUtils#DEFAULT_BUFFER_SIZE}). */ public CircularByteBuffer() { this(IOUtils.DEFAULT_BUFFER_SIZE); } /** * Constructs 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; } /** * 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; } } /** * 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("Illegal offset: " + offset); } if (length < 0) { throw new IllegalArgumentException("Illegal 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; } /** * Removes all bytes from the buffer. */ public void clear() { startOffset = 0; endOffset = 0; currentNumberOfBytes = 0; } /** * Returns the number of bytes, that are currently present in the buffer. * * @return the number of bytes */ public int getCurrentNumberOfBytes() { return currentNumberOfBytes; } /** * 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, 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, 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 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("Illegal offset: " + offset); } if (length < 0 || length > buffer.length) { throw new IllegalArgumentException("Illegal 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; } /** * 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("Illegal offset: " + targetOffset); } if (length < 0 || length > buffer.length) { throw new IllegalArgumentException("Illegal 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; } } } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/buffer/PeekableInputStream.java0100644 0000000 0000000 00000007031 14603604450 032715 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; import org.apache.commons.io.IOUtils; /** * 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 { /** * Constructs 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 PeekableInputStream(final InputStream inputStream) { super(inputStream); } /** * Constructs 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); } /** * 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.16.1-src/src/main/java/org/apache/commons/io/input/buffer/package-info.java0100644 0000000 0000000 00000002046 14603604450 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. */ /** * Provides implementations of buffered input classes, such as * {@link org.apache.commons.io.input.buffer.CircularBufferInputStream} and * {@link org.apache.commons.io.input.buffer.PeekableInputStream}. */ package org.apache.commons.io.input.buffer; commons-io-2.16.1-src/src/main/java/org/apache/commons/io/input/package-info.java0100644 0000000 0000000 00000001677 14603604450 030076 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Provides implementations of input classes, such as {@link java.io.InputStream} and {@link java.io.Reader}. */ package org.apache.commons.io.input; commons-io-2.16.1-src/src/main/java/org/apache/commons/io/monitor/FileAlterationListener.java0100644 0000000 0000000 00000004406 14603604450 032503 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; /** * Receives events of file system modifications. *

* Register {@link FileAlterationListener}s with a {@link FileAlterationObserver}. *

* * @see FileAlterationObserver * @since 2.0 */ public interface FileAlterationListener { /** * Directory changed Event. * * @param directory The directory changed */ void onDirectoryChange(final File directory); /** * Directory created Event. * * @param directory The directory created */ void onDirectoryCreate(final File directory); /** * Directory deleted Event. * * @param directory The directory deleted */ void onDirectoryDelete(final File directory); /** * File changed Event. * * @param file The file changed */ void onFileChange(final File file); /** * File created Event. * * @param file The file created */ void onFileCreate(final File file); /** * File deleted Event. * * @param file The file deleted */ void onFileDelete(final File file); /** * File system observer started checking event. * * @param observer The file system observer */ void onStart(final FileAlterationObserver observer); /** * File system observer finished checking event. * * @param observer The file system observer */ void onStop(final FileAlterationObserver observer); } ././@LongLink0100644 0000000 0000000 00000000145 14603604450 011635 Lustar 0000000 0000000 commons-io-2.16.1-src/src/main/java/org/apache/commons/io/monitor/FileAlterationListenerAdaptor.javacommons-io-2.16.1-src/src/main/java/org/apache/commons/io/monitor/FileAlterationListenerAdaptor.java0100644 0000000 0000000 00000005235 14603604450 034017 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 { /** * Directory changed Event. * * @param directory The directory changed (ignored) */ @Override public void onDirectoryChange(final File directory) { // noop } /** * Directory created Event. * * @param directory The directory created (ignored) */ @Override public void onDirectoryCreate(final File directory) { // noop } /** * Directory deleted Event. * * @param directory The directory deleted (ignored) */ @Override public void onDirectoryDelete(final File directory) { // noop } /** * File changed Event. * * @param file The file changed (ignored) */ @Override public void onFileChange(final File file) { // noop } /** * File created Event. * * @param file The file created (ignored) */ @Override public void onFileCreate(final File file) { // noop } /** * File deleted Event. * * @param file The file deleted (ignored) */ @Override public void onFileDelete(final File file) { // noop } /** * File system observer started checking event. * * @param observer The file system observer (ignored) */ @Override public void onStart(final FileAlterationObserver observer) { // 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.16.1-src/src/main/java/org/apache/commons/io/monitor/FileAlterationMonitor.java0100644 0000000 0000000 00000015106 14603604450 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.monitor; import java.time.Duration; import java.util.ArrayList; 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; import java.util.stream.Stream; import org.apache.commons.io.ThreadUtils; /** * 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 intervalMillis; 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(10_000); } /** * Constructs a monitor with the specified interval. * * @param intervalMillis The amount of time in milliseconds to wait between * checks of the file system. */ public FileAlterationMonitor(final long intervalMillis) { this.intervalMillis = intervalMillis; } /** * 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) { Stream.of(observers).forEach(this::addObserver); } } /** * 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); } } /** * Returns the interval. * * @return the interval */ public long getInterval() { return intervalMillis; } /** * Returns the set of {@link FileAlterationObserver} registered with * this monitor. * * @return The set of {@link FileAlterationObserver} */ public Iterable getObservers() { return new ArrayList<>(observers); } /** * 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) { observers.removeIf(observer::equals); } } /** * Runs this monitor. */ @Override public void run() { while (running) { observers.forEach(FileAlterationObserver::checkAndNotify); if (!running) { break; } try { ThreadUtils.sleep(Duration.ofMillis(intervalMillis)); } catch (final InterruptedException ignored) { // ignore } } } /** * Sets the thread factory. * * @param threadFactory the thread factory */ public synchronized void setThreadFactory(final ThreadFactory threadFactory) { this.threadFactory = threadFactory; } /** * 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(intervalMillis); } /** * 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(); } } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/monitor/FileAlterationObserver.java0100644 0000000 0000000 00000042005 14603604450 032502 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.List; import java.util.Objects; import java.util.concurrent.CopyOnWriteArrayList; import java.util.stream.Stream; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOCase; import org.apache.commons.io.comparator.NameFileComparator; import org.apache.commons.io.filefilter.TrueFileFilter; /** * 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(FileUtils.current(), "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. *

*

Deprecating Serialization

*

* Serialization is deprecated and will be removed in 3.0. *

* * @see FileAlterationListener * @see FileAlterationMonitor * @since 2.0 */ public class FileAlterationObserver implements Serializable { private static final long serialVersionUID = 1185122225658782848L; private static Comparator toComparator(final IOCase ioCase) { switch (IOCase.value(ioCase, IOCase.SYSTEM)) { case SYSTEM: return NameFileComparator.NAME_SYSTEM_COMPARATOR; case INSENSITIVE: return NameFileComparator.NAME_INSENSITIVE_COMPARATOR; default: return NameFileComparator.NAME_COMPARATOR; } } /** * List of listeners. */ private transient final List listeners = new CopyOnWriteArrayList<>(); /** * The root directory to observe. */ private final FileEntry rootEntry; /** * The file filter or null if none. */ private transient final FileFilter fileFilter; /** * Compares file names. */ private final Comparator comparator; /** * 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 ioCase what case sensitivity to use comparing file names, null means system sensitive. */ public FileAlterationObserver(final File directory, final FileFilter fileFilter, final IOCase ioCase) { this(new FileEntry(directory), fileFilter, ioCase); } /** * 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 comparator how to compare files. */ private FileAlterationObserver(final FileEntry rootEntry, final FileFilter fileFilter, final Comparator comparator) { Objects.requireNonNull(rootEntry, "rootEntry"); Objects.requireNonNull(rootEntry.getFile(), "rootEntry.getFile()"); this.rootEntry = rootEntry; this.fileFilter = fileFilter != null ? fileFilter : TrueFileFilter.INSTANCE; this.comparator = Objects.requireNonNull(comparator, "comparator"); } /** * 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 ioCase what case sensitivity to use comparing file names, null means system sensitive. */ protected FileAlterationObserver(final FileEntry rootEntry, final FileFilter fileFilter, final IOCase ioCase) { this(rootEntry, fileFilter, toComparator(ioCase)); } /** * 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); } /** * Constructs 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 ioCase what case sensitivity to use comparing file names, null means system sensitive. */ public FileAlterationObserver(final String directoryName, final FileFilter fileFilter, final IOCase ioCase) { this(new File(directoryName), fileFilter, ioCase); } /** * Adds a file system listener. * * @param listener The file system listener. */ public void addListener(final FileAlterationListener listener) { if (listener != null) { listeners.add(listener); } } /** * Compares two file lists for files which have been created, modified or deleted. * * @param parentEntry The parent entry. * @param previousEntries The original list of file entries. * @param currentEntries The current list of files entries. */ private void checkAndFire(final FileEntry parentEntry, final FileEntry[] previousEntries, final File[] currentEntries) { int c = 0; final FileEntry[] actualEntries = currentEntries.length > 0 ? new FileEntry[currentEntries.length] : FileEntry.EMPTY_FILE_ENTRY_ARRAY; for (final FileEntry previousEntry : previousEntries) { while (c < currentEntries.length && comparator.compare(previousEntry.getFile(), currentEntries[c]) > 0) { actualEntries[c] = createFileEntry(parentEntry, currentEntries[c]); fireOnCreate(actualEntries[c]); c++; } if (c < currentEntries.length && comparator.compare(previousEntry.getFile(), currentEntries[c]) == 0) { fireOnChange(previousEntry, currentEntries[c]); checkAndFire(previousEntry, previousEntry.getChildren(), listFiles(currentEntries[c])); actualEntries[c] = previousEntry; c++; } else { checkAndFire(previousEntry, previousEntry.getChildren(), FileUtils.EMPTY_FILE_ARRAY); fireOnDelete(previousEntry); } } for (; c < currentEntries.length; c++) { actualEntries[c] = createFileEntry(parentEntry, currentEntries[c]); fireOnCreate(actualEntries[c]); } parentEntry.setChildren(actualEntries); } /** * Checks whether the file and its children have been created, modified or deleted. */ public void checkAndNotify() { // fire onStart() listeners.forEach(listener -> listener.onStart(this)); // fire directory/file events final File rootFile = rootEntry.getFile(); if (rootFile.exists()) { checkAndFire(rootEntry, rootEntry.getChildren(), listFiles(rootFile)); } else if (rootEntry.isExists()) { checkAndFire(rootEntry, rootEntry.getChildren(), FileUtils.EMPTY_FILE_ARRAY); } // Else: Didn't exist and still doesn't // fire onStop() listeners.forEach(listener -> listener.onStop(this)); } /** * Creates a new file entry for the specified file. * * @param parent The parent file entry. * @param file The file to wrap. * @return A new file entry. */ private FileEntry createFileEntry(final FileEntry parent, final File file) { final FileEntry entry = parent.newChildInstance(file); entry.refresh(file); entry.setChildren(listFileEntries(file, entry)); return entry; } /** * Final processing. * * @throws Exception if an error occurs. */ @SuppressWarnings("unused") // Possibly thrown from subclasses. public void destroy() throws Exception { // noop } /** * Fires directory/file change events to the registered listeners. * * @param entry The previous file system entry. * @param file The current file. */ private void fireOnChange(final FileEntry entry, final File file) { if (entry.refresh(file)) { listeners.forEach(listener -> { if (entry.isDirectory()) { listener.onDirectoryChange(file); } else { listener.onFileChange(file); } }); } } /** * Fires directory/file created events to the registered listeners. * * @param entry The file entry. */ private void fireOnCreate(final FileEntry entry) { listeners.forEach(listener -> { if (entry.isDirectory()) { listener.onDirectoryCreate(entry.getFile()); } else { listener.onFileCreate(entry.getFile()); } }); Stream.of(entry.getChildren()).forEach(this::fireOnCreate); } /** * Fires directory/file delete events to the registered listeners. * * @param entry The file entry. */ private void fireOnDelete(final FileEntry entry) { listeners.forEach(listener -> { if (entry.isDirectory()) { listener.onDirectoryDelete(entry.getFile()); } else { listener.onFileDelete(entry.getFile()); } }); } /** * 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; } /** * Returns the set of registered file system listeners. * * @return The file system listeners */ public Iterable getListeners() { return new ArrayList<>(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()); rootEntry.setChildren(listFileEntries(rootEntry.getFile(), rootEntry)); } /** * Lists the file entries in {@code file}. * * @param file The directory to list. * @param entry the parent entry. * @return The child file entries. */ private FileEntry[] listFileEntries(final File file, final FileEntry entry) { return Stream.of(listFiles(file)).map(f -> createFileEntry(entry, f)).toArray(FileEntry[]::new); } /** * Lists the contents of a directory. * * @param directory The directory to list. * @return the directory contents or a zero length array if the empty or the file is not a directory */ private File[] listFiles(final File directory) { return directory.isDirectory() ? sort(directory.listFiles(fileFilter)) : FileUtils.EMPTY_FILE_ARRAY; } /** * Removes a file system listener. * * @param listener The file system listener. */ public void removeListener(final FileAlterationListener listener) { if (listener != null) { listeners.removeIf(listener::equals); } } private File[] sort(final File[] files) { if (files == null) { return FileUtils.EMPTY_FILE_ARRAY; } if (files.length > 1) { Arrays.sort(files, comparator); } return files; } /** * 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('\''); builder.append(", "); builder.append(fileFilter.toString()); builder.append(", listeners="); builder.append(listeners.size()); builder.append("]"); return builder.toString(); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/monitor/FileEntry.java0100644 0000000 0000000 00000021603 14603604450 027772 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 java.nio.file.attribute.FileTime; import java.util.Objects; import org.apache.commons.io.FileUtils; import org.apache.commons.io.file.attribute.FileTimes; /** * 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. *

*

Deprecating Serialization

*

* Serialization is deprecated and will be removed in 3.0. *

* @see FileAlterationObserver * @since 2.0 */ public class FileEntry implements Serializable { private static final long serialVersionUID = -2505664948818681153L; static final FileEntry[] EMPTY_FILE_ENTRY_ARRAY = {}; /** The parent. */ private final FileEntry parent; /** My children. */ private FileEntry[] children; /** Monitored file. */ private final File file; /** Monitored file name. */ private String name; /** Whether the file exists. */ private boolean exists; /** Whether the file is a directory or not. */ private boolean directory; /** The file's last modified timestamp. */ private SerializableFileTime lastModified = SerializableFileTime.EPOCH; /** The file's length. */ private long length; /** * Constructs a new monitor for a specified {@link File}. * * @param file The file being monitored */ public FileEntry(final File file) { this(null, file); } /** * Constructs 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) { this.file = Objects.requireNonNull(file, "file"); this.parent = parent; this.name = file.getName(); } /** * Gets 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; } /** * Gets the file being monitored. * * @return the file being monitored */ public File getFile() { return file; } /** * Gets the last modified time from the last time it * was checked. * * @return the last modified time in milliseconds. */ public long getLastModified() { return lastModified.toMillis(); } /** * Gets the last modified time from the last time it was checked. * * @return the last modified time. * @since 2.12.0 */ public FileTime getLastModifiedFileTime() { return lastModified.unwrap(); } /** * Gets the length. * * @return the length */ public long getLength() { return length; } /** * Gets the level * * @return the level */ public int getLevel() { return parent == null ? 0 : parent.getLevel() + 1; } /** * Gets the file name. * * @return the file name */ public String getName() { return name; } /** * Gets the parent entry. * * @return the parent entry */ public FileEntry getParent() { return parent; } /** * Tests whether the file is a directory or not. * * @return whether the file is a directory or not */ public boolean isDirectory() { return directory; } /** * Tests whether the file existed the last time it * was checked. * * @return whether the file existed */ public boolean isExists() { return exists; } /** * Constructs 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); } /** * Refreshes 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 SerializableFileTime 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 { setLastModified(exists ? FileUtils.lastModifiedFileTime(file) : FileTimes.EPOCH); } catch (final IOException e) { setLastModified(SerializableFileTime.EPOCH); } length = exists && !directory ? file.length() : 0; // Return if there are changes return exists != origExists || !lastModified.equals(origLastModified) || directory != origDirectory || length != origLength; } /** * Sets the directory's files. * * @param children This directory's files, may be null */ public void setChildren(final FileEntry... children) { this.children = children; } /** * Sets 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; } /** * Sets 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; } /** * Sets the last modified time from the last time it was checked. * * @param lastModified The last modified time. * @since 2.12.0 */ public void setLastModified(final FileTime lastModified) { setLastModified(new SerializableFileTime(lastModified)); } /** * Sets the last modified time from the last time it * was checked. * * @param lastModified The last modified time in milliseconds. */ public void setLastModified(final long lastModified) { setLastModified(FileTime.fromMillis(lastModified)); } void setLastModified(final SerializableFileTime lastModified) { this.lastModified = lastModified; } /** * Sets the length. * * @param length the length */ public void setLength(final long length) { this.length = length; } /** * Sets the file name. * * @param name the file name */ public void setName(final String name) { this.name = name; } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/monitor/SerializableFileTime.java0100644 0000000 0000000 00000005533 14603604450 032122 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.nio.file.attribute.FileTime; import java.time.Instant; import java.util.Objects; import java.util.concurrent.TimeUnit; import org.apache.commons.io.file.attribute.FileTimes; /** * Wraps a {@link FileTime} and allows it to be Serializable. * *

Deprecating Serialization

*

* Serialization is deprecated and will be removed in 3.0. *

*/ final class SerializableFileTime implements Serializable { static final SerializableFileTime EPOCH = new SerializableFileTime(FileTimes.EPOCH); private static final long serialVersionUID = 1L; private FileTime fileTime; public SerializableFileTime(final FileTime fileTime) { this.fileTime = Objects.requireNonNull(fileTime); } public int compareTo(final FileTime other) { return fileTime.compareTo(other); } @Override public boolean equals(final Object obj) { if (this == obj) { return true; } if (!(obj instanceof SerializableFileTime)) { return false; } final SerializableFileTime other = (SerializableFileTime) obj; return Objects.equals(fileTime, other.fileTime); } @Override public int hashCode() { return fileTime.hashCode(); } private void readObject(final ObjectInputStream ois) throws ClassNotFoundException, IOException { this.fileTime = FileTime.from((Instant) ois.readObject()); } long to(final TimeUnit unit) { return fileTime.to(unit); } Instant toInstant() { return fileTime.toInstant(); } long toMillis() { return fileTime.toMillis(); } @Override public String toString() { return fileTime.toString(); } FileTime unwrap() { return fileTime; } private void writeObject(final ObjectOutputStream oos) throws IOException { oos.writeObject(fileTime.toInstant()); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/monitor/package-info.java0100644 0000000 0000000 00000001704 14603604450 030415 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Provides a component for monitoring file system events (directory and file create, update and delete events). */ package org.apache.commons.io.monitor; commons-io-2.16.1-src/src/main/java/org/apache/commons/io/output/AbstractByteArrayOutputStream.java0100644 0000000 0000000 00000034127 14603604450 033732 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.IOUtils.EOF; import java.io.IOException; import java.io.InputStream; 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 org.apache.commons.io.IOUtils; import org.apache.commons.io.input.ClosedInputStream; /** * 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 {@link AbstractByteArrayOutputStream} has no effect. The methods in * this class can be called after the stream has been closed without * generating an {@link 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 { /** * Constructor for an InputStream subclass. * * @param the type of the InputStream. */ @FunctionalInterface protected interface InputStreamConstructor { /** * Constructs an InputStream subclass. * * @param buffer the buffer * @param offset the offset into the buffer * @param length the length of the buffer * * @return the InputStream subclass. */ T construct(final byte[] buffer, final int offset, final int length); } 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; /** * Does nothing. * * The methods in this class can be called after the stream has been closed without generating an {@link 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 } /** * 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); } } /** * See {@link ByteArrayOutputStream#reset()}. * * @see ByteArrayOutputStream#reset() */ public abstract void reset(); /** * Implements a default reset behavior. * * @see 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; } } /** * Returns the current size of the byte array. * * @return the current size of the byte array */ public abstract int size(); /** * 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 an 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 an 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.INSTANCE; } 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)); } /** * 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 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 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); } /** * 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); } @Override public abstract void write(final byte[] b, final int off, final int len); /** * Writes the entire contents of the specified input stream to this * byte stream. Bytes from the input stream are read directly into the * internal buffer of this stream. * * @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; @Override public abstract void write(final int b); /** * 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; } /** * Writes the entire contents of the specified input stream to this * byte stream. Bytes from the input stream are read directly into the * internal buffer of this stream. * * @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; } /** * 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 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; } } } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/output/AppendableOutputStream.java0100644 0000000 0000000 00000003771 14603604450 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.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 StringBuilder} * or {@link StringBuffer}. *

* * @since 2.5 * @see Appendable * * @param The type of the {@link Appendable} wrapped by this AppendableOutputStream. */ public class AppendableOutputStream extends OutputStream { private final T appendable; /** * Constructs a new instance with the specified appendable. * * @param appendable the appendable to write to */ public AppendableOutputStream(final T appendable) { this.appendable = appendable; } /** * Gets the target appendable. * * @return the target appendable */ public T getAppendable() { return 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); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/output/AppendableWriter.java0100644 0000000 0000000 00000011726 14603604450 031177 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 StringBuilder} * or {@link StringBuffer}. *

* * @since 2.7 * @see 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 } /** * Gets 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.16.1-src/src/main/java/org/apache/commons/io/output/BrokenOutputStream.java0100644 0000000 0000000 00000007176 14603604450 031570 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.util.function.Supplier; import org.apache.commons.io.function.Erase; /** * Always throws an exception from all {@link OutputStream} methods where {@link IOException} is declared. *

* This class is mostly useful for testing error handling. *

* * @since 2.0 */ public class BrokenOutputStream extends OutputStream { /** * The singleton instance using a default IOException. * * @since 2.12.0 */ public static final BrokenOutputStream INSTANCE = new BrokenOutputStream(); /** * Supplies the exception that is thrown by all methods of this class. */ private final Supplier exceptionSupplier; /** * Constructs a new stream that always throws an {@link IOException}. */ public BrokenOutputStream() { this(() -> new IOException("Broken output stream")); } /** * Constructs a new stream that always throws the given exception. * * @param exception the exception to be thrown. * @deprecated Use {@link #BrokenOutputStream(Throwable)}. */ @Deprecated public BrokenOutputStream(final IOException exception) { this(() -> exception); } /** * Constructs a new stream that always throws the supplied exception. * * @param exceptionSupplier a supplier for the IOException or RuntimeException to be thrown. * @since 2.12.0 */ public BrokenOutputStream(final Supplier exceptionSupplier) { this.exceptionSupplier = exceptionSupplier; } /** * Constructs a new stream that always throws the given exception. * * @param exception the exception to be thrown. * @since 2.16.0 */ public BrokenOutputStream(final Throwable exception) { this(() -> exception); } /** * Throws the configured exception. * * @throws IOException always throws the exception configured in a constructor. */ @Override public void close() throws IOException { throw rethrow(); } /** * Throws the configured exception. * * @throws IOException always throws the exception configured in a constructor. */ @Override public void flush() throws IOException { throw rethrow(); } /** * Throws the configured exception from its supplier. * * @return Throws the configured exception from its supplier. */ private RuntimeException rethrow() { return Erase.rethrow(exceptionSupplier.get()); } /** * Throws the configured exception. * * @param b ignored. * @throws IOException always throws the exception configured in a constructor. */ @Override public void write(final int b) throws IOException { throw rethrow(); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/output/BrokenWriter.java0100644 0000000 0000000 00000007224 14603604450 030362 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.function.Supplier; import org.apache.commons.io.function.Erase; /** * Always throws an exception from all {@link Writer} methods where {@link IOException} is declared. *

* This class is mostly useful for testing error handling. *

* * @since 2.0 */ public class BrokenWriter extends Writer { /** * The singleton instance using a default IOException. * * @since 2.12.0 */ public static final BrokenWriter INSTANCE = new BrokenWriter(); /** * Supplies the exception that is thrown by all methods of this class. */ private final Supplier exceptionSupplier; /** * Constructs a new writer that always throws an {@link IOException}. */ public BrokenWriter() { this(() -> new IOException("Broken writer")); } /** * Constructs a new writer that always throws the given exception. * * @param exception the exception to be thrown. * @deprecated Use {@link #BrokenWriter(Throwable)}. */ @Deprecated public BrokenWriter(final IOException exception) { this(() -> exception); } /** * Constructs a new writer that always throws the supplied exception. * * @param exceptionSupplier a supplier for the IOException or RuntimeException to be thrown. * @since 2.12.0 */ public BrokenWriter(final Supplier exceptionSupplier) { this.exceptionSupplier = exceptionSupplier; } /** * Constructs a new writer that always throws the given exception. * * @param exception the exception to be thrown. * @since 2.16.0 */ public BrokenWriter(final Throwable exception) { this(() -> exception); } /** * Throws the configured exception. * * @throws IOException always throws the exception configured in a constructor. */ @Override public void close() throws IOException { throw rethrow(); } /** * Throws the configured exception. * * @throws IOException always throws the exception configured in a constructor. */ @Override public void flush() throws IOException { throw rethrow(); } /** * Throws the configured exception from its supplier. * * @return Throws the configured exception from its supplier. */ private RuntimeException rethrow() { return Erase.rethrow(exceptionSupplier.get()); } /** * Throws the configured exception. * * @param cbuf ignored. * @param off ignored. * @param len ignored. * @throws IOException always throws the exception configured in a constructor. */ @Override public void write(final char[] cbuf, final int off, final int len) throws IOException { throw rethrow(); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/output/ByteArrayOutputStream.java0100644 0000000 0000000 00000012317 14603604450 032243 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.BufferedInputStream; 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 { /** * Fetches entire contents of an {@link 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 * {@link 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 {@link 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 * {@link 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 (ByteArrayOutputStream output = new ByteArrayOutputStream(size)) { output.write(input); return output.toInputStream(); } } /** * Constructs 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); } /** * Constructs 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); } } /** * @see java.io.ByteArrayOutputStream#reset() */ @Override public synchronized void reset() { resetImpl(); } @Override public synchronized int size() { return count; } @Override public synchronized byte[] toByteArray() { return toByteArrayImpl(); } @Override public synchronized InputStream toInputStream() { return toInputStream(java.io.ByteArrayInputStream::new); } @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 int write(final InputStream in) throws IOException { return writeImpl(in); } @Override public synchronized void write(final int b) { writeImpl(b); } @Override public synchronized void writeTo(final OutputStream out) throws IOException { writeToImpl(out); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/output/ChunkedOutputStream.java0100644 0000000 0000000 00000011617 14603604450 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; import org.apache.commons.io.IOUtils; import org.apache.commons.io.build.AbstractStreamBuilder; /** * 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. *

* To build an instance, see {@link Builder} *

* * @see Builder * @since 2.5 */ public class ChunkedOutputStream extends FilterOutputStream { // @formatter:off /** * Builds a new {@link UnsynchronizedByteArrayOutputStream}. * *

* Using File IO: *

*
{@code
     * UnsynchronizedByteArrayOutputStream s = UnsynchronizedByteArrayOutputStream.builder()
     *   .setBufferSize(8192)
     *   .get();
     * }
     * 
*

* Using NIO Path: *

*
{@code
     * UnsynchronizedByteArrayOutputStream s = UnsynchronizedByteArrayOutputStream.builder()
     *   .setBufferSize(8192)
     *   .get();
     * }
     * 
* * @see #get() * @since 2.13.0 */ // @formatter:on public static class Builder extends AbstractStreamBuilder { /** * Builds a new {@link UnsynchronizedByteArrayOutputStream}. *

* This builder use the following aspects: *

*
    *
  • {@link #getInputStream()}
  • *
  • {@link #getBufferSize()} (chunk size)
  • *
* * @return a new instance. * @throws IllegalStateException if the {@code origin} is {@code null}. * @throws UnsupportedOperationException if the origin cannot be converted to an {@link OutputStream}. * @throws IOException if an I/O error occurs. * @see #getOutputStream() * @see #getBufferSize() */ @Override public ChunkedOutputStream get() throws IOException { return new ChunkedOutputStream(getOutputStream(), getBufferSize()); } } /** * Constructs a new {@link Builder}. * * @return a new {@link Builder}. * @since 2.13.0 */ public static Builder builder() { return new Builder(); } /** * The maximum chunk size to us when writing data arrays */ private final int chunkSize; /** * Constructs a new stream that uses a chunk size of {@link IOUtils#DEFAULT_BUFFER_SIZE}. * * @param stream the stream to wrap * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated public ChunkedOutputStream(final OutputStream stream) { this(stream, IOUtils.DEFAULT_BUFFER_SIZE); } /** * Constructs 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 * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated public ChunkedOutputStream(final OutputStream stream, final int chunkSize) { super(stream); if (chunkSize <= 0) { throw new IllegalArgumentException("chunkSize <= 0"); } this.chunkSize = chunkSize; } int getChunkSize() { return chunkSize; } /** * 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.16.1-src/src/main/java/org/apache/commons/io/output/ChunkedWriter.java0100644 0000000 0000000 00000005424 14603604450 030523 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; /** * 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 = IOUtils.DEFAULT_BUFFER_SIZE; /** * The maximum chunk size to us when writing data arrays */ private final int chunkSize; /** * Constructs 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); } /** * Constructs 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; } /** * 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.16.1-src/src/main/java/org/apache/commons/io/output/CloseShieldOutputStream.java0100644 0000000 0000000 00000004527 14603604450 032543 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 { /** * Constructs 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); } /** * Constructs 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.INSTANCE; } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/output/CloseShieldWriter.java0100644 0000000 0000000 00000004252 14603604450 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.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 { /** * Constructs 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); } /** * Constructs 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.INSTANCE; } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/output/ClosedOutputStream.java0100644 0000000 0000000 00000005026 14603604450 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.output; import java.io.IOException; import java.io.OutputStream; /** * Throws an IOException 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 { /** * The singleton instance. * * @since 2.12.0 */ public static final ClosedOutputStream INSTANCE = new ClosedOutputStream(); /** * The singleton instance. * * @deprecated Use {@link #INSTANCE}. */ @Deprecated public static final ClosedOutputStream CLOSED_OUTPUT_STREAM = INSTANCE; /** * 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"); } /** * Throws an {@link IOException} to indicate that the stream is closed. * * @param b ignored * @param off ignored * @param len ignored * @throws IOException always thrown */ @Override public void write(final byte b[], final int off, final int len) throws IOException { throw new IOException("write(byte[], int, int) failed: stream is closed"); } /** * 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(int) failed: stream is closed"); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/output/ClosedWriter.java0100644 0000000 0000000 00000004473 14603604450 030356 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 IOException 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 { /** * The singleton instance. * * @since 2.12.0 */ public static final ClosedWriter INSTANCE = new ClosedWriter(); /** * The singleton instance. * * @deprecated Use {@link #INSTANCE}. */ @Deprecated public static final ClosedWriter CLOSED_WRITER = INSTANCE; @Override public void close() throws IOException { // noop } /** * 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"); } /** * 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"); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/output/CountingOutputStream.java0100644 0000000 0000000 00000007710 14603604450 032130 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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: 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; } /** * Gets 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; } /** * Sets 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; } /** * Sets 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; } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/output/DeferredFileOutputStream.java0100644 0000000 0000000 00000046126 14603604450 032666 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 java.nio.file.Path; import java.util.Objects; import java.util.function.Supplier; import org.apache.commons.io.build.AbstractStreamBuilder; import org.apache.commons.io.file.PathUtils; /** * 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. *

* To build an instance, use {@link Builder}. *

*

* The caller is responsible for deleting the output file ({@link #getFile()}, {@link #getPath()}) created by a DeferredFileOutputStream when the caller only * configured a prefix. *

*

* The caller is responsible for deleting the output file passed to a constructor or builder through {@link Builder#setOutputFile(File)} or * {@link Builder#setOutputFile(Path)}. *

*

* 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). *

* * @see Builder */ public class DeferredFileOutputStream extends ThresholdingOutputStream { // @formatter:off /** * Builds a new {@link DeferredFileOutputStream}. *

* For example: *

*
{@code
     * DeferredFileOutputStream s = DeferredFileOutputStream.builder()
     *   .setBufferSize(4096)
     *   .setDirectory(dir)
     *   .setOutputFile(outputFile)
     *   .setPrefix(prefix)
     *   .setSuffix(suffix)
     *   .setThreshold(threshold)
     *   .get();}
     * 
*

* The only super's aspect used us buffer size. *

* * @see #get() * @since 2.12.0 */ // @formatter:on public static class Builder extends AbstractStreamBuilder { private int threshold; private Path outputFile; private String prefix; private String suffix; private Path directory; /** * Constructs a new builder. */ public Builder() { setBufferSizeDefault(AbstractByteArrayOutputStream.DEFAULT_SIZE); setBufferSize(AbstractByteArrayOutputStream.DEFAULT_SIZE); } /** * Builds a new {@link DeferredFileOutputStream}. *

* This builder use the following aspects: *

*
    *
  • {@link #getBufferSize()}
  • *
  • threshold
  • *
  • outputFile
  • *
  • prefix
  • *
  • suffix
  • *
  • directory
  • *
* * @return a new instance. */ @Override public DeferredFileOutputStream get() { return new DeferredFileOutputStream(threshold, outputFile, prefix, suffix, directory, getBufferSize()); } /** * Sets the temporary file directory. * * @param directory Temporary file directory. * @return this */ public Builder setDirectory(final File directory) { this.directory = toPath(directory, null); return this; } /** * Sets the temporary file directory. * * @param directory Temporary file directory. * @return this * @since 2.14.0 */ public Builder setDirectory(final Path directory) { this.directory = toPath(directory, null); return this; } /** * Sets the file to which data is saved beyond the threshold. * * @param outputFile The file to which data is saved beyond the threshold. * @return this */ public Builder setOutputFile(final File outputFile) { this.outputFile = toPath(outputFile, null); return this; } /** * Sets the file to which data is saved beyond the threshold. * * @param outputFile The file to which data is saved beyond the threshold. * @return this * @since 2.14.0 */ public Builder setOutputFile(final Path outputFile) { this.outputFile = toPath(outputFile, null); return this; } /** * Sets the prefix to use for the temporary file. * * @param prefix Prefix to use for the temporary file. * @return this */ public Builder setPrefix(final String prefix) { this.prefix = prefix; return this; } /** * Sets the suffix to use for the temporary file. * * @param suffix Suffix to use for the temporary file. * @return this */ public Builder setSuffix(final String suffix) { this.suffix = suffix; return this; } /** * Sets the number of bytes at which to trigger an event. * * @param threshold The number of bytes at which to trigger an event. * @return this */ public Builder setThreshold(final int threshold) { this.threshold = threshold; return this; } } /** * Constructs a new {@link Builder}. * * @return a new {@link Builder}. * @since 2.12.0 */ public static Builder builder() { return new Builder(); } private static int checkBufferSize(final int initialBufferSize) { if (initialBufferSize < 0) { throw new IllegalArgumentException("Initial buffer size must be at least 0."); } return initialBufferSize; } private static Path toPath(final File file, final Supplier defaultPathSupplier) { return file != null ? file.toPath() : defaultPathSupplier == null ? null : defaultPathSupplier.get(); } private static Path toPath(final Path file, final Supplier defaultPathSupplier) { return file != null ? file : defaultPathSupplier == null ? null : defaultPathSupplier.get(); } /** * 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 Path outputPath; /** * 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 Path 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. * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated 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. * @throws IllegalArgumentException if initialBufferSize < 0. */ private DeferredFileOutputStream(final int threshold, final File outputFile, final String prefix, final String suffix, final File directory, final int initialBufferSize) { super(threshold); this.outputPath = toPath(outputFile, null); this.prefix = prefix; this.suffix = suffix; this.directory = toPath(directory, PathUtils::getTempDirectory); this.memoryOutputStream = new ByteArrayOutputStream(checkBufferSize(initialBufferSize)); this.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 * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated public DeferredFileOutputStream(final int threshold, final int initialBufferSize, final File outputFile) { this(threshold, outputFile, null, null, null, initialBufferSize); } /** * 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 * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated public DeferredFileOutputStream(final int threshold, final int initialBufferSize, final String prefix, final String suffix, final File directory) { this(threshold, null, Objects.requireNonNull(prefix, "prefix"), suffix, directory, initialBufferSize); } /** * 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. * @throws IllegalArgumentException if initialBufferSize < 0. */ private DeferredFileOutputStream(final int threshold, final Path outputFile, final String prefix, final String suffix, final Path directory, final int initialBufferSize) { super(threshold); this.outputPath = toPath(outputFile, null); this.prefix = prefix; this.suffix = suffix; this.directory = toPath(directory, PathUtils::getTempDirectory); this.memoryOutputStream = new ByteArrayOutputStream(checkBufferSize(initialBufferSize)); this.currentOutputStream = memoryOutputStream; } /** * 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 * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated public DeferredFileOutputStream(final int threshold, final String prefix, final String suffix, final File directory) { this(threshold, null, Objects.requireNonNull(prefix, "prefix"), suffix, directory, AbstractByteArrayOutputStream.DEFAULT_SIZE); } /** * 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; } /** * Gets 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; } /** * Gets 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 outputPath != null ? outputPath.toFile() : null; } /** * Gets either the output Path specified in the constructor or the temporary Path created or null. *

* If the constructor specifying the file is used then it returns that same output Path, even when threshold has not been reached. *

*

* If constructor specifying a temporary Path prefix/suffix is used then the temporary Path created once the threshold is reached is returned if the * threshold was not reached then {@code null} is returned. *

* * @return The Path for this output stream, or {@code null} if no such Path exists. * @since 2.14.0 */ public Path getPath() { return outputPath; } /** * Gets 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; } /** * Tests 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) { outputPath = Files.createTempFile(directory, prefix, suffix); } PathUtils.createParentDirectories(outputPath, null, PathUtils.EMPTY_FILE_ATTRIBUTE_ARRAY); final OutputStream fos = Files.newOutputStream(outputPath); try { memoryOutputStream.writeTo(fos); } catch (final IOException e) { fos.close(); throw e; } currentOutputStream = fos; memoryOutputStream = null; } /** * Converts the current contents of this byte stream to 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(outputPath); } /** * 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 { Files.copy(outputPath, outputStream); } } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/output/DemuxOutputStream.java0100644 0000000 0000000 00000005321 14603604450 031420 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.16.1-src/src/main/java/org/apache/commons/io/output/FileWriterWithEncoding.java0100644 0000000 0000000 00000035261 14603604450 032326 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.FileWriter; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; import java.util.Objects; import org.apache.commons.io.Charsets; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.io.build.AbstractOrigin; import org.apache.commons.io.build.AbstractStreamBuilder; /** * Writer of files that allows the encoding to be set. *

* This class provides a simple alternative to {@link FileWriter} that allows an encoding to be set. Unfortunately, it cannot subclass {@link 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. *

*

* To build an instance, use {@link Builder}. *

* * @see Builder * @since 1.4 */ public class FileWriterWithEncoding extends ProxyWriter { // @formatter:off /** * Builds a new {@link FileWriterWithEncoding}. * *

* Using a CharsetEncoder: *

*
{@code
     * FileWriterWithEncoding w = FileWriterWithEncoding.builder()
     *   .setPath(path)
     *   .setAppend(false)
     *   .setCharsetEncoder(StandardCharsets.UTF_8.newEncoder())
     *   .get();}
     * 
*

* Using a Charset: *

*
{@code
     * FileWriterWithEncoding w = FileWriterWithEncoding.builder()
     *   .setPath(path)
     *   .setAppend(false)
     *   .setCharsetEncoder(StandardCharsets.UTF_8)
     *   .get();}
     * 
* * @see #get() * @since 2.12.0 */ // @formatter:on public static class Builder extends AbstractStreamBuilder { private boolean append; private CharsetEncoder charsetEncoder = super.getCharset().newEncoder(); /** * Builds a new {@link FileWriterWithEncoding}. *

* You must set input that supports {@link File} on this builder, otherwise, this method throws an exception. *

*

* This builder use the following aspects: *

*
    *
  • {@link File}
  • *
  • {@link CharsetEncoder}
  • *
  • append
  • *
* * @return a new instance. * @throws UnsupportedOperationException if the origin cannot provide a File. * @throws IllegalStateException if the {@code origin} is {@code null}. * @see AbstractOrigin#getFile() */ @SuppressWarnings("resource") @Override public FileWriterWithEncoding get() throws IOException { if (charsetEncoder != null && getCharset() != null && !charsetEncoder.charset().equals(getCharset())) { throw new IllegalStateException(String.format("Mismatched Charset(%s) and CharsetEncoder(%s)", getCharset(), charsetEncoder.charset())); } final Object encoder = charsetEncoder != null ? charsetEncoder : getCharset(); return new FileWriterWithEncoding(FileWriterWithEncoding.initWriter(checkOrigin().getFile(), encoder, append)); } /** * Sets whether or not to append. * * @param append Whether or not to append. * @return this */ public Builder setAppend(final boolean append) { this.append = append; return this; } /** * Sets charsetEncoder to use for encoding. * * @param charsetEncoder The charsetEncoder to use for encoding. * @return this */ public Builder setCharsetEncoder(final CharsetEncoder charsetEncoder) { this.charsetEncoder = charsetEncoder; return this; } } /** * Constructs a new {@link Builder}. * * @return Creates a new {@link Builder}. * @since 2.12.0 */ public static Builder builder() { return new Builder(); } /** * Initializes 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, null uses the default Charset. * @param append true to append * @return a new initialized OutputStreamWriter * @throws IOException if an error occurs */ private static OutputStreamWriter initWriter(final File file, final Object encoding, final boolean append) throws IOException { Objects.requireNonNull(file, "file"); OutputStream outputStream = null; final boolean fileExistedAlready = file.exists(); try { outputStream = FileUtils.newOutputStream(file, append); if (encoding == null || encoding instanceof Charset) { return new OutputStreamWriter(outputStream, Charsets.toCharset((Charset) encoding)); } if (encoding instanceof CharsetEncoder) { return new OutputStreamWriter(outputStream, (CharsetEncoder) encoding); } return new OutputStreamWriter(outputStream, (String) encoding); } catch (final IOException | RuntimeException ex) { try { IOUtils.close(outputStream); } catch (final IOException e) { ex.addSuppressed(e); } if (!fileExistedAlready) { FileUtils.deleteQuietly(file); } throw ex; } } /** * 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 * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated 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, null uses the default Charset. * @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. * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated @SuppressWarnings("resource") // Call site is responsible for closing a new instance. public FileWriterWithEncoding(final File file, final Charset encoding, final boolean append) throws IOException { this(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 * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated 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, null uses the default Charset. * @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. * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated @SuppressWarnings("resource") // Call site is responsible for closing a new instance. public FileWriterWithEncoding(final File file, final CharsetEncoder charsetEncoder, final boolean append) throws IOException { this(initWriter(file, 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 * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated 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, null uses the default Charset. * @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. * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated @SuppressWarnings("resource") // Call site is responsible for closing a new instance. public FileWriterWithEncoding(final File file, final String charsetName, final boolean append) throws IOException { this(initWriter(file, charsetName, append)); } private FileWriterWithEncoding(final OutputStreamWriter outputStreamWriter) { super(outputStreamWriter); } /** * 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 * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated 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 * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated 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 * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated 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 * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated 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 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 * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated 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 * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated public FileWriterWithEncoding(final String fileName, final String charsetName, final boolean append) throws IOException { this(new File(fileName), charsetName, append); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/output/FilterCollectionWriter.java0100644 0000000 0000000 00000012525 14603604450 032403 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Objects; import java.util.stream.Stream; import org.apache.commons.io.IOExceptionList; import org.apache.commons.io.IOIndexedException; import org.apache.commons.io.function.IOConsumer; /** * 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; /** * Constructs 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; } /** * Constructs 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); } @Override public Writer append(final char c) throws IOException { return forAllWriters(w -> w.append(c)); } @Override public Writer append(final CharSequence csq) throws IOException { return forAllWriters(w -> w.append(csq)); } @Override public Writer append(final CharSequence csq, final int start, final int end) throws IOException { return forAllWriters(w -> w.append(csq, start, end)); } @SuppressWarnings("resource") // no allocation @Override public void close() throws IOException { forAllWriters(Writer::close); } /** * Flushes the stream. * * @throws IOException If an I/O error occurs */ @SuppressWarnings("resource") // no allocation @Override public void flush() throws IOException { forAllWriters(Writer::flush); } private FilterCollectionWriter forAllWriters(final IOConsumer action) throws IOExceptionList { IOConsumer.forAll(action, writers()); return this; } @SuppressWarnings("resource") // no allocation @Override public void write(final char[] cbuf) throws IOException { forAllWriters(w -> w.write(cbuf)); } /** * 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 * @throws IOException If an I/O error occurs */ @SuppressWarnings("resource") // no allocation @Override public void write(final char[] cbuf, final int off, final int len) throws IOException { forAllWriters(w -> w.write(cbuf, off, len)); } /** * Writes a single character. * * @throws IOException If an I/O error occurs */ @SuppressWarnings("resource") // no allocation @Override public void write(final int c) throws IOException { forAllWriters(w -> w.write(c)); } @SuppressWarnings("resource") // no allocation @Override public void write(final String str) throws IOException { forAllWriters(w -> w.write(str)); } /** * 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 * @throws IOException If an I/O error occurs */ @SuppressWarnings("resource") // no allocation @Override public void write(final String str, final int off, final int len) throws IOException { forAllWriters(w -> w.write(str, off, len)); } private Stream writers() { return writers.stream().filter(Objects::nonNull); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/output/LockableFileWriter.java0100644 0000000 0000000 00000041606 14603604450 031460 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.FileWriter; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.Writer; import java.nio.charset.Charset; import java.util.Objects; import org.apache.commons.io.Charsets; import org.apache.commons.io.FileUtils; import org.apache.commons.io.build.AbstractOrigin; import org.apache.commons.io.build.AbstractOriginSupplier; import org.apache.commons.io.build.AbstractStreamBuilder; /** * FileWriter that will create and honor lock files to allow simple cross thread file lock handling. *

* This class provides a simple alternative to {@link 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. *

*

* To build an instance, use {@link Builder}. *

* * @see Builder */ public class LockableFileWriter extends Writer { // @formatter:off /** * Builds a new {@link LockableFileWriter}. * *

* Using a CharsetEncoder: *

*
{@code
     * LockableFileWriter w = LockableFileWriter.builder()
     *   .setPath(path)
     *   .setAppend(false)
     *   .setLockDirectory("Some/Directory")
     *   .get();}
     * 
* * @see #get() * @since 2.12.0 */ // @formatter:on public static class Builder extends AbstractStreamBuilder { private boolean append; private AbstractOrigin lockDirectory = AbstractOriginSupplier.newFileOrigin(FileUtils.getTempDirectoryPath()); /** * Builds a new {@link LockableFileWriter}. */ public Builder() { setBufferSizeDefault(AbstractByteArrayOutputStream.DEFAULT_SIZE); setBufferSize(AbstractByteArrayOutputStream.DEFAULT_SIZE); } /** * Constructs a new instance. *

* You must set input that supports {@link File} on this builder, otherwise, this method throws an exception. *

*

* This builder use the following aspects: *

*
    *
  • {@link File}
  • *
  • {@link #getCharset()}
  • *
  • append
  • *
  • lockDirectory
  • *
* * @return a new instance. * @throws UnsupportedOperationException if the origin cannot provide a File. * @throws IllegalStateException if the {@code origin} is {@code null}. * @see AbstractOrigin#getFile() */ @Override public LockableFileWriter get() throws IOException { return new LockableFileWriter(checkOrigin().getFile(), getCharset(), append, lockDirectory.getFile().toString()); } /** * Sets whether to append (true) or overwrite (false). * * @param append whether to append (true) or overwrite (false). * @return this */ public Builder setAppend(final boolean append) { this.append = append; return this; } /** * Sets the directory in which the lock file should be held. * * @param lockDirectory the directory in which the lock file should be held. * @return this */ public Builder setLockDirectory(final File lockDirectory) { this.lockDirectory = AbstractOriginSupplier.newFileOrigin(lockDirectory != null ? lockDirectory : FileUtils.getTempDirectory()); return this; } /** * Sets the directory in which the lock file should be held. * * @param lockDirectory the directory in which the lock file should be held. * @return this */ public Builder setLockDirectory(final String lockDirectory) { this.lockDirectory = AbstractOriginSupplier.newFileOrigin(lockDirectory != null ? lockDirectory : FileUtils.getTempDirectoryPath()); return this; } } /** The extension for the lock file. */ private static final String LCK = ".lck"; // Cannot extend ProxyWriter, as requires writer to be // known when super() is called /** * Constructs a new {@link Builder}. * * @return a new {@link Builder}. * @since 2.12.0 */ public static Builder builder() { return new Builder(); } /** 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 file the file to write to, not null * @throws NullPointerException if the file is null * @throws IOException in case of an I/O error * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated 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 * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated 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 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 * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated 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 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 * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated public LockableFileWriter(final File file, final Charset charset, final boolean append, final String lockDir) throws IOException { // init file to create/append final File absFile = Objects.requireNonNull(file, "file").getAbsoluteFile(); if (absFile.getParentFile() != null) { FileUtils.forceMkdir(absFile.getParentFile()); } if (absFile.isDirectory()) { throw new IOException("File specified is a directory"); } // init lock file final File lockDirFile = new File(lockDir != null ? lockDir : FileUtils.getTempDirectoryPath()); FileUtils.forceMkdir(lockDirFile); testLockDir(lockDirFile); lockFile = new File(lockDirFile, absFile.getName() + LCK); // check if locked createLock(); // init wrapped writer out = initWriter(absFile, charset, append); } /** * 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. * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated 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 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. * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated public LockableFileWriter(final File file, final String charsetName, final boolean append, final String lockDir) throws IOException { this(file, Charsets.toCharset(charsetName), append, lockDir); } /** * 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 * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated 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 * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated 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 * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated public LockableFileWriter(final String fileName, final boolean append, final String lockDir) throws IOException { this(new File(fileName), append, lockDir); } /** * 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); } } /** * 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(); } } /** * Flushes the stream. * * @throws IOException if an I/O error occurs. */ @Override public void flush() throws IOException { out.flush(); } /** * 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; } } /** * 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()); } } /** * 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 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 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); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/output/NullAppendable.java0100644 0000000 0000000 00000003316 14603604450 030631 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 { // NOPMD Class will be final in 3.0. /** * 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.16.1-src/src/main/java/org/apache/commons/io/output/NullOutputStream.java0100644 0000000 0000000 00000004605 14603604450 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 java.io.IOException; import java.io.OutputStream; /** * Never writes data. Calls never go beyond this class. *

* This output stream has no destination (file/socket etc.) and all bytes written to it are ignored and lost. *

*/ public class NullOutputStream extends OutputStream { /** * The singleton instance. * * @since 2.12.0 */ public static final NullOutputStream INSTANCE = new NullOutputStream(); /** * The singleton instance. * * @deprecated Use {@link #INSTANCE}. */ @Deprecated public static final NullOutputStream NULL_OUTPUT_STREAM = INSTANCE; /** * Deprecated in favor of {@link #INSTANCE}. * * TODO: Will be private in 3.0. * * @deprecated Use {@link #INSTANCE}. */ @Deprecated public NullOutputStream() { } /** * 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 } /** * 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 } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/output/NullPrintStream.java0100644 0000000 0000000 00000003320 14603604450 031041 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; /** * Never prints data. Calls never go beyond this class. *

* 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. * * @since 2.12.0 */ public static final NullPrintStream INSTANCE = new NullPrintStream(); /** * The singleton instance. * * @deprecated Use {@link #INSTANCE}. */ @Deprecated public static final NullPrintStream NULL_PRINT_STREAM = INSTANCE; /** * Constructs an instance. * * @deprecated Use {@link #INSTANCE}. */ @Deprecated public NullPrintStream() { // Relies on the default charset which is OK since we are not actually writing. super(NullOutputStream.INSTANCE); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/output/NullWriter.java0100644 0000000 0000000 00000007566 14603604450 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.output; import java.io.Writer; /** * Never writes data. Calls never go beyond this class. *

* This {@link Writer} has no destination (file/socket etc.) and all characters written to it are ignored and lost. *

*/ public class NullWriter extends Writer { /** * The singleton instance. * * @since 2.12.0 */ public static final NullWriter INSTANCE = new NullWriter(); /** * The singleton instance. * * @deprecated Use {@link #INSTANCE}. */ @Deprecated public static final NullWriter NULL_WRITER = INSTANCE; /** * Constructs a new NullWriter. * * @deprecated Use {@link #INSTANCE}. */ @Deprecated 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 * @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 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; } /** @see java.io.Writer#close() */ @Override public void close() { //to /dev/null } /** @see java.io.Writer#flush() */ @Override public void flush() { //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 idx The character to write */ @Override public void write(final int idx) { //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 } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/output/ProxyCollectionWriter.java0100644 0000000 0000000 00000021624 14603604450 032277 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 { /** * Constructs a new proxy collection writer. * * @param writers Writers object to provide the underlying targets. */ public ProxyCollectionWriter(final Collection writers) { super(writers); } /** * Constructs 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 */ @SuppressWarnings("resource") // Fluent API. @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. */ @SuppressWarnings("resource") // Fluent API. @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. */ @SuppressWarnings("resource") // Fluent API. @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.16.1-src/src/main/java/org/apache/commons/io/output/ProxyOutputStream.java0100644 0000000 0000000 00000012752 14603604450 031465 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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' } /** * 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 } /** * 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 } /** * 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); } /** * 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); } } /** * 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; } /** * 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 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); } } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/output/ProxyWriter.java0100644 0000000 0000000 00000020434 14603604450 030261 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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' } /** * 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 } /** * 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)} 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 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; } /** * 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 } /** * 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); } /** * 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); } } /** * Handles 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; } /** * 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(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(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); } } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/output/QueueOutputStream.java0100644 0000000 0000000 00000007111 14603604450 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.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; import org.apache.commons.io.input.QueueInputStream; /** * 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 {@link QueueOutputStream} has no effect. The methods in this class can be called after the stream has been * closed without generating an {@link 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"); } /** * Constructs 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 QueueInputStream.builder().setBlockingQueue(blockingQueue).get(); } /** * 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.16.1-src/src/main/java/org/apache/commons/io/output/StringBuilderWriter.java0100644 0000000 0000000 00000011400 14603604450 031706 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 * {@link 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 * {@link java.io.StringWriter} should be used. *

*

Deprecating Serialization

*

* Serialization is deprecated and will be removed in 3.0. *

* @since 2.0 */ public class StringBuilderWriter extends Writer implements Serializable { private static final long serialVersionUID = -146927496096066153L; /** The append target. */ 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 } /** * Gets 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(); } /** * 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); } } /** * 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); } } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/output/TaggedOutputStream.java0100644 0000000 0000000 00000010010 14603604450 031520 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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(); /** * Constructs a tagging decorator for the given output stream. * * @param proxy output stream to be decorated */ public TaggedOutputStream(final OutputStream proxy) { super(proxy); } /** * 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); } /** * 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); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/output/TaggedWriter.java0100644 0000000 0000000 00000007674 14603604450 030346 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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(); /** * Constructs a tagging decorator for the given writer. * * @param proxy writer to be decorated */ public TaggedWriter(final Writer proxy) { super(proxy); } /** * 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); } /** * 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); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/output/TeeOutputStream.java0100644 0000000 0000000 00000006522 14603604450 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.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; } /** * 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(); } } /** * Flushes both streams. * * @throws IOException if an I/O error occurs. */ @Override public void flush() throws IOException { super.flush(); this.branch.flush(); } /** * 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); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/output/TeeWriter.java0100644 0000000 0000000 00000003177 14603604450 027662 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 { /** * Constructs a new filtered collection writer. * * @param writers Writers to provide the underlying targets. */ public TeeWriter(final Collection writers) { super(writers); } /** * Constructs a new filtered collection writer. * * @param writers Writers to provide the underlying targets. */ public TeeWriter(final Writer... writers) { super(writers); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/output/ThresholdingOutputStream.java0100644 0000000 0000000 00000022637 14603604450 033001 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 on the first write that causes * the total number of bytes written to the stream to exceed a configured threshold, * and every subsequent write. The event * can be used, for example, to throw an exception if a maximum has been reached, * or to switch the underlying stream when the threshold is exceeded. * *

* This class overrides all {@link 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.INSTANCE; /** * 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. * A negative threshold has no meaning and will be treated as 0 * * @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 < 0 ? 0 : 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 } // TODO for 4.0: Replace with getOutputStream() 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 { // TODO for 4.0: Replace with getOutputStream() getStream().flush(); } /** * Gets the number of bytes that have been written to this output stream. * * @return The number of bytes written. */ public long getByteCount() { return written; } /** * Gets the underlying output stream, to which the corresponding {@link OutputStream} methods in this class will * ultimately delegate. * * @return The underlying output stream. * @throws IOException if an error occurs. * @since 2.14.0 */ protected OutputStream getOutputStream() throws IOException { return outputStreamGetter.apply(this); } /** * Gets the underlying output stream, to which the corresponding {@link OutputStream} methods in this class will * ultimately delegate. * * @return The underlying output stream. * @throws IOException if an error occurs. * @deprecated Use {@link #getOutputStream()}. */ @Deprecated protected OutputStream getStream() throws IOException { return getOutputStream(); } /** * Gets the threshold, in bytes, at which an event will be triggered. * * @return The threshold point, in bytes. */ public int getThreshold() { return threshold; } /** * Tests 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); // TODO for 4.0: Replace with getOutputStream() 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 { // TODO we could write the sub-array up the threshold, fire the event, // and then write the rest so the event is always fired at the precise point. checkThreshold(len); // TODO for 4.0: Replace with getOutputStream() 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); // TODO for 4.0: Replace with getOutputStream() getStream().write(b); written++; } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/output/UncheckedAppendable.java0100644 0000000 0000000 00000004054 14603604450 031610 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.UncheckedIOException; /** * An {@link Appendable} that throws {@link UncheckedIOException} instead of {@link IOException}. * * @see Appendable * @see IOException * @see UncheckedIOException * @since 2.12.0 */ public interface UncheckedAppendable extends Appendable { /** * Constructs a new instance on the given Appendable. * * @param appendable The Appendable to uncheck. * @return a new instance. */ static UncheckedAppendable on(final Appendable appendable) { return new UncheckedAppendableImpl(appendable); } /** * Appends per {@link Appendable#append(char)} but rethrows {@link IOException} as {@link UncheckedIOException}. */ @Override UncheckedAppendable append(char c); /** * Appends per {@link Appendable#append(CharSequence)} but rethrows {@link IOException} as {@link UncheckedIOException}. */ @Override UncheckedAppendable append(CharSequence csq); /** * Appends per {@link Appendable#append(CharSequence, int, int)} but rethrows {@link IOException} as * {@link UncheckedIOException}. */ @Override UncheckedAppendable append(CharSequence csq, int start, int end); } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/output/UncheckedAppendableImpl.java0100644 0000000 0000000 00000003760 14603604450 032435 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.UncheckedIOException; import java.util.Objects; import org.apache.commons.io.function.Uncheck; /** * An {@link Appendable} implementation that throws {@link UncheckedIOException} instead of {@link IOException}. * * @see Appendable * @see IOException * @see UncheckedIOException * @since 2.12.0 */ final class UncheckedAppendableImpl implements UncheckedAppendable { private final Appendable appendable; UncheckedAppendableImpl(final Appendable appendable) { this.appendable = Objects.requireNonNull(appendable, "appendable"); } @Override public UncheckedAppendable append(final char c) { Uncheck.apply(appendable::append, c); return this; } @Override public UncheckedAppendable append(final CharSequence csq) { Uncheck.apply(appendable::append, csq); return this; } @Override public UncheckedAppendable append(final CharSequence csq, final int start, final int end) { Uncheck.apply(appendable::append, csq, start, end); return this; } @Override public String toString() { return appendable.toString(); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/output/UncheckedFilterOutputStream.java0100644 0000000 0000000 00000011343 14603604450 033376 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 java.io.UncheckedIOException; import org.apache.commons.io.build.AbstractStreamBuilder; import org.apache.commons.io.function.Uncheck; /** * A {@link FilterOutputStream} that throws {@link UncheckedIOException} instead of {@link UncheckedIOException}. *

* To build an instance, use {@link Builder}. *

* * @see Builder * @see FilterOutputStream * @see UncheckedIOException * @since 2.12.0 */ public final class UncheckedFilterOutputStream extends FilterOutputStream { // @formatter:off /** * Builds a new {@link UncheckedFilterOutputStream}. * *

* Using File IO: *

*
{@code
     * UncheckedFilterOutputStream s = UncheckedFilterOutputStream.builder()
     *   .setFile(file)
     *   .get();}
     * 
*

* Using NIO Path: *

*
{@code
     * UncheckedFilterOutputStream s = UncheckedFilterOutputStream.builder()
     *   .setPath(path)
     *   .get();}
     * 
* * @see #get() */ // @formatter:on public static class Builder extends AbstractStreamBuilder { /** * Builds a new {@link UncheckedFilterOutputStream}. *

* You must set input that supports {@link #getOutputStream()} on this builder, otherwise, this method throws an exception. *

*

* This builder use the following aspects: *

*
    *
  • {@link #getOutputStream()}
  • *
* * @return a new instance. * @throws IllegalStateException if the {@code origin} is {@code null}. * @throws UnsupportedOperationException if the origin cannot be converted to an {@link OutputStream}. * @throws IOException if an I/O error occurs. * @see #getOutputStream() */ @SuppressWarnings("resource") @Override public UncheckedFilterOutputStream get() throws IOException { return new UncheckedFilterOutputStream(getOutputStream()); } } /** * Constructs a new {@link Builder}. * * @return a new {@link Builder}. */ public static Builder builder() { return new Builder(); } /** * Constructs an output stream filter built on top of the specified underlying output stream. * * @param outputStream the underlying output stream, or {@code null} if this instance is to be created without an * underlying stream. */ private UncheckedFilterOutputStream(final OutputStream outputStream) { super(outputStream); } /** * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}. */ @Override public void close() throws UncheckedIOException { Uncheck.run(super::close); } /** * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}. */ @Override public void flush() throws UncheckedIOException { Uncheck.run(super::flush); } /** * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}. */ @Override public void write(final byte[] b) throws UncheckedIOException { Uncheck.accept(super::write, b); } /** * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}. */ @Override public void write(final byte[] b, final int off, final int len) throws UncheckedIOException { Uncheck.accept(super::write, b, off, len); } /** * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}. */ @Override public void write(final int b) throws UncheckedIOException { Uncheck.accept(super::write, b); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/output/UncheckedFilterWriter.java0100644 0000000 0000000 00000013305 14603604450 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.output; import java.io.FilterWriter; import java.io.IOException; import java.io.UncheckedIOException; import java.io.Writer; import org.apache.commons.io.build.AbstractStreamBuilder; import org.apache.commons.io.function.Uncheck; /** * A {@link FilterWriter} that throws {@link UncheckedIOException} instead of {@link IOException}. *

* To build an instance, use {@link Builder}. *

* * @see Builder * @see FilterWriter * @see IOException * @see UncheckedIOException * @since 2.12.0 */ public final class UncheckedFilterWriter extends FilterWriter { // @formatter:off /** * Builds a new {@link UncheckedFilterWriter}. * *

* Using File IO: *

*
{@code
     * UncheckedFilterWriter s = UncheckedFilterWriter.builder()
     *   .setFile(file)
     *   .get();}
     * 
*

* Using NIO Path: *

*
{@code
     * UncheckedFilterWriter s = UncheckedFilterWriter.builder()
     *   .setPath(path)
     *   .get();}
     * 
* * @see #get() */ // @formatter:on public static class Builder extends AbstractStreamBuilder { /** * Builds a new {@link UncheckedFilterWriter}. *

* You must set input that supports {@link #getWriter()} on this builder, otherwise, this method throws an exception. *

*

* This builder use the following aspects: *

*
    *
  • {@link #getWriter()}
  • *
* * @return a new instance. * @throws UnsupportedOperationException if the origin cannot provide a Writer. * @see #getWriter() */ @SuppressWarnings("resource") @Override public UncheckedFilterWriter get() throws IOException { return new UncheckedFilterWriter(getWriter()); } } /** * Constructs a new {@link Builder}. * * @return a new {@link Builder}. */ public static Builder builder() { return new Builder(); } /** * Constructs a new filtered writer. * * @param writer a Writer object providing the underlying stream. * @throws NullPointerException if {@code writer} is {@code null}. */ private UncheckedFilterWriter(final Writer writer) { super(writer); } /** * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}. */ @Override public Writer append(final char c) throws UncheckedIOException { return Uncheck.apply(super::append, c); } /** * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}. */ @Override public Writer append(final CharSequence csq) throws UncheckedIOException { return Uncheck.apply(super::append, csq); } /** * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}. */ @Override public Writer append(final CharSequence csq, final int start, final int end) throws UncheckedIOException { return Uncheck.apply(super::append, csq, start, end); } /** * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}. */ @Override public void close() throws UncheckedIOException { Uncheck.run(super::close); } /** * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}. */ @Override public void flush() throws UncheckedIOException { Uncheck.run(super::flush); } /** * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}. */ @Override public void write(final char[] cbuf) throws UncheckedIOException { Uncheck.accept(super::write, cbuf); } /** * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}. */ @Override public void write(final char[] cbuf, final int off, final int len) throws UncheckedIOException { Uncheck.accept(super::write, cbuf, off, len); } /** * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}. */ @Override public void write(final int c) throws UncheckedIOException { Uncheck.accept(super::write, c); } /** * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}. */ @Override public void write(final String str) throws UncheckedIOException { Uncheck.accept(super::write, str); } /** * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}. */ @Override public void write(final String str, final int off, final int len) throws UncheckedIOException { Uncheck.accept(super::write, str, off, len); } } ././@LongLink0100644 0000000 0000000 00000000152 14603604450 011633 Lustar 0000000 0000000 commons-io-2.16.1-src/src/main/java/org/apache/commons/io/output/UnsynchronizedByteArrayOutputStream.javacommons-io-2.16.1-src/src/main/java/org/apache/commons/io/output/UnsynchronizedByteArrayOutputStream0100644 0000000 0000000 00000016417 14603604450 034273 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.apache.commons.io.build.AbstractOrigin; import org.apache.commons.io.build.AbstractStreamBuilder; import org.apache.commons.io.function.Uncheck; import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream; /** * Implements a version of {@link AbstractByteArrayOutputStream} without any concurrent thread safety. *

* To build an instance, use {@link Builder}. *

* * @see Builder * @since 2.7 */ //@NotThreadSafe public final class UnsynchronizedByteArrayOutputStream extends AbstractByteArrayOutputStream { // @formatter:off /** * Builds a new {@link UnsynchronizedByteArrayOutputStream}. * *

* Using File IO: *

*
{@code
     * UnsynchronizedByteArrayOutputStream s = UnsynchronizedByteArrayOutputStream.builder()
     *   .setBufferSize(8192)
     *   .get();}
     * 
*

* Using NIO Path: *

*
{@code
     * UnsynchronizedByteArrayOutputStream s = UnsynchronizedByteArrayOutputStream.builder()
     *   .setBufferSize(8192)
     *   .get();}
     * 
* * @see #get() */ // @formatter:on public static class Builder extends AbstractStreamBuilder { /** * Builds a new {@link UnsynchronizedByteArrayOutputStream}. * *

* This builder use the following aspects: *

*
    *
  • {@link #getBufferSize()}
  • *
* * @return a new instance. * @see AbstractOrigin#getByteArray() */ @Override public UnsynchronizedByteArrayOutputStream get() { return new UnsynchronizedByteArrayOutputStream(getBufferSize()); } } /** * Constructs a new {@link Builder}. * * @return a new {@link Builder}. */ public static Builder builder() { return new Builder(); } /** * Fetches entire contents of an {@link 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 {@link 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 {@link 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 {@link 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 (UnsynchronizedByteArrayOutputStream output = builder().setBufferSize(size).get()) { output.write(input); return output.toInputStream(); } } /** * Constructs a new byte array output stream. The buffer capacity is initially * * {@value AbstractByteArrayOutputStream#DEFAULT_SIZE} bytes, though its size increases if necessary. * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}. */ @Deprecated public UnsynchronizedByteArrayOutputStream() { this(DEFAULT_SIZE); } /** * Constructs 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 * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}. Will be private in 3.0.0. */ @Deprecated public UnsynchronizedByteArrayOutputStream(final int size) { if (size < 0) { throw new IllegalArgumentException("Negative initial size: " + size); } needNewBuffer(size); } /** * @see java.io.ByteArrayOutputStream#reset() */ @Override public void reset() { resetImpl(); } @Override public int size() { return count; } @Override public byte[] toByteArray() { return toByteArrayImpl(); } @Override public InputStream toInputStream() { // @formatter:off return toInputStream((buffer, offset, length) -> Uncheck .get(() -> UnsynchronizedByteArrayInputStream.builder() .setByteArray(buffer) .setOffset(offset) .setLength(length) .get())); // @formatter:on } @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 int write(final InputStream in) throws IOException { return writeImpl(in); } @Override public void write(final int b) { writeImpl(b); } @Override public void writeTo(final OutputStream out) throws IOException { writeToImpl(out); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/output/WriterOutputStream.java0100644 0000000 0000000 00000045402 14603604450 031616 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; import java.nio.charset.StandardCharsets; import org.apache.commons.io.Charsets; import org.apache.commons.io.IOUtils; import org.apache.commons.io.build.AbstractStreamBuilder; import org.apache.commons.io.charset.CharsetDecoders; /** * {@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): *

*

* To build an instance, use {@link Builder}. *

*
 * OutputStream out = ...
 * Charset cs = ...
 * OutputStreamWriter writer = new OutputStreamWriter(out, cs);
 * WriterOutputStream out2 = WriterOutputStream.builder()
 *   .setWriter(writer)
 *   .setCharset(cs)
 *   .get();
 * 
*

* {@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 Builder * @see org.apache.commons.io.input.ReaderInputStream * @since 2.0 */ public class WriterOutputStream extends OutputStream { // @formatter:off /** * Builds a new {@link WriterOutputStream}. * *

* For example: *

*
{@code
     * WriterOutputStream s = WriterOutputStream.builder()
     *   .setPath(path)
     *   .setBufferSize(8192)
     *   .setCharset(StandardCharsets.UTF_8)
     *   .setWriteImmediately(false)
     *   .get();}
     * 
* * @see #get() * @since 2.12.0 */ // @formatter:on public static class Builder extends AbstractStreamBuilder { private CharsetDecoder charsetDecoder; private boolean writeImmediately; /** * Constructs a new Builder. */ public Builder() { this.charsetDecoder = getCharset().newDecoder(); } /** * Builds a new {@link WriterOutputStream}. *

* You must set input that supports {@link #getWriter()} on this builder, otherwise, this method throws an exception. *

*

* This builder use the following aspects: *

*
    *
  • {@link #getWriter()}
  • *
  • {@link #getBufferSize()}
  • *
  • charsetDecoder
  • *
  • writeImmediately
  • *
* * @return a new instance. * @throws UnsupportedOperationException if the origin cannot provide a Writer. * @see #getWriter() */ @SuppressWarnings("resource") @Override public WriterOutputStream get() throws IOException { return new WriterOutputStream(getWriter(), charsetDecoder, getBufferSize(), writeImmediately); } @Override public Builder setCharset(final Charset charset) { super.setCharset(charset); this.charsetDecoder = getCharset().newDecoder(); return this; } @Override public Builder setCharset(final String charset) { super.setCharset(charset); this.charsetDecoder = getCharset().newDecoder(); return this; } /** * Sets the charset decoder. * * @param charsetDecoder the charset decoder. * @return this */ public Builder setCharsetDecoder(final CharsetDecoder charsetDecoder) { this.charsetDecoder = charsetDecoder != null ? charsetDecoder : getCharsetDefault().newDecoder(); super.setCharset(this.charsetDecoder.charset()); return this; } /** * Sets whether the output buffer will be flushed after each write operation ({@code true}), 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. * * @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. * @return this */ public Builder setWriteImmediately(final boolean writeImmediately) { this.writeImmediately = writeImmediately; return this; } } private static final int BUFFER_SIZE = IOUtils.DEFAULT_BUFFER_SIZE; /** * Constructs a new {@link Builder}. * * @return a new {@link Builder}. * @since 2.12.0 */ public static Builder builder() { return new Builder(); } /** * Checks 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 (!StandardCharsets.UTF_16.name().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"); } } 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} 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 Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated public WriterOutputStream(final Writer writer) { this(writer, Charset.defaultCharset(), BUFFER_SIZE, false); } /** * 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 * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated 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 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. * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated public WriterOutputStream(final Writer writer, final Charset charset, final int bufferSize, final boolean writeImmediately) { // @formatter:off this(writer, Charsets.toCharset(charset).newDecoder() .onMalformedInput(CodingErrorAction.REPLACE) .onUnmappableCharacter(CodingErrorAction.REPLACE) .replaceWith("?"), bufferSize, writeImmediately); // @formatter:on } /** * 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 * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated 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 * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated public WriterOutputStream(final Writer writer, final CharsetDecoder decoder, final int bufferSize, final boolean writeImmediately) { checkIbmJdkWithBrokenUTF16(CharsetDecoders.toCharsetDecoder(decoder).charset()); this.writer = writer; this.decoder = CharsetDecoders.toCharsetDecoder(decoder); this.writeImmediately = writeImmediately; this.decoderOut = CharBuffer.allocate(bufferSize); } /** * 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 * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated public WriterOutputStream(final Writer writer, final String charsetName) { this(writer, charsetName, 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. * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated public WriterOutputStream(final Writer writer, final String charsetName, final int bufferSize, final boolean writeImmediately) { this(writer, Charsets.toCharset(charsetName), bufferSize, writeImmediately); } /** * 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(); } /** * 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(); } /** * 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(); } } /** * 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(); } /** * 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 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 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); } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/output/XmlStreamWriter.java0100644 0000000 0000000 00000024147 14603604450 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.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.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.Locale; import java.util.Objects; import java.util.regex.Matcher; import org.apache.commons.io.Charsets; import org.apache.commons.io.IOUtils; import org.apache.commons.io.build.AbstractStreamBuilder; import org.apache.commons.io.input.XmlStreamReader; /** * Character stream that handles all the necessary work to figure out the charset encoding of the XML document written to the stream. *

* To build an instance, use {@link Builder}. *

* * @see Builder * @see XmlStreamReader * @since 2.0 */ public class XmlStreamWriter extends Writer { // @formatter:off /** * Builds a new {@link XmlStreamWriter}. * *

* For example: *

*
{@code
     * WriterOutputStream w = WriterOutputStream.builder()
     *   .setPath(path)
     *   .setCharset(StandardCharsets.UTF_8)
     *   .get();}
     * 
* * @see #get() * @since 2.12.0 */ // @formatter:off public static class Builder extends AbstractStreamBuilder { /** * Constructs a new {@link Builder}. */ public Builder() { setCharsetDefault(StandardCharsets.UTF_8); setCharset(StandardCharsets.UTF_8); } /** * Builds a new {@link XmlStreamWriter}. *

* You must set input that supports {@link #getOutputStream()} on this builder, otherwise, this method throws an exception. *

*

* This builder use the following aspects: *

*
    *
  • {@link #getOutputStream()}
  • *
  • {@link #getCharset()}
  • *
* * @return a new instance. * @throws IllegalStateException if the {@code origin} is {@code null}. * @throws UnsupportedOperationException if the origin cannot be converted to an {@link OutputStream}. * @throws IOException if an I/O error occurs. * @see #getOutputStream() */ @SuppressWarnings("resource") @Override public XmlStreamWriter get() throws IOException { return new XmlStreamWriter(getOutputStream(), getCharset()); } } private static final int BUFFER_SIZE = IOUtils.DEFAULT_BUFFER_SIZE; /** * Constructs a new {@link Builder}. * * @return a new {@link Builder}. * @since 2.12.0 */ public static Builder builder() { return new Builder(); } private final OutputStream out; private final Charset defaultCharset; private StringWriter prologWriter = new StringWriter(BUFFER_SIZE); private Writer writer; private Charset charset; /** * 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 * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated 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 * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated @SuppressWarnings("resource") public XmlStreamWriter(final File file, final String defaultEncoding) throws FileNotFoundException { this(new FileOutputStream(file), defaultEncoding); } /** * Constructs a new XML stream writer for the specified output stream * with a default encoding of UTF-8. * * @param out The output stream * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated public XmlStreamWriter(final OutputStream out) { this(out, StandardCharsets.UTF_8); } /** * 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 */ private XmlStreamWriter(final OutputStream out, final Charset defaultEncoding) { this.out = out; this.defaultCharset = Objects.requireNonNull(defaultEncoding); } /** * 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 * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} */ @Deprecated public XmlStreamWriter(final OutputStream out, final String defaultEncoding) { this(out, Charsets.toCharset(defaultEncoding, StandardCharsets.UTF_8)); } /** * Closes the underlying writer. * * @throws IOException if an error occurs closing the underlying writer */ @Override public void close() throws IOException { if (writer == null) { charset = defaultCharset; writer = new OutputStreamWriter(out, charset); writer.write(prologWriter.toString()); } writer.close(); } /** * 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 = prologWriter.getBuffer(); if (xmlProlog.length() + len > BUFFER_SIZE) { size = BUFFER_SIZE - xmlProlog.length(); } prologWriter.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 = XmlStreamReader.ENCODING_PATTERN.matcher(xmlProlog.substring(0, xmlPrologEnd)); if (m.find()) { final String encName = m.group(1).toUpperCase(Locale.ROOT); charset = Charset.forName(encName.substring(1, encName.length() - 1)); } else { // no encoding found in XML prolog: using default // encoding charset = defaultCharset; } } else if (xmlProlog.length() >= BUFFER_SIZE) { // no encoding found in first characters: using default // encoding charset = defaultCharset; } } else { // no XML prolog: using default encoding charset = defaultCharset; } if (charset != null) { // encoding has been chosen: let's do it prologWriter = null; writer = new OutputStreamWriter(out, charset); writer.write(xmlProlog.toString()); if (len > size) { writer.write(cbuf, off + size, len - size); } } } } /** * 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(); } } /** * Returns the default encoding. * * @return the default encoding */ public String getDefaultEncoding() { return defaultCharset.name(); } /** * Returns the detected encoding. * * @return the detected encoding */ public String getEncoding() { return charset.name(); } /** * 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 (prologWriter != null) { detectEncoding(cbuf, off, len); } else { writer.write(cbuf, off, len); } } } commons-io-2.16.1-src/src/main/java/org/apache/commons/io/output/package-info.java0100644 0000000 0000000 00000001705 14603604450 030267 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Provides implementations of output classes, such as {@link java.io.OutputStream} and * {@link java.io.Writer}. */ package org.apache.commons.io.output; commons-io-2.16.1-src/src/main/java/org/apache/commons/io/overview.html0100644 0000000 0000000 00000002352 14603604450 026273 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.16.1-src/src/main/java/org/apache/commons/io/package-info.java0100644 0000000 0000000 00000003440 14603604450 026725 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Provides 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 file names 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. *

*/ package org.apache.commons.io; commons-io-2.16.1-src/src/main/java/org/apache/commons/io/serialization/ClassNameMatcher.java0100644 0000000 0000000 00000002322 14603604450 032426 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * 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.16.1-src/src/main/java/org/apache/commons/io/serialization/FullClassNameMatcher.java0100644 0000000 0000000 00000003104 14603604450 033250 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * 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.16.1-src/src/main/java/org/apache/commons/io/serialization/RegexpClassNameMatcher.java0100644 0000000 0000000 00000003576 14603604450 033615 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * 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.Objects; 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 pattern. * * @param pattern a pattern for evaluating acceptable class names * @throws NullPointerException if {@code pattern} is null */ public RegexpClassNameMatcher(final Pattern pattern) { this.pattern = Objects.requireNonNull(pattern, "pattern"); } /** * 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)); } @Override public boolean matches(final String className) { return pattern.matcher(className).matches(); } }././@LongLink0100644 0000000 0000000 00000000151 14603604450 011632 Lustar 0000000 0000000 commons-io-2.16.1-src/src/main/java/org/apache/commons/io/serialization/ValidatingObjectInputStream.javacommons-io-2.16.1-src/src/main/java/org/apache/commons/io/serialization/ValidatingObjectInputStream.0100644 0000000 0000000 00000015554 14603604450 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.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; import java.util.stream.Stream; /** * An {@link 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); } /** * 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) { Stream.of(classes).map(c -> new FullClassNameMatcher(c.getName())).forEach(acceptMatchers::add); 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; } /** * 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; } /** * 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) { Stream.of(patterns).map(WildcardClassNameMatcher::new).forEach(acceptMatchers::add); return this; } /** * Checks that the class name conforms to requirements. * * @param name The class name * @throws InvalidClassException when a non-accepted class is encountered */ private void checkClassName(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 {@link 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); } /** * 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) { Stream.of(classes).map(c -> new FullClassNameMatcher(c.getName())).forEach(rejectMatchers::add); 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; } /** * 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; } /** * 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) { Stream.of(patterns).map(WildcardClassNameMatcher::new).forEach(rejectMatchers::add); return this; } @Override protected Class resolveClass(final ObjectStreamClass osc) throws IOException, ClassNotFoundException { checkClassName(osc.getName()); return super.resolveClass(osc); } }././@LongLink0100644 0000000 0000000 00000000146 14603604450 011636 Lustar 0000000 0000000 commons-io-2.16.1-src/src/main/java/org/apache/commons/io/serialization/WildcardClassNameMatcher.javacommons-io-2.16.1-src/src/main/java/org/apache/commons/io/serialization/WildcardClassNameMatcher.jav0100644 0000000 0000000 00000003206 14603604450 033741 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * 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.16.1-src/src/main/java/org/apache/commons/io/serialization/package-info.java0100644 0000000 0000000 00000001641 14603604450 031603 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Provides a framework for controlling the deserialization of classes. */ package org.apache.commons.io.serialization; commons-io-2.16.1-src/src/media/io-logo-white.xcf0100644 0000000 0000000 00000047413 14603604450 022053 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.16.1-src/src/media/logo.gif0100644 0000000 0000000 00000010471 14603604450 020307 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.16.1-src/src/site/resources/download_io.cgi0100755 0000000 0000000 00000000235 14603604450 023541 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.16.1-src/src/site/resources/images/io-logo-white.png0100644 0000000 0000000 00000024631 14603604450 025220 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.16.1-src/src/site/resources/profile.jacoco0100644 0000000 0000000 00000000000 14603604450 023362 0ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/site/site.xml0100644 0000000 0000000 00000004015 14603604450 020230 0ustar00rootroot0000000 0000000 Commons IO /images/io-logo-white.png /index.html commons-io-2.16.1-src/src/site/xdoc/bestpractices.xml0100644 0000000 0000000 00000012322 14603604450 023054 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 on 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 hard disks 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.16.1-src/src/site/xdoc/building.xml0100644 0000000 0000000 00000004227 14603604450 022023 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.16.1-src/src/site/xdoc/description.xml0100644 0000000 0000000 00000023625 14603604450 022554 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 be 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.16.1-src/src/site/xdoc/download_io.xml0100644 0000000 0000000 00000017706 14603604450 022532 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.16.1-bin.tar.gz sha512 pgp
commons-io-2.16.1-bin.zip sha512 pgp
commons-io-2.16.1-src.tar.gz sha512 pgp
commons-io-2.16.1-src.zip sha512 pgp

Older releases can be obtained from the archives.

commons-io-2.16.1-src/src/site/xdoc/index.xml0100644 0000000 0000000 00000014312 14603604450 021331 0ustar00rootroot0000000 0000000 Commons IO Overview Commons Documentation Team

Apache Commons IO is a library of utilities to assist with developing IO functionality.

Main areas include:

  • io - This package defines utility classes for working with streams, readers, writers and files.
  • build - This package provides classes to implement IO builders.
  • charset - This package provides classes to work with code from java.nio.charset.
  • comparator - This package provides various Comparator implementations for Files and Paths.
  • file - This package provides extensions in the realm of java.nio.file.
  • file.attribute - This package provides help using java.nio.file.attribute types.
  • file SPI - This package provides extensions in the realm of java.nio.file.spi.
  • 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 requires a minimum of Java 8 - Download now .

View the Release Notes and Javadoc API documents .

See the download archive and Javadoc archive .

The Java platform requirements are:

  • Version 2.7 and up requires Java 8 or above.
  • Version 2.6 requires Java 7 or above.
  • Version 2.3 through 2.5 requires Java 6 or above.
  • Version 2.2 requires Java 5 or above.

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.16.1-src/src/site/xdoc/issue-tracking.xml0100644 0000000 0000000 00000013277 14603604450 023163 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 creating patches see the Apache Contributors Guide.

You may also find these links useful:

commons-io-2.16.1-src/src/site/xdoc/mail-lists.xml0100644 0000000 0000000 00000021277 14603604450 022310 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; most of the lists are set up to drop attachments. Patches are best handled via the Issue Tracking system. If you have a GitHub account, most components also accept PRs (pull requests). 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 lists.apache.org www.mail-archive.com
Commons Developer List

Discussion of development of Apache Commons IO.

Subscribe Unsubscribe Post lists.apache.org www.mail-archive.com
Commons Issues List

Only for e-mails automatically generated by the issue tracking system.

Subscribe Unsubscribe read only lists.apache.org www.mail-archive.com
Commons Commits List

Only for e-mails automatically generated by the source control system.

Subscribe Unsubscribe read only lists.apache.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 lists.apache.org www.mail-archive.com
commons-io-2.16.1-src/src/site/xdoc/proposal.xml0100644 0000000 0000000 00000006145 14603604450 022066 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.16.1-src/src/site/xdoc/tasks.xml0100644 0000000 0000000 00000003447 14603604450 021356 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.16.1-src/src/site/xdoc/upgradeto1_1.xml0100644 0000000 0000000 00000015452 14603604450 022523 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 necessary 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 character 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 necessary - IOUtils and EndianUtils are no longer final [28978] Allows developers to have subclasses if desired

commons-io-2.16.1-src/src/site/xdoc/upgradeto1_2.xml0100644 0000000 0000000 00000005147 14603604450 022524 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 compare 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.16.1-src/src/site/xdoc/upgradeto1_3.xml0100644 0000000 0000000 00000017672 14603604450 022533 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 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 inaccurate 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 callback 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.16.1-src/src/site/xdoc/upgradeto1_3_1.xml0100644 0000000 0000000 00000003355 14603604450 022744 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.16.1-src/src/site/xdoc/upgradeto1_3_2.xml0100644 0000000 0000000 00000004663 14603604450 022750 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.16.1-src/src/site/xdoc/upgradeto1_4.xml0100644 0000000 0000000 00000011637 14603604450 022527 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-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) - ThresholdingOutputStream [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 facility to specify case sensitivity on prefix matching - SuffixFileFilter [IO-126] - Add facility 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.16.1-src/src/site/xdoc/upgradeto2_0.xml0100644 0000000 0000000 00000017734 14603604450 022530 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 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 subdirectories * [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.16.1-src/src/site/xdoc/upgradeto2_0_1.xml0100644 0000000 0000000 00000004005 14603604450 022733 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.16.1-src/src/site/xdoc/upgradeto2_1.xml0100644 0000000 0000000 00000006411 14603604450 022517 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.16.1-src/src/site/xdoc/upgradeto2_2.xml0100644 0000000 0000000 00000010071 14603604450 022515 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.16.1-src/src/site/xdoc/upgradeto2_3.xml0100644 0000000 0000000 00000004405 14603604450 022522 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.16.1-src/src/site/xdoc/upgradeto2_4.xml0100644 0000000 0000000 00000006633 14603604450 022530 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.16.1-src/src/site/xdoc/upgradeto2_5.xml0100644 0000000 0000000 00000025467 14603604450 022537 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 forever 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 failure 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.16.1-src/src/site/xdoc/upgradeto2_6.xml0100644 0000000 0000000 00000016646 14603604450 022537 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.16.1-src/src/test/java/org/apache/commons/io/AbstractFileUtilsDeleteDirectoryTest.java0100644 0000000 0000000 00000022260 14603604450 033671 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.assertThrows; 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 AbstractFileUtilsDeleteDirectoryTest { @TempDir public File top; protected abstract boolean setupSymlink(final File res, final File link) throws Exception; @Test public void testDeleteDirectoryNullArgument() { assertThrows(NullPointerException.class, () -> FileUtils.deleteDirectory(null)); } @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); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/BrokenTestFactories.java0100644 0000000 0000000 00000006313 14603604450 030356 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.FileNotFoundException; import java.io.IOException; import java.nio.file.FileSystemNotFoundException; import java.util.stream.Stream; import org.apache.commons.io.input.BrokenInputStream; import org.apache.commons.io.input.BrokenReader; import org.apache.commons.io.output.BrokenOutputStream; import org.apache.commons.io.output.BrokenWriter; /** * Factory for parameterized tests of {@link BrokenInputStream}, {@link BrokenReader}, {@link BrokenOutputStream}, and {@link BrokenWriter}. */ public class BrokenTestFactories { /** * A custom Error class. */ public static final class CustomError extends Error { private static final long serialVersionUID = 1L; } /** * A custom Exception class. */ public static final class CustomException extends Exception { private static final long serialVersionUID = 1L; } /** * A custom RuntimeException class. */ public static final class CustomRuntimeException extends RuntimeException { private static final long serialVersionUID = 1L; } /** * Creates a stream of all throwable types used in testing broken streams. * * @return a stream of all throwable types used in testing broken streams. */ public static Stream> parameters() { // @formatter:off return Stream.of( Throwable.class, // JRE Root class Exception.class, // JRE Root Exception class IOException.class, // JRE Root IOException class FileNotFoundException.class, // JRE IOException subclass RuntimeException.class, // JRE Root RuntimeException FileSystemNotFoundException.class, // JRE RuntimeException subclass in NIO IllegalArgumentException.class, // JRE RuntimeException subclass IllegalStateException.class, // JRE RuntimeException subclass Error.class, // JRE Error root class ExceptionInInitializerError.class, // JRE Error subclass CustomException.class, // Custom Exception subclass CustomRuntimeException.class, // Custom RuntimeException subclass CustomError.class // Custom Error subclass ); // @formatter:on } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/ByteOrderMarkTest.java0100644 0000000 0000000 00000014305 14603604450 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.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; import java.nio.charset.Charset; import org.junit.jupiter.api.Test; /** * Test for {@link ByteOrderMark}. */ public class ByteOrderMarkTest { 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); /** Tests that {@link ByteOrderMark#getCharsetName()} can be loaded as a {@link java.nio.charset.Charset} as advertised. */ @Test public void testConstantCharsetNames() { 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())); } /** Tests Exceptions */ @Test public void testConstructorExceptions() { assertThrows(NullPointerException.class, () -> new ByteOrderMark(null, 1, 2, 3)); assertThrows(IllegalArgumentException.class, () -> new ByteOrderMark("", 1, 2, 3)); assertThrows(NullPointerException.class, () -> new ByteOrderMark("a", (int[]) null)); assertThrows(IllegalArgumentException.class, () -> new ByteOrderMark("b")); } /** Tests {@link ByteOrderMark#equals(Object)} */ @SuppressWarnings("EqualsWithItself") @Test public void testEquals() { assertEquals(ByteOrderMark.UTF_16BE, ByteOrderMark.UTF_16BE); assertEquals(ByteOrderMark.UTF_16LE, ByteOrderMark.UTF_16LE); assertEquals(ByteOrderMark.UTF_32BE, ByteOrderMark.UTF_32BE); assertEquals(ByteOrderMark.UTF_32LE, ByteOrderMark.UTF_32LE); assertEquals(ByteOrderMark.UTF_8, ByteOrderMark.UTF_8); assertNotEquals(ByteOrderMark.UTF_8, ByteOrderMark.UTF_16BE); assertNotEquals(ByteOrderMark.UTF_8, ByteOrderMark.UTF_16LE); assertNotEquals(ByteOrderMark.UTF_8, ByteOrderMark.UTF_32BE); assertNotEquals(ByteOrderMark.UTF_8, ByteOrderMark.UTF_32LE); 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"); } /** Tests {@link ByteOrderMark#getBytes()} */ @Test public void testGetBytes() { 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"); } /** Tests {@link ByteOrderMark#getCharsetName()} */ @Test public void testGetCharsetName() { 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 {@link ByteOrderMark#get(int)} */ @Test public void testGetInt() { 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)"); } /** Tests {@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 "); } /** Tests {@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"); } /** Tests {@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.16.1-src/src/test/java/org/apache/commons/io/ByteOrderParserTest.java0100644 0000000 0000000 00000003134 14603604450 030350 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; /** * Test for {@link ByteOrderParser}. */ 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.16.1-src/src/test/java/org/apache/commons/io/CharsetsTest.java0100644 0000000 0000000 00000011055 14603604450 027051 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.Set; import java.util.SortedMap; import org.junit.jupiter.api.Test; /** * Tests {@link Charsets}. */ @SuppressWarnings("deprecation") // testing deprecated code public class CharsetsTest { /** * For parameterized tests. */ public static final String AVAIL_CHARSETS = "org.apache.commons.io.CharsetsTest#availableCharsetsKeySet"; /** * For parameterized tests. */ public static final String REQUIRED_CHARSETS = "org.apache.commons.io.CharsetsTest#getRequiredCharsetNames"; /** * For parameterized tests. * * @return {@code Charset.availableCharsets().keySet()}. */ public static Set availableCharsetsKeySet() { return Charset.availableCharsets().keySet(); } /** * For parameterized tests. * * @return {@code Charset.requiredCharsets().keySet()}. */ public static Set getRequiredCharsetNames() { return Charsets.requiredCharsets().keySet(); } @Test public void testIso8859_1() { assertEquals("ISO-8859-1", Charsets.ISO_8859_1.name()); } @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 testToCharset_String() { 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 testToCharset_String_Charset() { assertNull(Charsets.toCharset((String) null, null)); assertEquals(Charset.defaultCharset(), Charsets.toCharset((String) null, Charset.defaultCharset())); assertEquals(Charset.defaultCharset(), Charsets.toCharset((Charset) null, Charset.defaultCharset())); assertNull(Charsets.toCharset((Charset) null, null)); assertEquals(Charset.defaultCharset(), Charsets.toCharset(Charset.defaultCharset(), Charset.defaultCharset())); assertEquals(StandardCharsets.UTF_8, Charsets.toCharset(StandardCharsets.UTF_8, Charset.defaultCharset())); assertEquals(StandardCharsets.UTF_8, Charsets.toCharset(StandardCharsets.UTF_8, null)); } @Test public void testUsAscii() { assertEquals(StandardCharsets.US_ASCII.name(), Charsets.US_ASCII.name()); } @Test public void testUtf16() { assertEquals(StandardCharsets.UTF_16.name(), Charsets.UTF_16.name()); } @Test public void testUtf16Be() { assertEquals(StandardCharsets.UTF_16BE.name(), Charsets.UTF_16BE.name()); } @Test public void testUtf16Le() { assertEquals(StandardCharsets.UTF_16LE.name(), Charsets.UTF_16LE.name()); } @Test public void testUtf8() { assertEquals(StandardCharsets.UTF_8.name(), Charsets.UTF_8.name()); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/CopyUtilsTest.java0100644 0000000 0000000 00000025166 14603604450 027240 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.input.CharSequenceInputStream; 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 /** * Test for {@link 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); @Test public void testCopy_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 testCopy_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 = StandardCharsets.UTF_8.name(); 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 testCopy_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 testCopy_inputStreamToWriterWithEncoding() throws Exception { final String inDataStr = "data"; final String charsetName = StandardCharsets.UTF_8.name(); final StringWriter writer = new StringWriter(); CopyUtils.copy(new CharSequenceInputStream.Builder().setCharSequence(inDataStr).setCharset(charsetName).get(), 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 testCopy_readerToOutputStreamString() 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, StandardCharsets.US_ASCII.name()); //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_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 testCopy_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 testCopy_stringToOutputStreamString() 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, StandardCharsets.US_ASCII.name()); //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 testCopy_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"); } @Test public void testCtor() { new CopyUtils(); // Nothing to assert, the constructor is public and does not blow up. } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/DeleteDirectoryTest.java0100644 0000000 0000000 00000012564 14603604450 030372 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.attribute.PosixFilePermission; import java.util.Set; import org.apache.commons.io.file.AbstractTempDirTest; import org.apache.commons.io.file.PathUtils; import org.apache.commons.io.file.StandardDeleteOption; import org.apache.commons.io.function.IOConsumer; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.DisabledOnOs; import org.junit.jupiter.api.condition.OS; /** * Tests IO-751. *

* Must be run on a POSIX file system, macOS or Linux, disabled on Windows. *

*/ @DisabledOnOs(OS.WINDOWS) public class DeleteDirectoryTest extends AbstractTempDirTest { private void testDeleteDirectory(final IOConsumer deleter) throws IOException { // Create a test file final String contents = "Hello!"; final Path file = tempDirPath.resolve("file.txt"); final Charset charset = StandardCharsets.UTF_8; PathUtils.writeString(file, contents, charset); final Set permissions = Files.getPosixFilePermissions(file); // Sanity check: Owner has write permission on the new file assertTrue(permissions.contains(PosixFilePermission.OWNER_WRITE), permissions::toString); // Create a test directory final Path testDir = tempDirPath.resolve("dir"); Files.createDirectory(testDir); // Inside the test directory, create a symlink to the test file final Path symLink = testDir.resolve("symlink.txt"); Files.createSymbolicLink(symLink, file); // Sanity check: The symlink really points to the test file assertEquals(contents, PathUtils.readString(symLink, charset)); // Delete the test directory using the given implementation deleter.accept(testDir); // Symlink is gone -- passes assertFalse(Files.exists(symLink), symLink::toString); // The test file still exists -- passes assertTrue(Files.exists(file), file::toString); // The permissions of the test file should still be the same assertEquals(permissions, Files.getPosixFilePermissions(file), file::toString); } @Test public void testDeleteDirectoryWithFileUtils() throws IOException { testDeleteDirectory(dir -> FileUtils.deleteDirectory(dir.toFile())); } @Test public void testDeleteDirectoryWithPathUtils() throws IOException { testDeleteDirectory(PathUtils::deleteDirectory); } @Test public void testDeleteDirectoryWithPathUtilsOverrideReadOnly() throws IOException { testDeleteDirectory(dir -> PathUtils.deleteDirectory(dir, StandardDeleteOption.OVERRIDE_READ_ONLY)); } @Test @DisabledOnOs(OS.LINUX) // TODO public void testDeleteFileCheckParentAccess() throws IOException { // Create a test directory final Path testDir = tempDirPath.resolve("dir"); Files.createDirectory(testDir); // Create a test file final Path file = testDir.resolve("file.txt"); final Charset charset = StandardCharsets.UTF_8; PathUtils.writeString(file, "Hello!", charset); // A file is RO in POSIX if the parent is not W and not E. PathUtils.setReadOnly(file, true); final Set permissions = Files.getPosixFilePermissions(testDir); assertFalse(Files.isWritable(testDir), () -> String.format("Parent directory '%s' of '%s' should NOT be Writable, permissions are %s ", testDir, file, permissions)); assertFalse(Files.isExecutable(testDir), () -> String.format("Parent directory '%s' of '%s' should NOT be Executable, permissions are %s ", testDir, file, permissions)); assertThrows(IOException.class, () -> PathUtils.delete(file)); // Nothing happened, we're not even allowed to test attributes, so the file seems deleted, but it is not. PathUtils.delete(file, StandardDeleteOption.OVERRIDE_READ_ONLY); assertFalse(Files.exists(file)); assertEquals(permissions, Files.getPosixFilePermissions(testDir), testDir::toString); assertFalse(Files.isWritable(testDir)); assertFalse(Files.isExecutable(testDir)); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/DemuxInputStreamTest.java0100644 0000000 0000000 00000016016 14603604450 030555 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.InputStream; import java.io.OutputStream; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Random; import org.apache.commons.io.input.CharSequenceInputStream; 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; /** * Tests {@link DemuxInputStream}. */ public class DemuxInputStreamTest { private static final class ReaderThread extends Thread { private final DemuxInputStream demuxInputStream; private final InputStream inputStream; private final StringBuffer stringBuffer = new StringBuffer(); 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 sleepMillis = Math.abs(RANDOM.nextInt() % 10); TestUtils.sleep(sleepMillis); ch = demuxInputStream.read(); } } catch (final Exception e) { e.printStackTrace(); } } } private static final class WriterThread extends Thread { private final byte[] byteArray; private final DemuxOutputStream demuxOutputStream; private final OutputStream outputStream; 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 sleepMillis = Math.abs(RANDOM.nextInt() % 10); TestUtils.sleep(sleepMillis); } catch (final Exception e) { e.printStackTrace(); } } } } private static final Random RANDOM = new Random(); 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 String T1 = "Thread1"; private static final String T2 = "Thread2"; private static final String T3 = "Thread3"; private static final String T4 = "Thread4"; private final HashMap outputMap = new HashMap<>(); private final HashMap threadMap = new HashMap<>(); private void doJoin() throws InterruptedException { for (final String name : threadMap.keySet()) { final Thread thread = threadMap.get(name); thread.join(); } } private void doStart() { threadMap.keySet().forEach(name -> threadMap.get(name).start()); } private String getInput(final String threadName) { final ReaderThread thread = (ReaderThread) threadMap.get(threadName); assertNotNull(thread, "getInput()"); return thread.getData(); } private String getOutput(final String threadName) { final ByteArrayOutputStream output = outputMap.get(threadName); assertNotNull(output, "getOutput()"); return output.toString(StandardCharsets.UTF_8); } private void startReader(final String name, final String data, final DemuxInputStream demux) { final InputStream input = CharSequenceInputStream.builder().setCharSequence(data).get(); final ReaderThread thread = new ReaderThread(name, input, demux); threadMap.put(name, thread); } 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); } @Test public void testInputStream() throws Exception { try (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"); } } @Test public void testOutputStream() throws Exception { try (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 testReadEOF() throws Exception { try (final DemuxInputStream input = new DemuxInputStream()) { assertEquals(IOUtils.EOF, input.read()); } } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/DirectoryWalkerTest.java0100644 0000000 0000000 00000051253 14603604450 030413 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.assertThrows; 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; /** * Tests {@link DirectoryWalker}. */ public class DirectoryWalkerTest { /** * 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 Cancel. */ @Override protected void handleCancelled(final File startDirectory, final Collection results, final CancelException cancel) throws IOException { if (!suppressCancel) { super.handleCancelled(startDirectory, results, cancel); } } /** 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); } } } /** * Test DirectoryWalker implementation that always returns false * from handleDirectoryStart() */ private static final 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 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 that finds files in a directory hierarchy * applying a file filter. */ private static final 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()); } } /** * 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 Cancel. */ @Override protected void handleCancelled(final File startDirectory, final Collection results, final CancelException cancel) throws IOException { if (!suppressCancel) { super.handleCancelled(startDirectory, results, cancel); } } /** 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; } } // Directories private static final File current = FileUtils.current(); 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); /** * 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); } /** * 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; } /** * 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 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 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 an invalid start directory */ @Test public void testHandleStartDirectoryFalse() { final List results = new TestFalseFileFinder(null, -1).find(current); assertEquals(0, results.size(), "Result Size"); } /** * 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(FileUtils.current()), "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"); assertThrows(NullPointerException.class, () -> new TestFileFinder(null, -1).find(null)); } /** * 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); } } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/DirectoryWalkerTestCaseJava4.java0100644 0000000 0000000 00000045611 14603604450 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.assertThrows; 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 { /** * 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 Cancel. */ @Override protected void handleCancelled(final File startDirectory, final Collection results, final CancelException cancel) throws IOException { if (!suppressCancel) { super.handleCancelled(startDirectory, results, cancel); } } /** * 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); } } } /** * Test DirectoryWalker implementation that always returns false * from handleDirectoryStart() */ private static final 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 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 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 Cancel. */ @Override protected void handleCancelled(final File startDirectory, final Collection results, final CancelException cancel) throws IOException { if (!suppressCancel) { super.handleCancelled(startDirectory, results, cancel); } } /** * 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; } } // Directories private static final File current = FileUtils.current(); 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); /** * 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); } /** * 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; } /** * 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 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 an invalid start directory */ @Test public void testHandleStartDirectoryFalse() { final List results = new TestFalseFileFinder(null, -1).find(current); assertEquals(0, results.size(), "Result Size"); } /** * 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(FileUtils.current()), "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"); assertThrows(NullPointerException.class, () -> new TestFileFinder(null, -1).find(null)); } /** * 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); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/EndianUtilsTest.java0100644 0000000 0000000 00000032056 14603604450 027520 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.EOFException; import java.io.IOException; import org.junit.jupiter.api.Test; /** * Tests {@link EndianUtils}. */ public class EndianUtilsTest { @Test public void testCtor() { new EndianUtils(); // Constructor does not blow up. } @Test public void testEOFException() { final ByteArrayInputStream input = new ByteArrayInputStream(new byte[] {}); assertThrows(EOFException.class, () -> EndianUtils.readSwappedDouble(input)); } @Test public void testInvalidOffset() throws IOException { final byte[] bytes = {}; assertThrows(IllegalArgumentException.class, () -> EndianUtils.readSwappedInteger(bytes, 0)); assertThrows(IllegalArgumentException.class, () -> EndianUtils.readSwappedLong(bytes, 0)); assertThrows(IllegalArgumentException.class, () -> EndianUtils.readSwappedShort(bytes, 0)); assertThrows(IllegalArgumentException.class, () -> EndianUtils.readSwappedUnsignedInteger(bytes, 0)); assertThrows(IllegalArgumentException.class, () -> EndianUtils.readSwappedUnsignedShort(bytes, 0)); assertThrows(IllegalArgumentException.class, () -> EndianUtils.writeSwappedInteger(bytes, 0, 0)); assertThrows(IllegalArgumentException.class, () -> EndianUtils.writeSwappedLong(bytes, 0, 0L)); assertThrows(IllegalArgumentException.class, () -> EndianUtils.writeSwappedShort(bytes, 0, (short) 0)); } @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 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 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 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 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 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 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 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 ); } @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 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 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 ) ); } /** * 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 ); } // 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"); } @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] ); } @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 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 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 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] ); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/FileCleanerTest.java0100644 0000000 0000000 00000002130 14603604450 027440 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; /** * Tests {@link FileCleaner}. */ @SuppressWarnings("deprecation") // testing deprecated class public class FileCleanerTest extends FileCleaningTrackerTest { @Override protected FileCleaningTracker newInstance() { return FileCleaner.getInstance(); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/FileCleaningTrackerTest.java0100644 0000000 0000000 00000033027 14603604450 031134 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 java.io.BufferedOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; import java.lang.ref.ReferenceQueue; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import org.apache.commons.io.file.AbstractTempDirTest; 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; /** * Tests {@link FileCleaningTracker}. */ public class FileCleaningTrackerTest extends AbstractTempDirTest { private File testFile; private Path testPath; private FileCleaningTracker theInstance; RandomAccessFile createRandomAccessFile() throws FileNotFoundException { return RandomAccessFileMode.READ_WRITE.create(testFile); } protected FileCleaningTracker newInstance() { return new FileCleaningTracker(); } private void pauseForDeleteToComplete(File file) { int count = 0; while (file.exists() && count++ < 40) { TestUtils.sleepQuietly(500L); file = new File(file.getPath()); } } private void pauseForDeleteToComplete(Path file) { int count = 0; while (Files.exists(file) && count++ < 40) { TestUtils.sleepQuietly(500L); file = Paths.get(file.toAbsolutePath().toString()); } } @BeforeEach public void setUp() { testFile = new File(tempDirFile, "file-test.txt"); testPath = testFile.toPath(); theInstance = newInstance(); } private String showFailures() { if (theInstance.deleteFailures.size() == 1) { return "[Delete Failed: " + theInstance.deleteFailures.get(0) + "]"; } return "[Delete Failures: " + theInstance.deleteFailures.size() + "]"; } @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 testFileCleanerDirectory_ForceStrategy_FileSource() throws Exception { if (!testFile.getParentFile().exists()) { throw new IOException("Cannot create file " + testFile + " as the parent directory does not exist"); } try (BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(testFile.toPath()))) { TestUtils.generateTestData(output, 100); } assertTrue(testFile.exists()); assertTrue(tempDirFile.exists()); Object obj = new Object(); assertEquals(0, theInstance.getTrackCount()); theInstance.track(tempDirFile, 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 testFileCleanerDirectory_ForceStrategy_PathSource() throws Exception { if (!Files.exists(testPath.getParent())) { throw new IOException("Cannot create file " + testPath + " as the parent directory does not exist"); } try (BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(testPath))) { TestUtils.generateTestData(output, 100); } assertTrue(Files.exists(testPath)); assertTrue(Files.exists(tempDirPath)); Object obj = new Object(); assertEquals(0, theInstance.getTrackCount()); theInstance.track(tempDirPath, obj, FileDeleteStrategy.FORCE); assertEquals(1, theInstance.getTrackCount()); obj = null; waitUntilTrackCount(); pauseForDeleteToComplete(testPath.getParent()); assertEquals(0, theInstance.getTrackCount()); assertFalse(Files.exists(testPath), showFailures()); assertFalse(Files.exists(testPath.getParent()), showFailures()); } @Test public void testFileCleanerDirectory_NullStrategy() throws Exception { TestUtils.createFile(testFile, 100); assertTrue(testFile.exists()); assertTrue(tempDirFile.exists()); Object obj = new Object(); assertEquals(0, theInstance.getTrackCount()); theInstance.track(tempDirFile, 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 testFileCleanerDirectoryFileSource() throws Exception { TestUtils.createFile(testFile, 100); assertTrue(testFile.exists()); assertTrue(tempDirFile.exists()); Object obj = new Object(); assertEquals(0, theInstance.getTrackCount()); theInstance.track(tempDirFile, 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 testFileCleanerDirectoryPathSource() throws Exception { TestUtils.createFile(testPath, 100); assertTrue(Files.exists(testPath)); assertTrue(Files.exists(tempDirPath)); Object obj = new Object(); assertEquals(0, theInstance.getTrackCount()); theInstance.track(tempDirPath, obj); assertEquals(1, theInstance.getTrackCount()); obj = null; waitUntilTrackCount(); assertEquals(0, theInstance.getTrackCount()); assertTrue(Files.exists(testPath)); // not deleted, as dir not empty assertTrue(Files.exists(testPath.getParent())); // not deleted, as dir not empty } @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(); assertThrows(IllegalStateException.class, () -> theInstance.track(path, marker)); assertTrue(theInstance.exitWhenFinished); assertNull(theInstance.reaper); } @Test public void testFileCleanerExitWhenFinished1() throws Exception { final String path = testFile.getPath(); assertFalse(testFile.exists(), "1-testFile exists: " + testFile); // Do NOT used a try-with-resources statement here or the test will fail. RandomAccessFile raf = createRandomAccessFile(); assertTrue(testFile.exists(), "2-testFile exists"); assertEquals(0, theInstance.getTrackCount(), "3-Track Count"); theInstance.track(path, raf); 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"); raf.close(); testFile = null; raf = 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 = createRandomAccessFile(); 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()); } @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 testFileCleanerFile() throws Exception { final String path = testFile.getPath(); assertFalse(testFile.exists()); RandomAccessFile r = createRandomAccessFile(); 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 testFileCleanerNull() { assertThrows(NullPointerException.class, () -> theInstance.track((File) null, new Object())); assertThrows(NullPointerException.class, () -> theInstance.track((File) null, new Object(), FileDeleteStrategy.NORMAL)); assertThrows(NullPointerException.class, () -> theInstance.track((String) null, new Object())); assertThrows(NullPointerException.class, () -> theInstance.track((String) null, new Object(), FileDeleteStrategy.NORMAL)); } 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 test with less memory (-Xmx)"); } } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/FileDeleteStrategyTest.java0100644 0000000 0000000 00000012620 14603604450 031021 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.assertThrows; 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.Test; import org.junit.jupiter.api.io.TempDir; /** * Tests {@link FileDeleteStrategy}. */ public class FileDeleteStrategyTest { @TempDir public File temporaryFolder; @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 (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 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 (BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(subFile.toPath()))) { TestUtils.generateTestData(output, 16); } assertTrue(subDir.exists()); assertTrue(subFile.exists()); // delete dir assertThrows(IOException.class, () -> FileDeleteStrategy.NORMAL.delete(subDir)); 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 testDeleteNull() throws Exception { assertThrows(NullPointerException.class, () -> FileDeleteStrategy.NORMAL.delete(null)); assertTrue(FileDeleteStrategy.NORMAL.deleteQuietly(null)); } @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 (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 testToString() { assertEquals("FileDeleteStrategy[Normal]", FileDeleteStrategy.NORMAL.toString()); assertEquals("FileDeleteStrategy[Force]", FileDeleteStrategy.FORCE.toString()); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/FileSystemTest.java0100644 0000000 0000000 00000013670 14603604450 027366 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; import org.junit.jupiter.api.condition.EnabledOnOs; import org.junit.jupiter.api.condition.OS; /** * Tests {@link FileSystem}. */ public class FileSystemTest { @Test public void testGetBlockSize() { assertTrue(FileSystem.getCurrent().getBlockSize() >= 0); } @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 @EnabledOnOs(OS.WINDOWS) public void testIsReservedFileNameOnWindows() { final FileSystem fs = FileSystem.WINDOWS; for (final String candidate : fs.getReservedFileNames()) { // System.out.printf("Reserved %s exists: %s%n", candidate, Files.exists(Paths.get(candidate))); assertTrue(fs.isReservedFileName(candidate)); assertTrue(fs.isReservedFileName(candidate + ".txt"), candidate); } // This can hang when trying to create files for some reserved names, but it is interesting to keep // // for (final String candidate : fs.getReservedFileNames()) { // System.out.printf("Testing %s%n", candidate); // assertTrue(fs.isReservedFileName(candidate)); // final Path path = Paths.get(candidate); // final boolean exists = Files.exists(path); // try { // PathUtils.writeString(path, "Hello World!", StandardCharsets.UTF_8); // } catch (IOException ignored) { // // Asking to create a reserved file either: // // - Throws an exception, for example "AUX" // // - Is a NOOP, for example "COM3" // } // assertEquals(exists, Files.exists(path), path.toString()); // } } @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.16.1-src/src/test/java/org/apache/commons/io/FileSystemUtilsTest.java0100644 0000000 0000000 00000007360 14603604450 030406 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; /** * Tests {@link FileSystemUtils}. */ @SuppressWarnings("deprecation") // testing deprecated class public class FileSystemUtilsTest { static char[] getIllegalFileNameChars() { return FileSystem.getCurrent().getIllegalFileNameChars(); } @ParameterizedTest @MethodSource("getIllegalFileNameChars") public void testGetFreeSpace_IllegalFileName(final char illegalFileNameChar) throws Exception { assertThrows(IllegalArgumentException.class, () -> FileSystemUtils.freeSpace("\\ \"" + illegalFileNameChar)); } @Test public void testGetFreeSpace_IllegalFileNames() throws Exception { assertThrows(IllegalArgumentException.class, () -> FileSystemUtils.freeSpace("\\ \"")); } @Test public void testGetFreeSpace_String() throws Exception { assertThrows(NullPointerException.class, () -> FileSystemUtils.freeSpace(null)); assertThrows(IllegalArgumentException.class, () -> FileSystemUtils.freeSpace("this directory does not exist, at all.")); // "" means current dir. assertTrue(FileSystemUtils.freeSpace("") > 0); assertTrue(FileSystemUtils.freeSpace("target") > 0); // files worked as well in previous versions. assertTrue(FileSystemUtils.freeSpace("pom.xml") > 0); } @Test public void testGetFreeSpaceKb() throws Exception { assertTrue(FileSystemUtils.freeSpaceKb() > 0); } @Test public void testGetFreeSpaceKb_long() throws Exception { assertTrue(FileSystemUtils.freeSpaceKb(0) > 0); } @Test public void testGetFreeSpaceKb_String() throws Exception { assertThrows(NullPointerException.class, () -> FileSystemUtils.freeSpaceKb(null)); assertThrows(IllegalArgumentException.class, () -> FileSystemUtils.freeSpaceKb("this directory does not exist, at all.")); // "" means current dir. assertTrue(FileSystemUtils.freeSpaceKb("") > 0); assertTrue(FileSystemUtils.freeSpaceKb("target") > 0); // files worked as well in previous versions. assertTrue(FileSystemUtils.freeSpaceKb("pom.xml") > 0); } @Test public void testGetFreeSpaceKb_String_long() throws Exception { assertThrows(NullPointerException.class, () -> FileSystemUtils.freeSpaceKb(null, 0)); assertThrows(IllegalArgumentException.class, () -> FileSystemUtils.freeSpaceKb("this directory does not exist, at all.", 0)); // "" means current dir. assertTrue(FileSystemUtils.freeSpaceKb("", 0) > 0); assertTrue(FileSystemUtils.freeSpaceKb("target", 0) > 0); // files worked as well in previous versions. assertTrue(FileSystemUtils.freeSpaceKb("pom.xml", 0) > 0); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/FileUtilsCleanDirectoryTest.java0100644 0000000 0000000 00000010413 14603604450 032022 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 static org.junit.jupiter.api.Assertions.assertTrue; 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.apache.commons.io.file.AbstractTempDirTest; import org.apache.commons.lang3.ArrayUtils; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.DisabledOnOs; import org.junit.jupiter.api.condition.OS; /** * 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 FileUtilsCleanDirectoryTest extends AbstractTempDirTest { /** 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(ArrayUtils.EMPTY_STRING_ARRAY)); } catch (final IOException e) { return false; } return proc.waitFor() == 0; } @DisabledOnOs(OS.WINDOWS) @Test public void testCleanDirectoryToForceDelete() throws Exception { final File file = new File(tempDirFile, "restricted"); FileUtils.touch(file); // 300 = owner: WE. // 500 = owner: RE. // 700 = owner: RWE. assumeTrue(chmod(tempDirFile, 700, false)); // cleanDirectory calls forceDelete FileUtils.cleanDirectory(tempDirFile); } @Test public void testCleanEmpty() throws Exception { assertEquals(0, tempDirFile.list().length); FileUtils.cleanDirectory(tempDirFile); assertEquals(0, tempDirFile.list().length); } @Test public void testDeletesNested() throws Exception { final File nested = new File(tempDirFile, "nested"); assertTrue(nested.mkdirs()); FileUtils.touch(new File(nested, "file")); assertEquals(1, tempDirFile.list().length); FileUtils.cleanDirectory(tempDirFile); assertEquals(0, tempDirFile.list().length); } @Test public void testDeletesRegular() throws Exception { FileUtils.touch(new File(tempDirFile, "regular")); FileUtils.touch(new File(tempDirFile, ".hidden")); assertEquals(2, tempDirFile.list().length); FileUtils.cleanDirectory(tempDirFile); assertEquals(0, tempDirFile.list().length); } @DisabledOnOs(OS.WINDOWS) @Test public void testThrowsOnNullList() throws Exception { // test won't work if we can't restrict permissions on the // directory, so skip it. assumeTrue(chmod(tempDirFile, 0, false)); try { // cleanDirectory calls forceDelete final IOException e = assertThrows(IOException.class, () -> FileUtils.cleanDirectory(tempDirFile)); assertEquals("Unknown I/O error listing contents of directory: " + tempDirFile.getAbsolutePath(), e.getMessage()); } finally { chmod(tempDirFile, 755, false); } } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/FileUtilsCleanSymlinksTest.java0100644 0000000 0000000 00000023133 14603604450 031672 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.apache.commons.lang3.ArrayUtils; 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 FileUtilsCleanSymlinksTest { @TempDir public File top; 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(ArrayUtils.EMPTY_STRING_ARRAY)); return proc.waitFor() == 0; } @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 // should clean the contents of this but not recurse into other links FileUtils.cleanDirectory(symlinkParentDirectory); 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 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 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)); } @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 nonExistentFile = new File(top, "non-existent"); final File symlinkFile = new File(top, "fakeinner"); final File badSymlinkInPathFile = new File(symlinkFile, "fakeinner"); final File nonExistentParentFile = new File("non-existent", "file"); assertTrue(setupSymlink(nonExistentFile, symlinkFile)); assertTrue(FileUtils.isSymlink(symlinkFile)); assertFalse(FileUtils.isSymlink(nonExistentFile)); assertFalse(FileUtils.isSymlink(nonExistentParentFile)); assertFalse(FileUtils.isSymlink(badSymlinkInPathFile)); } @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 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); } } ././@LongLink0100644 0000000 0000000 00000000145 14603604450 011635 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/FileUtilsCopyDirectoryToDirectoryTest.javacommons-io-2.16.1-src/src/test/java/org/apache/commons/io/FileUtilsCopyDirectoryToDirectoryTest.java0100644 0000000 0000000 00000012346 14603604450 034111 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import org.apache.commons.io.file.PathUtils; import org.apache.commons.io.file.TempFile; 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 FileUtilsCopyDirectoryToDirectoryTest { 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 testCopyDirectoryToDirectoryThrowsIllegalArgumentExceptionWithCorrectMessageWhenDstDirIsNotDirectory() 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 testCopyDirectoryToDirectoryThrowsIllegalExceptionWithCorrectMessageWhenSrcDirIsNotDirectory() throws IOException { try (TempFile srcDir = TempFile.create("notadirectory", null)) { final File destDir = new File(temporaryFolder, "destinationDirectory"); destDir.mkdirs(); final String expectedMessage = String.format("Parameter 'srcDir' is not a directory: '%s'", srcDir); assertExceptionTypeAndMessage(srcDir.toFile(), destDir, IllegalArgumentException.class, expectedMessage); } } @Test public void testCopyDirectoryToDirectoryThrowsNullPointerExceptionWithCorrectMessageWhenDstDirIsNull() { final File srcDir = new File(temporaryFolder, "sourceDirectory"); srcDir.mkdir(); final File destDir = null; assertExceptionTypeAndMessage(srcDir, destDir, NullPointerException.class, "destinationDir"); } @Test public void testCopyDirectoryToDirectoryThrowsNullPointerExceptionWithCorrectMessageWhenSrcDirIsNull() { final File srcDir = null; final File destinationDirectory = new File(temporaryFolder, "destinationDirectory"); destinationDirectory.mkdir(); assertExceptionTypeAndMessage(srcDir, destinationDirectory, NullPointerException.class, "sourceDir"); } @Test public void testCopyFileAndCheckAcl() throws IOException { try (TempFile sourcePath = TempFile.create("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.get(), destPath); // FileUtils.copyFile(sourcePath.toFile(), destPath.toFile()); assertAclEntryList(sourcePath.get(), destPath); // FileUtils.copyFile(sourcePath.toFile(), destPath.toFile(), true, StandardCopyOption.REPLACE_EXISTING); assertAclEntryList(sourcePath.get(), destPath); // FileUtils.copyFile(sourcePath.toFile(), destPath.toFile(), true, StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.COPY_ATTRIBUTES); assertAclEntryList(sourcePath.get(), destPath); } } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/FileUtilsCopyToFileTest.java0100644 0000000 0000000 00000006431 14603604450 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; 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; /** * Tests {@link FileUtils}. */ public class FileUtilsCopyToFileTest { private final 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; } } @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 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"); } } /** * 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"); } } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/FileUtilsDeleteDirectoryLinuxTest.java0100644 0000000 0000000 00000010217 14603604450 033224 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 static org.junit.jupiter.api.Assertions.assertTrue; 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.apache.commons.lang3.ArrayUtils; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.DisabledOnOs; import org.junit.jupiter.api.condition.OS; /** * Tests {@link FileUtils}. */ @DisabledOnOs({OS.WINDOWS, OS.MAC}) public class FileUtilsDeleteDirectoryLinuxTest extends AbstractFileUtilsDeleteDirectoryTest { /** 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(ArrayUtils.EMPTY_STRING_ARRAY)); } 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(ArrayUtils.EMPTY_STRING_ARRAY)); 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 final IOExceptionList ioExceptionList = (IOExceptionList) assertThrows(IOException.class, () -> FileUtils.deleteDirectory(nested)); final String message = ioExceptionList.getCause(0).getMessage(); assertTrue(message.endsWith("Cannot delete file: " + file.getAbsolutePath()), message); } 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 won't work if we can't restrict permissions on the // directory, so skip it. assumeTrue(chmod(nested, 0, false)); try { // cleanDirectory calls forceDelete final IOException e = assertThrows(IOException.class, () -> FileUtils.deleteDirectory(nested)); 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); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/FileUtilsDeleteDirectoryWindowsTest.java0100644 0000000 0000000 00000004262 14603604450 033562 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.apache.commons.lang3.ArrayUtils; 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 FileUtilsDeleteDirectoryWindowsTest extends AbstractFileUtilsDeleteDirectoryTest { @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(ArrayUtils.EMPTY_STRING_ARRAY)); 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.16.1-src/src/test/java/org/apache/commons/io/FileUtilsDirectoryContainsTest.java0100644 0000000 0000000 00000014452 14603604450 032565 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.File; import java.io.FileNotFoundException; 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) */ public class FileUtilsDirectoryContainsTest { 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() { final File dir = new File("DOESNOTEXIST"); assertFalse(dir.exists()); assertThrows(FileNotFoundException.class, () -> FileUtils.directoryContains(dir, file1)); } @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 testFileHavingSamePrefixBug() throws IOException { final File foo = new File(top, "foo"); final File foobar = new File(top, "foobar"); final File fooTxt = new File(top, "foo.txt"); foo.mkdir(); foobar.mkdir(); FileUtils.touch(fooTxt); assertFalse(FileUtils.directoryContains(foo, foobar)); assertFalse(FileUtils.directoryContains(foo, fooTxt)); } @Test public void testIO466() throws IOException { final File fooFile = new File(directory1.getParent(), "directory1.txt"); assertFalse(FileUtils.directoryContains(directory1, fooFile)); } @Test public void testSameFile() { assertThrows(IllegalArgumentException.class, () -> FileUtils.directoryContains(file1, file1)); } @Test public void testUnrealizedContainment() { final File dir = new File("DOESNOTEXIST"); final File file = new File(dir, "DOESNOTEXIST2"); assertFalse(dir.exists()); assertFalse(file.exists()); assertThrows(FileNotFoundException.class, () -> FileUtils.directoryContains(dir, file)); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/FileUtilsFileNewerTest.java0100644 0000000 0000000 00000015655 14603604450 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; 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.nio.file.attribute.FileTime; import java.util.Date; import org.apache.commons.io.file.attribute.FileTimes; 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; /** * Tests {@link FileUtils}. */ public class FileUtilsFileNewerTest { // Test data private static final int FILE1_SIZE = 1; private static final int FILE2_SIZE = 1024 * 4 + 1; @TempDir public File temporaryFolder; 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 (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 (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 FileTime fileLastModified = Files.getLastModifiedTime(testFile1.toPath()); final long TWO_SECOND = 2; testIsFileNewer("two second earlier is not newer", testFile1, FileTimes.plusSeconds(fileLastModified, TWO_SECOND), false); testIsFileNewer("same time is not newer", testFile1, fileLastModified, false); testIsFileNewer("two second later is newer", testFile1, FileTimes.minusSeconds(fileLastModified, TWO_SECOND), true); } /** * 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 fileTime the time reference measured in milliseconds since the epoch * @param wantedResult the expected result * @throws IOException if an I/O error occurs. */ protected void testIsFileNewer(final String description, final File file, final FileTime fileTime, final boolean wantedResult) throws IOException { assertEquals(wantedResult, FileUtils.isFileNewer(file, fileTime), () -> description + " - FileTime"); assertEquals(wantedResult, FileUtils.isFileNewer(file, fileTime.toInstant()), () -> description + " - Instant"); final File temporaryFile = testFile2; Files.setLastModifiedTime(temporaryFile.toPath(), fileTime); assertEquals(fileTime, Files.getLastModifiedTime(temporaryFile.toPath()), "The temporary file hasn't the right last modification date"); assertEquals(wantedResult, FileUtils.isFileNewer(file, temporaryFile), () -> description + " - file"); } /** * 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.lastModifiedFileTime(testFile2), false); } /** * 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, 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, 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.16.1-src/src/test/java/org/apache/commons/io/FileUtilsListFilesTest.java0100644 0000000 0000000 00000020632 14603604450 031015 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.File; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.stream.Collectors; import org.apache.commons.io.filefilter.FileFilterUtils; import org.apache.commons.io.filefilter.IOFileFilter; import org.apache.commons.lang3.function.Consumers; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; /** * Tests FileUtils.listFiles() methods. */ public class FileUtilsListFilesTest { @TempDir public File temporaryFolder; private Collection filesToFilenames(final Collection files) { return files.stream().map(File::getName).collect(Collectors.toList()); } /** * Consumes and closes the underlying stream. * * @param files The iterator to consume. * @return a new collection. */ private Collection filesToFilenames(final Iterator files) { final Collection fileNames = new ArrayList<>(); // Iterator.forEachRemaining() closes the underlying stream. files.forEachRemaining(f -> fileNames.add(f.getName())); return fileNames; } @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); } @Test public void testIterateFilesByExtension() { final String[] extensions = { "xml", "txt" }; Iterator files = FileUtils.iterateFiles(temporaryFolder, extensions, false); try { final Collection fileNames = filesToFilenames(files); assertEquals(1, fileNames.size()); assertTrue(fileNames.contains("dummy-build.xml")); assertFalse(fileNames.contains("README")); assertFalse(fileNames.contains("dummy-file.txt")); } finally { // Backstop in case filesToFilenames() failure. files.forEachRemaining(Consumers.nop()); } try { files = FileUtils.iterateFiles(temporaryFolder, extensions, true); final Collection fileNames = filesToFilenames(files); assertEquals(4, fileNames.size()); assertTrue(fileNames.contains("dummy-file.txt")); assertFalse(fileNames.contains("dummy-index.html")); } finally { // Backstop in case filesToFilenames() failure. files.forEachRemaining(Consumers.nop()); } files = FileUtils.iterateFiles(temporaryFolder, null, false); try { final Collection fileNames = filesToFilenames(files); assertEquals(2, fileNames.size()); assertTrue(fileNames.contains("dummy-build.xml")); assertTrue(fileNames.contains("README")); assertFalse(fileNames.contains("dummy-file.txt")); } finally { // Backstop in case filesToFilenames() failure. files.forEachRemaining(Consumers.nop()); } } @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"); assertThrows(NullPointerException.class, () -> FileUtils.listFiles(temporaryFolder, null, null)); } @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")); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/FileUtilsTest.java0100644 0000000 0000000 00000465657 14603604450 027222 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 static org.junit.jupiter.api.Assumptions.assumeFalse; import static org.junit.jupiter.api.Assumptions.assumeTrue; 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.io.UncheckedIOException; import java.math.BigInteger; import java.net.URL; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.charset.UnsupportedCharsetException; import java.nio.file.Files; import java.nio.file.LinkOption; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.nio.file.attribute.AclFileAttributeView; import java.nio.file.attribute.FileTime; import java.nio.file.attribute.PosixFilePermission; import java.nio.file.attribute.PosixFilePermissions; import java.time.Instant; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.OffsetDateTime; import java.time.OffsetTime; import java.time.ZoneId; import java.time.ZoneOffset; 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.Set; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import java.util.zip.CRC32; import java.util.zip.Checksum; import org.apache.commons.io.file.AbstractTempDirTest; import org.apache.commons.io.file.Counters.PathCounters; import org.apache.commons.io.file.PathUtils; import org.apache.commons.io.file.TempDirectory; import org.apache.commons.io.file.TempFile; 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.condition.EnabledIf; import org.junit.jupiter.api.condition.EnabledOnOs; import org.junit.jupiter.api.condition.OS; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; /** * Tests {@link FileUtils}. */ @SuppressWarnings({"deprecation", "ResultOfMethodCallIgnored"}) // unit tests include tests of many deprecated methods public class FileUtilsTest extends AbstractTempDirTest { /** * 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; } } private static final Path DIR_SIZE_1 = Paths.get("src/test/resources/org/apache/commons/io/dirs-1-file-size-1"); private static final String UTF_8 = StandardCharsets.UTF_8.name(); /** Test data. */ private static final long DATE3 = 1_000_000_002_000L; /** Test data. */ private static final long DATE2 = 1_000_000_001_000L; /** Test data. */ private static final long DATE1 = 1_000_000_000_000L; /** * 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(); private File testFile1; private File testFile2; private long testFile1Size; private long testFile2Size; private void assertContentMatchesAfterCopyURLToFileFor(final String resourceName, final File destination) throws IOException { FileUtils.copyURLToFile(getClass().getResource(resourceName), destination); try (InputStream fis = Files.newInputStream(destination.toPath()); InputStream expected = getClass().getResourceAsStream(resourceName)) { assertTrue(IOUtils.contentEquals(expected, fis), "Content is not equal."); } } 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 Path createCircularOsSymLink(final String linkName, final String targetName) throws IOException { return Files.createSymbolicLink(Paths.get(linkName), Paths.get(targetName)); } /** * May throw java.nio.file.FileSystemException: C:\Users\...\FileUtilsTestCase\cycle: A required privilege is not held * by the client. On Windows, you are fine if you run a terminal with admin karma. */ private void createCircularSymLink(final File file) throws IOException { assertTrue(file.exists()); final String linkName = file + "/cycle"; final String targetName = file + "/.."; assertTrue(file.exists()); final Path linkPath = Paths.get(linkName); assertFalse(Files.exists(linkPath)); final Path targetPath = Paths.get(targetName); assertTrue(Files.exists(targetPath)); try { // May throw java.nio.file.FileSystemException: C:\Users\...\FileUtilsTestCase\cycle: A required privilege is not held by the client. // On Windows, you are fine if you run a terminal with admin karma. Files.createSymbolicLink(linkPath, targetPath); } catch (final UnsupportedOperationException e) { createCircularOsSymLink(linkName, targetName); } // Sanity check: assertTrue(Files.isSymbolicLink(linkPath), () -> "Expected a sym link here: " + linkName); } private void createFilesForTestCopyDirectory(final File grandParentDir, final File parentDir, final File childDir) throws IOException { 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 Path createTempSymlinkedRelativeDir() throws IOException { final Path targetDir = tempDirPath.resolve("subdir"); final Path symlinkDir = tempDirPath.resolve("symlinked-dir"); Files.createDirectory(targetDir); Files.createSymbolicLink(symlinkDir, targetDir); return symlinkDir; } private Set getFilePathSet(final List files) { return files.stream().map(f -> { try { return f.getCanonicalPath(); } catch (final IOException e) { throw new RuntimeException(e); } }).collect(Collectors.toSet()); } 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 = FileUtils.iterateFilesAndDirs(dir, fileFilter, dirFilter); int filesCount = 0; 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); } } private 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); } @BeforeEach public void setUp() throws Exception { testFile1 = new File(tempDirFile, "file1-test.txt"); testFile2 = new File(tempDirFile, "file1a-test.txt"); testFile1Size = testFile1.length(); testFile2Size = testFile2.length(); if (!testFile1.getParentFile().exists()) { fail("Cannot create file " + testFile1 + " as the parent directory does not exist"); } try (BufferedOutputStream output3 = new BufferedOutputStream(Files.newOutputStream(testFile1.toPath()))) { TestUtils.generateTestData(output3, testFile1Size); } if (!testFile2.getParentFile().exists()) { fail("Cannot create file " + testFile2 + " as the parent directory does not exist"); } try (BufferedOutputStream output2 = new BufferedOutputStream(Files.newOutputStream(testFile2.toPath()))) { TestUtils.generateTestData(output2, testFile2Size); } FileUtils.deleteDirectory(tempDirFile); tempDirFile.mkdirs(); if (!testFile1.getParentFile().exists()) { fail("Cannot create file " + testFile1 + " as the parent directory does not exist"); } try (BufferedOutputStream output1 = new BufferedOutputStream(Files.newOutputStream(testFile1.toPath()))) { TestUtils.generateTestData(output1, testFile1Size); } if (!testFile2.getParentFile().exists()) { fail("Cannot create file " + testFile2 + " as the parent directory does not exist"); } try (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(tempDirFile, "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(tempDirFile, "subdir"); directory.mkdirs(); assertThrows(IOException.class, () -> FileUtils.openInputStream(directory)); } @Test public void test_openInputStream_notExists() { final File directory = new File(tempDirFile, "test.txt"); assertThrows(IOException.class, () -> FileUtils.openInputStream(directory)); } @Test public void test_openOutputStream_exists() throws Exception { final File file = new File(tempDirFile, "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(tempDirFile, "subdir"); directory.mkdirs(); assertThrows(IllegalArgumentException.class, () -> FileUtils.openOutputStream(directory)); } /** * Requires admin privileges on Windows. * * @throws Exception For example java.nio.file.FileSystemException: * C:\Users\you\AppData\Local\Temp\junit2324629522183300191\FileUtilsTest8613879743106252609\symlinked-dir: A required privilege is * not held by the client. */ @Test public void test_openOutputStream_intoExistingSymlinkedDir() throws Exception { final Path symlinkedDir = createTempSymlinkedRelativeDir(); final File file = symlinkedDir.resolve("test.txt").toFile(); try (FileOutputStream out = FileUtils.openOutputStream(file)) { out.write(0); } assertTrue(file.exists()); } @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(tempDirFile, "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(tempDirFile, "a/" + longStr + "/test.txt"); assertThrows(IOException.class, () -> FileUtils.openOutputStream(file)); } // 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(1024L * 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 testByteCountToDisplaySizeNumber() { assertEquals("0 bytes", FileUtils.byteCountToDisplaySize(Integer.valueOf(0))); assertEquals("1 bytes", FileUtils.byteCountToDisplaySize(Integer.valueOf(1))); assertEquals("1023 bytes", FileUtils.byteCountToDisplaySize(Integer.valueOf(1023))); assertEquals("1 KB", FileUtils.byteCountToDisplaySize(Integer.valueOf(1024))); assertEquals("1 KB", FileUtils.byteCountToDisplaySize(Integer.valueOf(1025))); assertEquals("1023 KB", FileUtils.byteCountToDisplaySize(Long.valueOf(1024 * 1023))); assertEquals("1 MB", FileUtils.byteCountToDisplaySize(Long.valueOf(1024 * 1024))); assertEquals("1 MB", FileUtils.byteCountToDisplaySize(Long.valueOf(1024 * 1025))); assertEquals("1023 MB", FileUtils.byteCountToDisplaySize(Long.valueOf(1024 * 1024 * 1023))); assertEquals("1 GB", FileUtils.byteCountToDisplaySize(Long.valueOf(1024 * 1024 * 1024))); assertEquals("1 GB", FileUtils.byteCountToDisplaySize(Long.valueOf(1024 * 1024 * 1025))); assertEquals("2 GB", FileUtils.byteCountToDisplaySize(Long.valueOf(1024L * 1024 * 1024 * 2))); assertEquals("1 GB", FileUtils.byteCountToDisplaySize(Long.valueOf(1024L * 1024 * 1024 * 2 - 1))); assertEquals("1 TB", FileUtils.byteCountToDisplaySize(Long.valueOf(1024L * 1024 * 1024 * 1024))); assertEquals("1 PB", FileUtils.byteCountToDisplaySize(Long.valueOf(1024L * 1024 * 1024 * 1024 * 1024))); assertEquals("1 EB", FileUtils.byteCountToDisplaySize(Long.valueOf(1024L * 1024 * 1024 * 1024 * 1024 * 1024))); assertEquals("7 EB", FileUtils.byteCountToDisplaySize(Long.valueOf(Long.MAX_VALUE))); // Other MAX_VALUEs assertEquals("63 KB", FileUtils.byteCountToDisplaySize(Integer.valueOf(Character.MAX_VALUE))); assertEquals("31 KB", FileUtils.byteCountToDisplaySize(Short.valueOf(Short.MAX_VALUE))); assertEquals("1 GB", FileUtils.byteCountToDisplaySize(Integer.valueOf(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(tempDirFile, "checksum-test.txt"); FileUtils.writeStringToFile(file, text, StandardCharsets.US_ASCII.name()); // 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(tempDirFile, "checksum-test.txt"); FileUtils.writeStringToFile(file, text, StandardCharsets.US_ASCII.name()); // 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(tempDirFile, "checksum-test.txt"); FileUtils.writeStringToFile(file1, text1, StandardCharsets.US_ASCII.name()); // create a second test file final String text2 = "To be or not to be - Shakespeare"; final File file2 = new File(tempDirFile, "checksum-test2.txt"); FileUtils.writeStringToFile(file2, text2, StandardCharsets.US_ASCII.name()); // 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() { assertThrows(IllegalArgumentException.class, () -> FileUtils.checksum(FileUtils.current(), new CRC32())); } @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(tempDirFile, "checksum-test.txt"); FileUtils.writeStringToFile(file, text, StandardCharsets.US_ASCII.name()); assertThrows(NullPointerException.class, () -> FileUtils.checksum(file, null)); } @Test public void testChecksumOnNullFile() { assertThrows(NullPointerException.class, () -> FileUtils.checksum(null, new CRC32())); } // 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(tempDirFile, getName()); final File file2 = new File(tempDirFile, 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(tempDirFile, tempDirFile)); // Different files final File objFile1 = new File(tempDirFile, getName() + ".object"); FileUtils.copyURLToFile( getClass().getResource("/java/lang/Object.class"), objFile1); final File objFile1b = new File(tempDirFile, getName() + ".object2"); FileUtils.copyURLToFile( getClass().getResource("/java/lang/Object.class"), objFile1b); final File objFile2 = new File(tempDirFile, getName() + ".collection"); 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)); } @Test public void testContentEqualsIgnoreEOL() throws Exception { // Non-existent files final File file1 = new File(tempDirFile, getName()); final File file2 = new File(tempDirFile, 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(tempDirFile, tempDirFile, null)); // Different files final File tfile1 = new File(tempDirFile, getName() + ".txt1"); FileUtils.write(tfile1, "123\r"); final File tfile2 = new File(tempDirFile, getName() + ".txt2"); FileUtils.write(tfile2, "123\n"); final File tfile3 = new File(tempDirFile, getName() + ".collection"); 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)); } /** * See what happens when copyDirectory copies a directory that is a symlink * to another directory containing non-symlinked files. * This is a characterization test to explore current behavior, and arguably * represents a bug. This behavior, and the test, is likely to change * and should not be relied on. */ @Test public void testCopyDir_symLink() throws Exception { // Make a directory final File realDirectory = new File(tempDirFile, "real_directory"); realDirectory.mkdir(); final File content = new File(realDirectory, "hello.txt"); FileUtils.writeStringToFile(content, "HELLO WORLD", "UTF8"); // Make a symlink to the directory final Path linkPath = tempDirFile.toPath().resolve("link_to_directory"); Files.createSymbolicLink(linkPath, realDirectory.toPath()); // Now copy symlink final File destination = new File(tempDirFile, "destination"); // Is the copy a symlink or an actual directory? FileUtils.copyDirectory(linkPath.toFile(), destination); // delete the original file so that if we can read the bytes from the // copied directory it's definitely been copied, not linked. assumeTrue(content.delete()); assertFalse(Files.isSymbolicLink(destination.toPath())); final File copied_content = new File(destination, "hello.txt"); final String actual = FileUtils.readFileToString(copied_content, "UTF8"); assertEquals("HELLO WORLD", actual); } @Test public void testCopyDir_symLinkCycle() throws Exception { // Make a directory final File topDirectory = new File(tempDirFile, "topDirectory"); topDirectory.mkdir(); final File content = new File(topDirectory, "hello.txt"); FileUtils.writeStringToFile(content, "HELLO WORLD", "UTF8"); final File childDirectory = new File(topDirectory, "child_directory"); childDirectory.mkdir(); // Make a symlink to the top directory final Path linkPath = childDirectory.toPath().resolve("link_to_top"); Files.createSymbolicLink(linkPath, topDirectory.toPath()); // Now copy symlink final File destination = new File(tempDirFile, "destination"); FileUtils.copyDirectory(linkPath.toFile(), destination); // delete the original file so that if we can read the bytes from the // copied directory it's definitely been copied, not linked. assumeTrue(content.delete()); assertFalse(Files.isSymbolicLink(destination.toPath())); final File copied_content = new File(destination, "hello.txt"); final String actual = FileUtils.readFileToString(copied_content, "UTF8"); assertEquals("HELLO WORLD", actual); final File[] copied = destination.listFiles(); assertEquals(2, copied.length); } /** * Tests IO-807. */ @Test public void testCopyDirectory_brokenSymLink() throws IOException { // Make a file final File sourceDirectory = new File(tempDirFile, "source_directory"); sourceDirectory.mkdir(); final File targetFile = new File(sourceDirectory, "hello.txt"); FileUtils.writeStringToFile(targetFile, "HELLO WORLD", "UTF8"); // Make a symlink to the file final Path targetPath = targetFile.toPath(); final Path linkPath = sourceDirectory.toPath().resolve("linkfile"); Files.createSymbolicLink(linkPath, targetPath); assumeTrue(Files.isSymbolicLink(linkPath), () -> "Expected a symlink here: " + linkPath); assumeTrue(Files.exists(linkPath)); assumeTrue(Files.exists(linkPath, LinkOption.NOFOLLOW_LINKS)); // Delete the file file to break the symlink assumeTrue(targetFile.delete()); assumeFalse(Files.exists(linkPath)); assumeTrue(Files.exists(linkPath, LinkOption.NOFOLLOW_LINKS)); // Now copy sourceDirectory, including the broken link, to another directory final File destination = new File(tempDirFile, "destination"); FileUtils.copyDirectory(sourceDirectory, destination); assertTrue(destination.exists()); final Path copiedBrokenSymlink = new File(destination, "linkfile").toPath(); // test for the existence of the copied symbolic link as a link assertTrue(Files.isSymbolicLink(copiedBrokenSymlink)); // shouldn't be able to read through to the source of the link. // If we can, then the link points somewhere other than the deleted file assertFalse(Files.exists(copiedBrokenSymlink)); } @Test public void testCopyDirectory_symLink() throws IOException { // Make a file final File sourceDirectory = new File(tempDirFile, "source_directory"); sourceDirectory.mkdir(); final File targetFile = new File(sourceDirectory, "hello.txt"); FileUtils.writeStringToFile(targetFile, "HELLO WORLD", "UTF8"); // Make a symlink to the file final Path targetPath = targetFile.toPath(); final Path linkPath = sourceDirectory.toPath().resolve("linkfile"); Files.createSymbolicLink(linkPath, targetPath); assumeTrue(Files.isSymbolicLink(linkPath), () -> "Expected a symlink here: " + linkPath); assumeTrue(Files.exists(linkPath)); assumeTrue(Files.exists(linkPath, LinkOption.NOFOLLOW_LINKS)); // Now copy sourceDirectory to another directory final File destination = new File(tempDirFile, "destination"); FileUtils.copyDirectory(sourceDirectory, destination); assertTrue(destination.exists()); final Path copiedSymlink = new File(destination, "linkfile").toPath(); // test for the existence of the copied symbolic link as a link assertTrue(Files.isSymbolicLink(copiedSymlink)); assertTrue(Files.exists(copiedSymlink)); } /** * Test what happens when copyDirectory copies a directory that contains a symlink * to a file outside the copied directory. */ @Test public void testCopyDirectory_symLinkExternalFile() throws Exception { // make a file final File content = new File(tempDirFile, "hello.txt"); FileUtils.writeStringToFile(content, "HELLO WORLD", "UTF8"); // Make a directory final File realDirectory = new File(tempDirFile, "real_directory"); realDirectory.mkdir(); // Make a symlink to the file final Path linkPath = realDirectory.toPath().resolve("link_to_file"); Files.createSymbolicLink(linkPath, content.toPath()); // Now copy the directory final File destination = new File(tempDirFile, "destination"); FileUtils.copyDirectory(realDirectory, destination); // test that the copied directory contains a link to the original file final File copiedLink = new File(destination, "link_to_file"); assertTrue(Files.isSymbolicLink(copiedLink.toPath())); final String actual = FileUtils.readFileToString(copiedLink, "UTF8"); assertEquals("HELLO WORLD", actual); final Path source = Files.readSymbolicLink(copiedLink.toPath()); assertEquals(content.toPath(), source); } @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(tempDirFile, tempDirFile)); // // IOException assertThrows(IOException.class, () -> FileUtils.copyDirectory(new File("doesnt-exist"), new File("a"))); assertThrows(IllegalArgumentException.class, () -> FileUtils.copyDirectory(tempDirFile, testFile1)); } @Test public void testCopyDirectoryFiltered() throws IOException { final File grandParentDir = new File(tempDirFile, "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(tempDirFile, "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(tempDirFile, "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(tempDirFile, "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)); } // Test permission of copied file match destination folder if (!SystemUtils.IS_OS_WINDOWS) { final Set parentPerms = Files.getPosixFilePermissions(target.getParentFile().toPath()); final Set targetPerms = Files.getPosixFilePermissions(target.toPath()); assertEquals(parentPerms, targetPerms); } else { final AclFileAttributeView parentView = Files.getFileAttributeView(target.getParentFile().toPath(), AclFileAttributeView.class); final AclFileAttributeView targetView = Files.getFileAttributeView(target.toPath(), AclFileAttributeView.class); assertEquals(parentView.getAcl(), targetView.getAcl()); } 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); } /** Tests IO-141 */ @Test public void testCopyDirectoryToChild() throws IOException { final File grandParentDir = new File(tempDirFile, "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"); } @Test public void testCopyDirectoryToDirectory_NonExistingDest() throws Exception { if (!testFile1.getParentFile().exists()) { fail("Cannot create file " + testFile1 + " as the parent directory does not exist"); } try (final OutputStream output1 = new BufferedOutputStream(Files.newOutputStream(testFile1.toPath()))) { TestUtils.generateTestData(output1, 1234); } if (!testFile2.getParentFile().exists()) { fail("Cannot create file " + testFile2 + " as the parent directory does not exist"); } try (final OutputStream output = new BufferedOutputStream(Files.newOutputStream(testFile2.toPath()))) { TestUtils.generateTestData(output, 4321); } final File srcDir = tempDirFile; 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(FileUtils.getTempDirectoryPath(), "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 testCopyDirectoryToExistingDest() throws Exception { if (!testFile1.getParentFile().exists()) { fail("Cannot create file " + testFile1 + " as the parent directory does not exist"); } try (final OutputStream output1 = new BufferedOutputStream(Files.newOutputStream(testFile1.toPath()))) { TestUtils.generateTestData(output1, 1234); } if (!testFile2.getParentFile().exists()) { fail("Cannot create file " + testFile2 + " as the parent directory does not exist"); } try (final OutputStream output = new BufferedOutputStream(Files.newOutputStream(testFile2.toPath()))) { TestUtils.generateTestData(output, 4321); } final File srcDir = tempDirFile; 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()); } /** Test IO-141 */ @Test public void testCopyDirectoryToGrandChild() throws IOException { final File grandParentDir = new File(tempDirFile, "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"); } /** Tests IO-217 FileUtils.copyDirectoryToDirectory makes infinite loops */ @Test public void testCopyDirectoryToItself() throws Exception { final File dir = new File(tempDirFile, "itself"); dir.mkdirs(); FileUtils.copyDirectoryToDirectory(dir, dir); assertEquals(1, LIST_WALKER.list(dir).size()); } @Test public void testCopyDirectoryToNonExistingDest() throws Exception { if (!testFile1.getParentFile().exists()) { fail("Cannot create file " + testFile1 + " as the parent directory does not exist"); } try (final OutputStream output1 = new BufferedOutputStream(Files.newOutputStream(testFile1.toPath()))) { TestUtils.generateTestData(output1, 1234); } if (!testFile2.getParentFile().exists()) { fail("Cannot create file " + testFile2 + " as the parent directory does not exist"); } try (final OutputStream output = new BufferedOutputStream(Files.newOutputStream(testFile2.toPath()));) { TestUtils.generateTestData(output, 4321); } final File srcDir = tempDirFile; 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(FileUtils.getTempDirectoryPath(), "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 for https://github.com/apache/commons-io/pull/371. The dir name 'par' is a substring of * the dir name 'parent' which is the parent of the 'parent/child' dir. */ @Test public void testCopyDirectoryWithPotentialFalsePartialMatch() throws IOException { final File grandParentDir = new File(tempDirFile, "grandparent"); final File parentDir = new File(grandParentDir, "parent"); final File parDir = new File(grandParentDir, "par"); final File childDir = new File(parentDir, "child"); createFilesForTestCopyDirectory(grandParentDir, parDir, childDir); final List initFiles = LIST_WALKER.list(grandParentDir); final List parFiles = LIST_WALKER.list(parDir); final long expectedCount = initFiles.size() + parFiles.size(); final long expectedSize = FileUtils.sizeOfDirectory(grandParentDir) + FileUtils.sizeOfDirectory(parDir); FileUtils.copyDirectory(parDir, childDir); final List latestFiles = LIST_WALKER.list(grandParentDir); assertEquals(expectedCount, latestFiles.size()); assertEquals(expectedSize, FileUtils.sizeOfDirectory(grandParentDir)); assertTrue(expectedCount > 0, "Count > 0"); assertTrue(expectedSize > 0, "Size > 0"); final Set initFilePaths = getFilePathSet(initFiles); final Set newFilePaths = getFilePathSet(latestFiles); newFilePaths.removeAll(initFilePaths); assertEquals(parFiles.size(), newFilePaths.size()); } @Test public void testCopyFile_symLink() throws Exception { // Make a file final File sourceDirectory = new File(tempDirFile, "source_directory"); sourceDirectory.mkdir(); final File targetFile = new File(sourceDirectory, "hello.txt"); FileUtils.writeStringToFile(targetFile, "HELLO WORLD", "UTF8"); // Make a symlink to the file final Path targetPath = targetFile.toPath(); final Path linkPath = sourceDirectory.toPath().resolve("linkfile"); Files.createSymbolicLink(linkPath, targetPath); // Now copy symlink to another directory final File destination = new File(tempDirFile, "destination"); FileUtils.copyFile(linkPath.toFile(), destination); assertFalse(Files.isSymbolicLink(destination.toPath())); final String contents = FileUtils.readFileToString(destination, StandardCharsets.UTF_8); assertEquals("HELLO WORLD", contents); } @Test public void testCopyFile1() throws Exception { final File destination = new File(tempDirFile, "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"); } @Test public void testCopyFile1ToDir() throws Exception { final File directory = new File(tempDirFile, "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(tempDirFile, "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"); } @Test public void testCopyFile2ToDir() throws Exception { final File directory = new File(tempDirFile, "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(tempDirFile, "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(tempDirFile, "large.txt"); final File destination = new File(tempDirFile, "copylarge.txt"); if (!largeFile.getParentFile().exists()) { fail("Cannot create file " + largeFile + " as the parent directory does not exist"); } try (final OutputStream output = new BufferedOutputStream(Files.newOutputStream(largeFile.toPath()))) { TestUtils.generateTestData(output, FileUtils.ONE_GB); } FileUtils.copyFile(largeFile, destination); 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 testCopyFileToReadOnlyDirectory() throws Exception { final File directory = new File(tempDirFile, "readonly"); if (!directory.exists()) { assumeTrue(directory.mkdirs()); } assumeTrue(directory.setWritable(false)); assertThrows(IOException.class, () -> FileUtils.copyFileToDirectory(testFile1, directory), "Should not be able to copy a file into a readonly directory"); } @Test public void testCopyToDirectoryWithDirectory() throws IOException { final File destDirectory = new File(tempDirFile, "destination"); if (!destDirectory.exists()) { destDirectory.mkdirs(); } // Create a test directory final File inputDirectory = new File(tempDirFile, "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(tempDirFile, "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(tempDirFile, "doesNotExists"), tempDirFile)); } @Test public void testCopyToDirectoryWithFileSourceIsNull() { assertThrows(NullPointerException.class, () -> FileUtils.copyToDirectory((File) null, tempDirFile)); } @Test public void testCopyToDirectoryWithIterable() throws IOException { final File directory = new File(tempDirFile, "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(tempDirFile, "doesNotExists")), tempDirFile)); } @Test public void testCopyToDirectoryWithIterableSourceIsNull() { assertThrows(NullPointerException.class, () -> FileUtils.copyToDirectory((List) null, tempDirFile)); } @Test public void testCopyToSelf() throws Exception { final File destination = new File(tempDirFile, "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(tempDirFile, getName()); assertContentMatchesAfterCopyURLToFileFor("/java/lang/Object.class", file); //TODO Maybe test copy to itself like for copyFile() } @Test public void testCopyURLToFileCreatesParentDirs() throws Exception { final File file = managedTempDirPath.resolve("subdir").resolve(getName()).toFile(); assertContentMatchesAfterCopyURLToFileFor("/java/lang/Object.class", file); } @Test public void testCopyURLToFileReplacesExisting() throws Exception { final File file = new File(tempDirFile, getName()); assertContentMatchesAfterCopyURLToFileFor("/java/lang/Object.class", file); assertContentMatchesAfterCopyURLToFileFor("/java/lang/String.class", file); } @Test public void testCopyURLToFileWithTimeout() throws Exception { // Creates file final File file = new File(tempDirFile, "testCopyURLToFileWithTimeout"); // Loads resource final String resourceName = "/java/lang/Object.class"; FileUtils.copyURLToFile(getClass().getResource(resourceName), file, 500, 500); // Tests that resource was copied correctly try (InputStream fis = Files.newInputStream(file.toPath()); InputStream resStream = getClass().getResourceAsStream(resourceName);) { assertTrue(IOUtils.contentEquals(resStream, fis), "Content is not equal."); } } /** * Tests a directory with one file of size 0. */ @Test public void testCountFolders1FileSize0() { assertEquals(0, FileUtils.sizeOfDirectory(Paths.get("src/test/resources/org/apache/commons/io/dirs-1-file-size-0").toFile())); } /** * Tests a directory with one file of size 1. */ @Test public void testCountFolders1FileSize1() { assertEquals(1, FileUtils.sizeOfDirectory(Paths.get("src/test/resources/org/apache/commons/io/dirs-1-file-size-1").toFile())); } /** * Tests a directory with two subdirectories, each containing one file of size 1. */ @Test public void testCountFolders2FileSize2() { assertEquals(2, FileUtils.sizeOfDirectory(Paths.get("src/test/resources/org/apache/commons/io/dirs-2-file-size-2").toFile())); } /** * Tests a directory with two subdirectories, each containing one file of size 1. */ @Test public void testCountFolders2FileSize4() { assertEquals(8, FileUtils.sizeOfDirectory(Paths.get("src/test/resources/org/apache/commons/io/dirs-2-file-size-4").toFile())); } @Test public void testCreateParentDirectories() throws IOException { // If a directory already exists, nothing happens. FileUtils.createParentDirectories(FileUtils.current()); // null is a noop FileUtils.createParentDirectories(null); } @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() { assertThrows(IllegalArgumentException.class, () -> FileUtils.deleteDirectory(testFile1)); } @Test public void testDeleteQuietlyDir() throws IOException { final File testDirectory = new File(tempDirFile, "testDeleteQuietlyDir"); final File testFile = new File(testDirectory, "testDeleteQuietlyFile"); testDirectory.mkdirs(); if (!testFile.getParentFile().exists()) { fail("Cannot create file " + testFile + " as the parent directory does not exist"); } try (final OutputStream output = new BufferedOutputStream(Files.newOutputStream(testFile.toPath()))) { TestUtils.generateTestData(output, 0); } 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(tempDirFile, "testDeleteQuietlyFile"); if (!testFile.getParentFile().exists()) { fail("Cannot create file " + testFile + " as the parent directory does not exist"); } try (final OutputStream output = new BufferedOutputStream(Files.newOutputStream(testFile.toPath()))) { TestUtils.generateTestData(output, 0); } assertTrue(testFile.exists()); FileUtils.deleteQuietly(testFile); assertFalse(testFile.exists(), "Check No Exist"); } @Test public void testDeleteQuietlyForNull() { FileUtils.deleteQuietly(null); } @Test public void testDeleteQuietlyNonExistent() { final File testFile = new File("testDeleteQuietlyNonExistent"); assertFalse(testFile.exists()); FileUtils.deleteQuietly(testFile); } /** * Tests the FileUtils implementation. */ @Test public void testFileUtils() throws Exception { // Loads file from classpath final File file1 = new File(tempDirFile, "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(tempDirFile, "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()"); } @Test public void testForceDeleteAFile1() throws Exception { final File destination = new File(tempDirFile, "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(tempDirFile, "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() { final File destination = new File(tempDirFile, "no_such_file"); assertFalse(destination.exists(), "Check No Exist"); assertThrows(IOException.class, () -> FileUtils.forceDelete(destination)); } @Test public void testForceDeleteDir() throws Exception { final File testDirectory = tempDirFile; assertTrue(testDirectory.exists(), "TestDirectory must exist"); FileUtils.forceDelete(testDirectory); assertFalse(testDirectory.exists(), "TestDirectory must not exist"); } /** * TODO Passes on macOS, fails on Linux and Windows with AccessDeniedException. */ @Test @EnabledOnOs(value = OS.MAC) public void testForceDeleteReadOnlyDirectory() throws Exception { try (TempDirectory destDir = TempDirectory.create("dir-"); TempFile destination = TempFile.create(destDir, "test-", ".txt")) { // sanity check structure assertTrue(Files.isDirectory(destDir.get())); assertEquals(destDir.get(), destination.get().getParent()); // sanity check attributes final File file = destination.toFile(); assertTrue(file.setReadOnly()); assertTrue(file.canRead()); assertFalse(file.canWrite()); // sanity check that File.delete() deletes a read-only directory. final PathCounters delete = destDir.delete(); assertEquals(1, delete.getDirectoryCounter().get()); assertEquals(1, delete.getFileCounter().get()); assertFalse(file.exists()); assertFalse(destDir.exists()); } try (TempDirectory destDir = TempDirectory.create("dir-"); TempFile destination = TempFile.create(destDir, "test-", ".txt")) { // sanity check structure assertTrue(Files.isDirectory(destDir.get())); assertEquals(destDir.get(), destination.get().getParent()); // sanity check attributes final File dir = destDir.toFile(); // real test assertTrue(dir.setReadOnly()); assertTrue(dir.canRead()); assertFalse(dir.canWrite()); assertTrue(dir.exists(), "File doesn't exist to delete"); // TODO Passes on macOS, fails on Linux and Windows with AccessDeniedException. FileUtils.forceDelete(dir); assertFalse(destination.exists(), "Check deletion"); assertFalse(dir.exists(), "Check deletion"); assertFalse(destDir.exists(), "Check deletion"); } } @Test public void testForceDeleteReadOnlyFile() throws Exception { try (TempFile destination = TempFile.create("test-", ".txt")) { final File file = destination.toFile(); assertTrue(file.setReadOnly()); assertTrue(file.canRead()); assertFalse(file.canWrite()); // sanity check that File.delete() deletes read-only files. assertTrue(file.delete()); } try (TempFile destination = TempFile.create("test-", ".txt")) { final File file = destination.toFile(); // real test assertTrue(file.setReadOnly()); assertTrue(file.canRead()); assertFalse(file.canWrite()); assertTrue(file.exists(), "File doesn't exist to delete"); FileUtils.forceDelete(file); assertFalse(file.exists(), "Check deletion"); } } /** * TODO Passes on macOS, fails on Linux and Windows with AccessDeniedException. */ @Test @EnabledOnOs(value = OS.MAC) public void testForceDeleteUnwritableDirectory() throws Exception { try (TempDirectory destDir = TempDirectory.create("dir-"); TempFile file = TempFile.create(destDir, "test-", ".txt")) { // sanity check structure assertTrue(Files.isDirectory(destDir.get())); assertEquals(destDir.get(), file.get().getParent()); // sanity check attributes final File dir = destDir.toFile(); assertTrue(dir.canWrite()); // Windows: setWritable(false) returns false. assertTrue(dir.setWritable(false), () -> "setWritable(false) on " + dir); assertFalse(dir.canWrite()); assertTrue(dir.canRead()); // sanity check that File.delete() cannot delete non-empty directories. assertFalse(dir.delete()); // delete underlying file. assertFalse(file.toFile().delete()); // reset attribute so we can delete file and auto-close/delete dir. assertTrue(dir.setWritable(true)); assertTrue(file.toFile().delete()); } try (TempDirectory destDir = TempDirectory.create("dir-"); TempFile file = TempFile.create(destDir, "test-", ".txt")) { // sanity check structure assertTrue(Files.isDirectory(destDir.get())); assertEquals(destDir.get(), file.get().getParent()); // sanity check attributes final File dir = destDir.toFile(); assertTrue(dir.canWrite()); assertTrue(dir.setWritable(false)); assertFalse(dir.canWrite()); assertTrue(dir.canRead()); // sanity check that File.delete() cannot delete non-empty directories. assertFalse(dir.delete()); // test // Linux: Fails with AccessDeniedException. FileUtils.forceDelete(dir); assertFalse(file.exists()); assertFalse(dir.exists()); } } @Test public void testForceDeleteUnwritableFile() throws Exception { try (TempFile destination = TempFile.create("test-", ".txt")) { final File file = destination.toFile(); assertTrue(file.canWrite()); assertTrue(file.setWritable(false)); assertFalse(file.canWrite()); assertTrue(file.canRead()); // sanity check that File.delete() deletes unwritable files. assertTrue(file.delete()); } try (TempFile destination = TempFile.create("test-", ".txt")) { final File file = destination.toFile(); // real test assertTrue(file.canWrite()); assertTrue(file.setWritable(false)); assertFalse(file.canWrite()); assertTrue(file.canRead()); assertTrue(file.exists(), "File doesn't exist to delete"); FileUtils.forceDelete(file); assertFalse(file.exists(), "Check deletion"); } } @Test public void testForceMkdir() throws Exception { // Tests with existing directory FileUtils.forceMkdir(tempDirFile); // Creates test file final File testFile = new File(tempDirFile, getName()); 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."); // noop FileUtils.forceMkdir(null); } @Test public void testForceMkdirParent() throws Exception { // Tests with existing directory assertTrue(tempDirFile.exists()); final File testParentDir = new File(tempDirFile, "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"); assertThrows(NullPointerException.class, () -> FileUtils.getFile((String[]) null)); } @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"); assertThrows(NullPointerException.class, () -> FileUtils.getFile(parent, (String[]) null)); assertThrows(NullPointerException.class, () -> FileUtils.getFile((File) null, "src")); } @Test public void testGetTempDirectory() { final File tempDirectory = new File(FileUtils.getTempDirectoryPath()); assertEquals(tempDirectory, FileUtils.getTempDirectory()); } @Test public void testGetTempDirectoryPath() { assertEquals(System.getProperty("java.io.tmpdir"), FileUtils.getTempDirectoryPath()); } @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()); } @Test public void testIO276() throws Exception { final File dir = new File("target", "IO276"); Files.deleteIfExists(dir.toPath()); 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 = tempDirFile; final File src = new File(testDirectory, "dir1"); final File dest = new File(src, "dir2"); assertTrue(dest.mkdirs()); assertTrue(src.exists()); assertThrows(IOException.class, () -> FileUtils.moveDirectoryToDirectory(src, dest, false)); assertTrue(src.exists()); } @Test public void testIO575() throws IOException { final Path sourceDir = Files.createTempDirectory("source-dir"); final String fileName = "some-file"; final Path sourceFile = Files.createFile(sourceDir.resolve(fileName)); assertEquals(SystemUtils.IS_OS_WINDOWS, sourceFile.toFile().canExecute()); sourceFile.toFile().setExecutable(true); assertTrue(sourceFile.toFile().canExecute()); final Path destDir = Files.createTempDirectory("some-empty-destination"); FileUtils.copyDirectory(sourceDir.toFile(), destDir.toFile()); final Path destFile = destDir.resolve(fileName); assertTrue(destFile.toFile().exists()); assertTrue(destFile.toFile().canExecute()); } @Test public void testIsDirectory() throws IOException { assertFalse(FileUtils.isDirectory(null)); assertTrue(FileUtils.isDirectory(tempDirFile)); assertFalse(FileUtils.isDirectory(testFile1)); final File tempDirAsFile; try (TempDirectory tempDir = TempDirectory.create(getClass().getCanonicalName())) { tempDirAsFile = tempDir.toFile(); assertTrue(FileUtils.isDirectory(tempDirAsFile)); } assertFalse(FileUtils.isDirectory(tempDirAsFile)); } @Test public void testIsEmptyDirectory() throws IOException { try (TempDirectory tempDir = TempDirectory.create(getClass().getCanonicalName())) { final File tempDirAsFile = tempDir.toFile(); Assertions.assertTrue(FileUtils.isEmptyDirectory(tempDirAsFile)); } Assertions.assertFalse(FileUtils.isEmptyDirectory(DIR_SIZE_1.toFile())); } @ParameterizedTest @ValueSource(longs = {1L, 100L, 1_000L, 10_000L, 100_000L, 1_000_000L}) public void testIsFileNewerOlder(final long millis) throws Exception { // Files final File oldFile = new File(tempDirFile, "FileUtils-old.txt"); final File refFile = new File(tempDirFile, "FileUtils-reference.txt"); final File newFile = new File(tempDirFile, "FileUtils-new.txt"); final File invalidFile = new File(tempDirFile, "FileUtils-invalid-file.txt"); // Paths final Path oldPath = oldFile.toPath(); final Path refPath = refFile.toPath(); final Path newPath = newFile.toPath(); // FileTimes // TODO What is wrong with Java 8 on macOS? Or is this a macOS file system issue? final long actualMillis = SystemUtils.IS_OS_MAC && SystemUtils.IS_JAVA_1_8 ? millis + 1000 : millis; final FileTime oldFileTime = FileTime.from(actualMillis * 1, TimeUnit.MILLISECONDS); final FileTime refFileTime = FileTime.from(actualMillis * 2, TimeUnit.MILLISECONDS); final FileTime testFileTime = FileTime.from(actualMillis * 3, TimeUnit.MILLISECONDS); final FileTime newFileTime = FileTime.from(actualMillis * 4, TimeUnit.MILLISECONDS); // Create fixtures try (final OutputStream output = new BufferedOutputStream(Files.newOutputStream(oldPath))) { TestUtils.generateTestData(output, 0); } Files.setLastModifiedTime(oldPath, oldFileTime); try (final OutputStream output = new BufferedOutputStream(Files.newOutputStream(refPath))) { TestUtils.generateTestData(output, 0); } Files.setLastModifiedTime(refPath, refFileTime); final Date date = new Date(testFileTime.toMillis()); final long now = date.getTime(); final Instant instant = date.toInstant(); final ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(instant, ZoneId.systemDefault()); final OffsetDateTime offsetDateTime = zonedDateTime.toOffsetDateTime(); final LocalDateTime localDateTime = zonedDateTime.toLocalDateTime(); final LocalDate localDate = zonedDateTime.toLocalDate(); final LocalDate localDatePlusDay = localDate.plusDays(1); final LocalTime localTime0 = LocalTime.MIDNIGHT; final OffsetTime offsetTime0 = OffsetTime.of(localTime0, ZoneOffset.UTC); try (final OutputStream output = new BufferedOutputStream(Files.newOutputStream(newPath))) { TestUtils.generateTestData(output, 0); } Files.setLastModifiedTime(newPath, newFileTime); // Test assertFalse(FileUtils.isFileNewer(oldFile, refFile), "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, offsetDateTime), "Old File - Newer - OffsetDateTime"); 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, localTime0), "Old File - Newer - LocalDate,LocalTime"); assertTrue(FileUtils.isFileNewer(oldFile, localDate, offsetTime0), "Old File - Newer - LocalDate,OffsetTime"); assertFalse(FileUtils.isFileNewer(oldFile, localDatePlusDay), "Old File - Newer - LocalDate plus one day"); assertFalse(FileUtils.isFileNewer(oldFile, localDatePlusDay, localTime0), "Old File - Newer - LocalDate plus one day,LocalTime"); assertFalse(FileUtils.isFileNewer(oldFile, localDatePlusDay, offsetTime0), "Old File - Newer - LocalDate plus one day,OffsetTime"); assertTrue(FileUtils.isFileNewer(newFile, refFile), "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, offsetDateTime), "New File - Newer - OffsetDateTime"); 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, localTime0), "New File - Newer - LocalDate,LocalTime"); assertTrue(FileUtils.isFileNewer(newFile, localDate, offsetTime0), "New File - Newer - LocalDate,OffsetTime"); assertFalse(FileUtils.isFileNewer(newFile, localDatePlusDay), "New File - Newer - LocalDate plus one day"); assertFalse(FileUtils.isFileNewer(newFile, localDatePlusDay, localTime0), "New File - Newer - LocalDate plus one day,LocalTime"); assertFalse(FileUtils.isFileNewer(newFile, localDatePlusDay, offsetTime0), "New File - Newer - LocalDate plus one day,OffsetTime"); assertFalse(FileUtils.isFileNewer(invalidFile, refFile), "Illegal - Newer - File"); assertThrows(UncheckedIOException.class, () -> FileUtils.isFileNewer(newFile, invalidFile)); // Test isFileOlder() assertTrue(FileUtils.isFileOlder(oldFile, refFile), "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, offsetDateTime), "Old File - Older - OffsetDateTime"); 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, localTime0), "Old File - Older - LocalDate,LocalTime"); assertFalse(FileUtils.isFileOlder(oldFile, localDate, offsetTime0), "Old File - Older - LocalDate,OffsetTime"); assertTrue(FileUtils.isFileOlder(oldFile, localDatePlusDay), "Old File - Older - LocalDate plus one day"); assertTrue(FileUtils.isFileOlder(oldFile, localDatePlusDay, localTime0), "Old File - Older - LocalDate plus one day,LocalTime"); assertTrue(FileUtils.isFileOlder(oldFile, localDatePlusDay, offsetTime0), "Old File - Older - LocalDate plus one day,OffsetTime"); assertFalse(FileUtils.isFileOlder(newFile, refFile), "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, offsetDateTime), "New File - Older - OffsetDateTime"); 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, localTime0), "New File - Older - LocalDate,LocalTime"); assertFalse(FileUtils.isFileOlder(newFile, localDate, offsetTime0), "New File - Older - LocalDate,OffsetTime"); assertTrue(FileUtils.isFileOlder(newFile, localDatePlusDay), "New File - Older - LocalDate plus one day"); assertTrue(FileUtils.isFileOlder(newFile, localDatePlusDay, localTime0), "New File - Older - LocalDate plus one day,LocalTime"); assertTrue(FileUtils.isFileOlder(newFile, localDatePlusDay, offsetTime0), "New File - Older - LocalDate plus one day,OffsetTime"); assertFalse(FileUtils.isFileOlder(invalidFile, refFile), "Illegal - Older - File"); assertThrows(UncheckedIOException.class, () -> FileUtils.isFileOlder(newFile, invalidFile)); // Null File assertThrows(NullPointerException.class, () -> FileUtils.isFileNewer(null, now)); // Null reference File assertThrows(NullPointerException.class, () -> FileUtils.isFileNewer(oldFile, (File) null)); // Invalid reference File assertThrows(UncheckedIOException.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(UncheckedIOException.class, () -> FileUtils.isFileOlder(oldFile, invalidFile)); } @Test public void testIsRegularFile() throws IOException { assertFalse(FileUtils.isRegularFile(null)); assertFalse(FileUtils.isRegularFile(tempDirFile)); assertTrue(FileUtils.isRegularFile(testFile1)); Files.delete(testFile1.toPath()); assertFalse(FileUtils.isRegularFile(testFile1)); } @Test public void testIterateFiles() throws Exception { final File srcDir = tempDirFile; 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 = WildcardFileFilter.builder().setWildcards("*.*").get(); 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 = tempDirFile; // 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 = WildcardFileFilter.builder().setWildcards("*.*").get(); final WildcardFileFilter fileFilterAllDirs = WildcardFileFilter.builder().setWildcards("*").get(); final WildcardFileFilter fileFilterExtTxt = WildcardFileFilter.builder().setWildcards("*.txt").get(); try { try (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 "*" 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 testIterateFilesOnlyNoDirs() throws IOException { final File directory = tempDirFile; assertTrue(new File(directory, "TEST").mkdir()); assertTrue(new File(directory, "test.txt").createNewFile()); final IOFileFilter filter = WildcardFileFilter.builder().setWildcards("*").setIoCase(IOCase.INSENSITIVE).get(); FileUtils.iterateFiles(directory, filter, null).forEachRemaining(file -> assertFalse(file.isDirectory(), file::getAbsolutePath)); } @Test public void testListFiles() throws Exception { final File srcDir = tempDirFile; 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()) { fail("Cannot create file " + theFile + " as the parent directory does not exist"); } try (final BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(theFile.toPath()))) { TestUtils.generateTestData(output, fileSizes[i]); } } // @formatter:off final Collection actualFiles = FileUtils.listFiles(subDir, WildcardFileFilter.builder().setWildcards("*.*").get(), WildcardFileFilter.builder().setWildcards("*").get()); // @formatter:on 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 testListFilesOnlyNoDirs() throws IOException { final File directory = tempDirFile; assertTrue(new File(directory, "TEST").mkdir()); assertTrue(new File(directory, "test.txt").createNewFile()); final IOFileFilter filter = WildcardFileFilter.builder().setWildcards("*").setIoCase(IOCase.INSENSITIVE).get(); for (final File file : FileUtils.listFiles(directory, filter, null)) { assertFalse(file.isDirectory(), file::getAbsolutePath); } } @Test public void testListFilesWithDirs() throws IOException { final File srcDir = tempDirFile; 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()) { fail("Cannot create file " + someFile + " as the parent directory does not exist"); } try (final BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(someFile.toPath()))) { TestUtils.generateTestData(output, 100); } final File subDir3 = new File(subDir2, "subdir3"); subDir3.mkdir(); // @formatter:off final Collection files = FileUtils.listFilesAndDirs(subDir1, WildcardFileFilter.builder().setWildcards("*.*").get(), WildcardFileFilter.builder().setWildcards("*").get()); // @formatter:on 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 = tempDirFile; 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()) { fail("Cannot create file " + testFile + " as the parent directory does not exist"); } try (final OutputStream output = new BufferedOutputStream(Files.newOutputStream(testFile.toPath()))) { TestUtils.generateTestData(output, 0); } 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)); assertThrows(FileNotFoundException.class, () -> FileUtils.moveDirectory(new File("non-existent"), new File("foo"))); final File testFile = new File(tempDirFile, "testMoveDirectoryFile"); if (!testFile.getParentFile().exists()) { fail("Cannot create file " + testFile + " as the parent directory does not exist"); } try (final OutputStream output = new BufferedOutputStream(Files.newOutputStream(testFile.toPath()))) { TestUtils.generateTestData(output, 0); } assertThrows(IllegalArgumentException.class, () -> FileUtils.moveDirectory(testFile, new File("foo"))); final File testSrcFile = new File(tempDirFile, "testMoveDirectorySource"); final File testDestFile = new File(tempDirFile, "testMoveDirectoryDest"); testSrcFile.mkdir(); testDestFile.mkdir(); assertThrows(FileExistsException.class, () -> FileUtils.moveDirectory(testSrcFile, testDestFile), "Expected FileExistsException when dest already exists"); } @Test public void testMoveDirectory_Rename() throws Exception { final File dir = tempDirFile; 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()) { fail("Cannot create file " + testFile + " as the parent directory does not exist"); } try (final OutputStream output = new BufferedOutputStream(Files.newOutputStream(testFile.toPath()))) { TestUtils.generateTestData(output, 0); } 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 = tempDirFile; 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()) { fail("Cannot create file " + testFile + " as the parent directory does not exist"); } try (final OutputStream output = new BufferedOutputStream(Files.newOutputStream(testFile.toPath()))) { TestUtils.generateTestData(output, 0); } 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(tempDirFile, "testMoveFileFile1"); final File testFile2 = new File(tempDirFile, "testMoveFileFile2"); if (!testFile1.getParentFile().exists()) { fail("Cannot create file " + testFile1 + " as the parent directory does not exist"); } try (final BufferedOutputStream output1 = new BufferedOutputStream(Files.newOutputStream(testFile1.toPath()))) { TestUtils.generateTestData(output1, 0); } if (!testFile2.getParentFile().exists()) { fail("Cannot create file " + testFile2 + " as the parent directory does not exist"); } try (final BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(testFile2.toPath()))) { TestUtils.generateTestData(output, 0); } assertThrows(IOException.class, () -> FileUtils.moveDirectoryToDirectory(testFile1, testFile2, true)); final File nonExistent = new File(tempDirFile, "testMoveFileNonExistent"); assertThrows(IOException.class, () -> FileUtils.moveDirectoryToDirectory(testFile1, nonExistent, false)); } @Test public void testMoveFile_CopyDelete() throws Exception { final File destination = new File(tempDirFile, "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() { final File destination = new File(tempDirFile, "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(tempDirFile, "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(tempDirFile, "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)); assertThrows(FileNotFoundException.class, () -> FileUtils.moveFile(new File("non-existent"), new File("foo"))); assertThrows(IllegalArgumentException.class, () -> FileUtils.moveFile(tempDirFile, new File("foo"))); final File testSourceFile = new File(tempDirFile, "testMoveFileSource"); final File testDestFile = new File(tempDirFile, "testMoveFileSource"); if (!testSourceFile.getParentFile().exists()) { fail("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); } assertTrue(testDestFile.getParentFile().exists(), () -> "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); } assertThrows(FileExistsException.class, () -> FileUtils.moveFile(testSourceFile, testDestFile), "Expected FileExistsException when dest already exists"); } @Test public void testMoveFile_Rename() throws Exception { final File destination = new File(tempDirFile, "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(tempDirFile, "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(tempDirFile, "testMoveFileFile1"); final File testFile2 = new File(tempDirFile, "testMoveFileFile2"); if (!testFile1.getParentFile().exists()) { fail("Cannot create file " + testFile1 + " as the parent directory does not exist"); } try (final BufferedOutputStream output1 = new BufferedOutputStream(Files.newOutputStream(testFile1.toPath()))) { TestUtils.generateTestData(output1, 0); } if (!testFile2.getParentFile().exists()) { fail("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 nonExistent = new File(tempDirFile, "testMoveFileNonExistent"); assertThrows(IOException.class, () -> FileUtils.moveFileToDirectory(testFile1, nonExistent, false)); } @Test public void testMoveToDirectory() throws Exception { final File destDir = new File(tempDirFile, "testMoveToDirectoryDestDir"); final File testDir = new File(tempDirFile, "testMoveToDirectoryTestDir"); final File testFile = new File(tempDirFile, "testMoveToDirectoryTestFile"); testDir.mkdirs(); if (!testFile.getParentFile().exists()) { fail("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 { assertThrows(NullPointerException.class, () -> FileUtils.moveDirectoryToDirectory(null, new File("foo"), true)); assertThrows(NullPointerException.class, () -> FileUtils.moveDirectoryToDirectory(new File("foo"), null, true)); final File nonExistent = new File(tempDirFile, "non-existent"); final File destDir = new File(tempDirFile, "MoveToDirectoryDestDir"); assertThrows(IOException.class, () -> FileUtils.moveToDirectory(nonExistent, destDir, true), "Expected IOException when source does not exist"); } @Test public void testReadFileToByteArray() throws Exception { final File file = new File(tempDirFile, "read.txt"); Files.write(file.toPath(), new byte[] {11, 21, 31}); 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 testReadFileToByteArray_Errors() { assertThrows(NullPointerException.class, () -> FileUtils.readFileToByteArray(null)); assertThrows(IOException.class, () -> FileUtils.readFileToByteArray(new File("non-exsistent"))); assertThrows(IOException.class, () -> FileUtils.readFileToByteArray(tempDirFile)); } @Test @EnabledIf("isPosixFilePermissionsSupported") public void testReadFileToByteArray_IOExceptionOnPosixFileSystem() throws Exception { final File file = TestUtils.newFile(tempDirFile, "cant-read.txt"); TestUtils.createFile(file, 100); Files.setPosixFilePermissions(file.toPath(), PosixFilePermissions.fromString("---------")); assertThrows(IOException.class, () -> FileUtils.readFileToByteArray(file)); } @Test public void testReadFileToString_Errors() { assertThrows(NullPointerException.class, () -> FileUtils.readFileToString(null)); assertThrows(IOException.class, () -> FileUtils.readFileToString(new File("non-exsistent"))); assertThrows(IOException.class, () -> FileUtils.readFileToString(tempDirFile)); assertThrows(UnsupportedCharsetException.class, () -> FileUtils.readFileToString(tempDirFile, "unsupported-charset")); } @Test @EnabledIf("isPosixFilePermissionsSupported") public void testReadFileToString_IOExceptionOnPosixFileSystem() throws Exception { final File file = TestUtils.newFile(tempDirFile, "cant-read.txt"); TestUtils.createFile(file, 100); Files.setPosixFilePermissions(file.toPath(), PosixFilePermissions.fromString("---------")); assertThrows(IOException.class, () -> FileUtils.readFileToString(file)); } @Test public void testReadFileToStringWithDefaultEncoding() throws Exception { final File file = new File(tempDirFile, "read.obj"); final String fixture = "Hello /u1234"; Files.write(file.toPath(), fixture.getBytes()); assertEquals(fixture, FileUtils.readFileToString(file)); } @Test public void testReadFileToStringWithEncoding() throws Exception { final File file = new File(tempDirFile, "read.obj"); final byte[] text = "Hello /u1234".getBytes(StandardCharsets.UTF_8); Files.write(file.toPath(), text); final String data = FileUtils.readFileToString(file, "UTF8"); assertEquals("Hello /u1234", data); } @Test public void testReadLines() throws Exception { final File file = TestUtils.newFile(tempDirFile, "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 testReadLines_Errors() { assertThrows(NullPointerException.class, () -> FileUtils.readLines(null)); assertThrows(IOException.class, () -> FileUtils.readLines(new File("non-exsistent"))); assertThrows(IOException.class, () -> FileUtils.readLines(tempDirFile)); assertThrows(UnsupportedCharsetException.class, () -> FileUtils.readLines(tempDirFile, "unsupported-charset")); } @Test @EnabledIf("isPosixFilePermissionsSupported") public void testReadLines_IOExceptionOnPosixFileSystem() throws Exception { final File file = TestUtils.newFile(tempDirFile, "cant-read.txt"); TestUtils.createFile(file, 100); Files.setPosixFilePermissions(file.toPath(), PosixFilePermissions.fromString("---------")); assertThrows(IOException.class, () -> FileUtils.readLines(file)); } @Test public void testSizeOf() throws Exception { final File file = new File(tempDirFile, getName()); // Null argument assertThrows(NullPointerException.class, () -> FileUtils.sizeOf(null)); // Non-existent file assertThrows(IllegalArgumentException.class, () -> FileUtils.sizeOf(file)); // Creates file file.createNewFile(); // 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(tempDirFile), "Unexpected directory size"); } @Test public void testSizeOfAsBigInteger() throws Exception { final File file = new File(tempDirFile, getName()); // Null argument assertThrows(NullPointerException.class, () -> FileUtils.sizeOfAsBigInteger(null)); // Non-existent file assertThrows(IllegalArgumentException.class, () -> FileUtils.sizeOfAsBigInteger(file)); // Creates file file.createNewFile(); // 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(tempDirFile), "Unexpected directory size"); } /** * Requires admin privileges on Windows. * * @throws Exception For example java.nio.file.FileSystemException: * C:\Users\you\AppData\Local\Temp\junit2324629522183300191\FileUtilsTest8613879743106252609\symlinked-dir: A required privilege is * not held by the client. */ @Test public void testSizeOfDirectory() throws Exception { final File file = new File(tempDirFile, getName()); // Null argument assertThrows(NullPointerException.class, () -> FileUtils.sizeOfDirectory(null)); // Non-existent file assertThrows(IllegalArgumentException.class, () -> FileUtils.sizeOfAsBigInteger(file)); // Creates file file.createNewFile(); // Existing file assertThrows(IllegalArgumentException.class, () -> FileUtils.sizeOfDirectory(file)); // Existing directory file.delete(); file.mkdir(); // Create a cyclic symlink this.createCircularSymLink(file); assertEquals(TEST_DIRECTORY_SIZE, FileUtils.sizeOfDirectory(file), "Unexpected directory size"); } /** * Requires admin privileges on Windows. * * @throws Exception For example java.nio.file.FileSystemException: * C:\Users\you\AppData\Local\Temp\junit2324629522183300191\FileUtilsTest8613879743106252609\symlinked-dir: A required privilege is * not held by the client. */ @Test public void testSizeOfDirectoryAsBigInteger() throws Exception { final File file = new File(tempDirFile, getName()); // Null argument assertThrows(NullPointerException.class, () -> FileUtils.sizeOfDirectoryAsBigInteger(null)); // Non-existent file assertThrows(UncheckedIOException.class, () -> FileUtils.sizeOfDirectoryAsBigInteger(file)); // Creates file file.createNewFile(); // Existing file assertThrows(IllegalArgumentException.class, () -> FileUtils.sizeOfDirectoryAsBigInteger(file)); // Existing directory file.delete(); file.mkdir(); 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, "non-emptyFile" + System.nanoTime()); assertTrue(nonEmptyFile.getParentFile().exists(), () -> "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); } 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"), }; assertThrows(IllegalArgumentException.class, () -> FileUtils.toFiles(urls)); } @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 { assertThrows(NullPointerException.class, () -> FileUtils.touch(null)); final File file = new File(tempDirFile, "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"); try (OutputStream out = Files.newOutputStream(file.toPath())) { assertEquals(0, file.length(), "Created empty file."); out.write(0); } 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 testTouchDirDoesNotExist() throws Exception { final File file = new File("target/does-not-exist", "touchme.txt"); final File parentDir = file.getParentFile(); file.delete(); parentDir.delete(); assertFalse(parentDir.exists()); assertFalse(file.exists()); FileUtils.touch(file); assertTrue(parentDir.exists()); assertTrue(file.exists()); } @Test public void testToURLs1() throws Exception { final File[] files = { new File(tempDirFile, "file1.txt"), new File(tempDirFile, "file2.txt"), new File(tempDirFile, "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 testToURLs2() { final File[] files = { new File(tempDirFile, "file1.txt"), null, }; assertThrows(NullPointerException.class, () -> FileUtils.toURLs(files), "Can't convert null URL"); } @Test public void testToURLs3() { final File[] files = null; assertThrows(NullPointerException.class, () -> FileUtils.toURLs(files), "Can't convert null list"); } @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(tempDirFile, "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(tempDirFile, "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(tempDirFile, "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(tempDirFile, "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(tempDirFile, "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(tempDirFile, "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(tempDirFile, "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(tempDirFile, "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(tempDirFile, "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(tempDirFile, "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(tempDirFile, "lines.txt"); FileUtils.writeLines(file, StandardCharsets.US_ASCII.name(), 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, StandardCharsets.US_ASCII.name()); assertEquals(expected, actual); } @Test public void testWriteLines_3argsWithAppendOptionFalse_ShouldDeletePreviousFileLines() throws Exception { final File file = TestUtils.newFile(tempDirFile, "lines.txt"); FileUtils.writeStringToFile(file, "This line was there before you...", StandardCharsets.UTF_8); 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(tempDirFile, "lines.txt"); FileUtils.writeStringToFile(file, "This line was there before you...", StandardCharsets.UTF_8); 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(tempDirFile, "lines.txt"); FileUtils.writeLines(file, StandardCharsets.US_ASCII.name(), list, "*"); final String expected = "hello*world**this is**some text*"; final String actual = FileUtils.readFileToString(file, StandardCharsets.US_ASCII.name()); 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(tempDirFile, "lines.txt"); FileUtils.writeLines(file, StandardCharsets.US_ASCII.name(), 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, StandardCharsets.US_ASCII.name()); assertEquals(expected, actual); } @Test public void testWriteLines_4arg_Writer_nullData() throws Exception { final File file = TestUtils.newFile(tempDirFile, "lines.txt"); FileUtils.writeLines(file, StandardCharsets.US_ASCII.name(), null, "*"); assertEquals(0, file.length(), "Sizes differ"); } @Test public void testWriteLines_4argsWithAppendOptionFalse_ShouldDeletePreviousFileLines() throws Exception { final File file = TestUtils.newFile(tempDirFile, "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(tempDirFile, "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(tempDirFile, "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(tempDirFile, "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(tempDirFile, "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(tempDirFile, "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(tempDirFile, "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(tempDirFile, "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 testWriteStringToFileIntoNonExistentSubdir() throws Exception { final File file = new File(tempDirFile, "subdir/write.txt"); FileUtils.writeStringToFile(file, "Hello /u1234", (Charset) null); final byte[] text = "Hello /u1234".getBytes(); TestUtils.assertEqualContent(text, file); } /** * Requires admin privileges on Windows. * * @throws Exception For example java.nio.file.FileSystemException: * C:\Users\you\AppData\Local\Temp\junit2324629522183300191\FileUtilsTest8613879743106252609\symlinked-dir: A required privilege is * not held by the client. */ @Test public void testWriteStringToFileIntoSymlinkedDir() throws Exception { final Path symlinkDir = createTempSymlinkedRelativeDir(); final File file = symlinkDir.resolve("file").toFile(); FileUtils.writeStringToFile(file, "Hello /u1234", StandardCharsets.UTF_8); final byte[] text = "Hello /u1234".getBytes(); TestUtils.assertEqualContent(text, file); } @Test public void testWriteStringToFileWithCharset() throws Exception { final File file = new File(tempDirFile, "write.txt"); FileUtils.writeStringToFile(file, "Hello /u1234", "UTF8"); final byte[] text = "Hello /u1234".getBytes(StandardCharsets.UTF_8); TestUtils.assertEqualContent(text, file); } @Test public void testWriteStringToFileWithEncoding_WithAppendOptionFalse_ShouldDeletePreviousFileLines() throws Exception { final File file = TestUtils.newFile(tempDirFile, "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(tempDirFile, "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 testWriteStringToFileWithNullCharset() throws Exception { final File file = new File(tempDirFile, "write.txt"); FileUtils.writeStringToFile(file, "Hello /u1234", (Charset) null); final byte[] text = "Hello /u1234".getBytes(); TestUtils.assertEqualContent(text, file); } @Test public void testWriteStringToFileWithNullStringCharset() throws Exception { final File file = new File(tempDirFile, "write.txt"); FileUtils.writeStringToFile(file, "Hello /u1234", (String) null); final byte[] text = "Hello /u1234".getBytes(); TestUtils.assertEqualContent(text, file); } @Test public void testWriteWithEncoding_WithAppendOptionFalse_ShouldDeletePreviousFileLines() throws Exception { final File file = TestUtils.newFile(tempDirFile, "lines.txt"); FileUtils.writeStringToFile(file, "This line was there before you...", StandardCharsets.UTF_8); 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(tempDirFile, "lines.txt"); FileUtils.writeStringToFile(file, "This line was there before you...", StandardCharsets.UTF_8); 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.16.1-src/src/test/java/org/apache/commons/io/FileUtilsWaitForTest.java0100644 0000000 0000000 00000004260 14603604450 030471 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicBoolean; import org.junit.jupiter.api.Test; /** * Tests FileUtils.waitFor(). *

* This class has been broken out from FileUtilsTestCase to solve issues as per BZ 38927 *

* * @see FileUtils */ public class FileUtilsWaitForTest { @Test public void testWaitFor0() { FileUtils.waitFor(FileUtils.current(), 0); } /** * TODO Fails randomly. */ @Test public void testWaitForInterrupted() throws InterruptedException { final AtomicBoolean wasInterrupted = new AtomicBoolean(); final CountDownLatch started = new CountDownLatch(2); final int seconds = 10; final Thread thread1 = new Thread(() -> { started.countDown(); assertTrue(FileUtils.waitFor(FileUtils.current(), seconds)); wasInterrupted.set(Thread.currentThread().isInterrupted()); }); thread1.start(); // Make sure the thread does not finish before we interrupt it: started.countDown(); thread1.interrupt(); started.await(); thread1.join(); assertTrue(wasInterrupted.get()); } @Test public void testWaitForNegativeDuration() { FileUtils.waitFor(FileUtils.current(), -1); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/FilenameUtilsTest.java0100644 0000000 0000000 00000212422 14603604450 030037 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 java.io.BufferedOutputStream; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; 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; /** * Tests {@link FilenameUtils}. */ public class FilenameUtilsTest { private static final String SEP = "" + File.separatorChar; private static final boolean WINDOWS = File.separatorChar == '\\'; @TempDir public Path temporaryFolder; private Path testFile1; private Path testFile2; private int testFile1Size; private int testFile2Size; @BeforeEach public void setUp() throws Exception { testFile1 = Files.createTempFile(temporaryFolder, "test", "1"); testFile2 = Files.createTempFile(temporaryFolder, "test", "2"); testFile1Size = (int) Files.size(testFile1); testFile2Size = (int) Files.size(testFile2); if (!Files.exists(testFile1.getParent())) { throw new IOException("Cannot create file " + testFile1 + " as the parent directory does not exist"); } try (BufferedOutputStream output3 = new BufferedOutputStream(Files.newOutputStream(testFile1))) { TestUtils.generateTestData(output3, testFile1Size); } if (!Files.exists(testFile2.getParent())) { throw new IOException("Cannot create file " + testFile2 + " as the parent directory does not exist"); } try (BufferedOutputStream output2 = new BufferedOutputStream(Files.newOutputStream(testFile2))) { TestUtils.generateTestData(output2, testFile2Size); } if (!Files.exists(testFile1.getParent())) { throw new IOException("Cannot create file " + testFile1 + " as the parent directory does not exist"); } try (BufferedOutputStream output1 = new BufferedOutputStream(Files.newOutputStream(testFile1))) { TestUtils.generateTestData(output1, testFile1Size); } if (!Files.exists(testFile2.getParent())) { throw new IOException("Cannot create file " + testFile2 + " as the parent directory does not exist"); } try (BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(testFile2))) { TestUtils.generateTestData(output, testFile2Size); } } @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 testDirectoryContains() { assertTrue(FilenameUtils.directoryContains("/foo", "/foo/bar")); assertTrue(FilenameUtils.directoryContains("/foo/", "/foo/bar")); assertTrue(FilenameUtils.directoryContains("C:\\foo", "C:\\foo\\bar")); assertTrue(FilenameUtils.directoryContains("C:\\foo\\", "C:\\foo\\bar")); assertFalse(FilenameUtils.directoryContains("/foo", "/foo")); assertFalse(FilenameUtils.directoryContains("/foo", "/foobar")); assertFalse(FilenameUtils.directoryContains("C:\\foo", "C:\\foobar")); assertFalse(FilenameUtils.directoryContains("/foo", null)); assertFalse(FilenameUtils.directoryContains("", "")); assertFalse(FilenameUtils.directoryContains("", "/foo")); assertFalse(FilenameUtils.directoryContains("/foo", "")); } @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 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 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 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 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")); assertFalse(FilenameUtils.equalsNormalizedOnSystem("//a.html", "//ab.html")); } @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 testGetBaseName() { assertNull(FilenameUtils.getBaseName(null)); assertEquals("noseparator", FilenameUtils.getBaseName("noseparator.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_null_character() { assertThrows(IllegalArgumentException.class, () -> FilenameUtils.getBaseName("fil\u0000e.txt.bak")); } @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 final IllegalArgumentException e = assertThrows(IllegalArgumentException.class, () -> FilenameUtils.getExtension("foo.exe:bar.txt")); 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 testGetFullPath() { assertNull(FilenameUtils.getFullPath(null)); assertEquals("", FilenameUtils.getFullPath("noseparator.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("noseparator.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("noseparator.inthispath", FilenameUtils.getName("noseparator.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 testGetPath() { assertNull(FilenameUtils.getPath(null)); assertEquals("", FilenameUtils.getPath("noseparator.inthispath")); assertEquals("", FilenameUtils.getPath("/noseparator.inthispath")); assertEquals("", FilenameUtils.getPath("\\noseparator.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_null_character() { assertThrows(IllegalArgumentException.class, () -> FilenameUtils.getPath("~user/a/\u0000b/c.txt")); } @Test public void testGetPathNoEndSeparator() { assertNull(FilenameUtils.getPath(null)); assertEquals("", FilenameUtils.getPath("noseparator.inthispath")); assertEquals("", FilenameUtils.getPathNoEndSeparator("/noseparator.inthispath")); assertEquals("", FilenameUtils.getPathNoEndSeparator("\\noseparator.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_character() { assertThrows(IllegalArgumentException.class, () -> FilenameUtils.getPathNoEndSeparator("~user/a\u0000/b/c.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_null_character() { assertThrows(IllegalArgumentException.class, () -> FilenameUtils.getPrefix("~u\u0000ser\\a\\b\\c.txt")); } @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 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 final IllegalArgumentException e = assertThrows(IllegalArgumentException.class, () -> FilenameUtils.indexOfExtension("foo.exe:bar.txt")); 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 testIndexOfLastSeparator() { assertEquals(-1, FilenameUtils.indexOfLastSeparator(null)); assertEquals(-1, FilenameUtils.indexOfLastSeparator("noseparator.inthispath")); assertEquals(3, FilenameUtils.indexOfLastSeparator("a/b/c")); assertEquals(3, FilenameUtils.indexOfLastSeparator("a\\b\\c")); } @Test public void testInjectionFailure() { assertThrows(IllegalArgumentException.class, () -> FilenameUtils.getName("a\\b\\\u0000c")); } @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() { assertThrows(IllegalArgumentException.class, () -> FilenameUtils.isExtension("a.b\\fi\u0000le.txt", "TXT")); } @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 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")))); } @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 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_null_character() { assertThrows(IllegalArgumentException.class, () -> FilenameUtils.normalize("a\\b/c\u0000.txt")); assertThrows(IllegalArgumentException.class, () -> FilenameUtils.normalize("\u0000a\\b/c.txt")); } @Test public void testNormalizeFromJavaDoc() { // Examples from Javadoc assertEquals(SEP + "foo" + SEP, FilenameUtils.normalize("/foo//")); assertEquals(SEP + "foo" + SEP, FilenameUtils.normalize(SEP + "foo" + SEP + "." + SEP)); assertEquals(SEP + "bar", FilenameUtils.normalize(SEP + "foo" + SEP + ".." + SEP + "bar")); assertEquals(SEP + "bar" + SEP, FilenameUtils.normalize(SEP + "foo" + SEP + ".." + SEP + "bar" + SEP)); assertEquals(SEP + "baz", FilenameUtils.normalize(SEP + "foo" + SEP + ".." + SEP + "bar" + SEP + ".." + SEP + "baz")); assertEquals(SEP + SEP + "foo" + SEP + "bar", FilenameUtils.normalize("//foo//./bar")); assertNull(FilenameUtils.normalize(SEP + ".." + SEP)); assertNull(FilenameUtils.normalize(".." + SEP + "foo")); assertEquals("foo" + SEP, FilenameUtils.normalize("foo" + SEP + "bar" + SEP + "..")); assertNull(FilenameUtils.normalize("foo" + SEP + ".." + SEP + ".." + SEP + "bar")); assertEquals("bar", FilenameUtils.normalize("foo" + SEP + ".." + SEP + "bar")); assertEquals(SEP + SEP + "server" + SEP + "bar", FilenameUtils.normalize(SEP + SEP + "server" + SEP + "foo" + SEP + ".." + SEP + "bar")); assertNull(FilenameUtils.normalize(SEP + SEP + "server" + SEP + ".." + SEP + "bar")); assertEquals("C:" + SEP + "bar", FilenameUtils.normalize("C:" + SEP + "foo" + SEP + ".." + SEP + "bar")); assertNull(FilenameUtils.normalize("C:" + SEP + ".." + SEP + "bar")); assertEquals("~" + SEP + "bar" + SEP, FilenameUtils.normalize("~" + SEP + "foo" + SEP + ".." + SEP + "bar" + SEP)); assertNull(FilenameUtils.normalize("~" + SEP + ".." + SEP + "bar")); assertEquals(SEP + SEP + "foo" + SEP + "bar", FilenameUtils.normalize("//foo//./bar")); assertEquals(SEP + SEP + "foo" + SEP + "bar", FilenameUtils.normalize("\\\\foo\\\\.\\bar")); } @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 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 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 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 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")); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/FilenameUtilsWildcardTest.java0100644 0000000 0000000 00000027465 14603604450 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; 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; /** * Tests {@link FilenameUtils} {@code wildcardMatch()} methods. */ public class FilenameUtilsWildcardTest { private static final boolean WINDOWS = File.separatorChar == '\\'; // Testing: // FilenameUtils.wildcardMatch(String,String) private void assertMatch(final String text, final String wildcard, final boolean expected) { assertEquals(expected, FilenameUtils.wildcardMatch(text, wildcard), text + " " + wildcard); } /** * 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); } } @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*")); } // 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); } @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 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 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("")); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/HexDumpTest.java0100644 0000000 0000000 00000032316 14603604450 026652 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.IOException; import org.apache.commons.io.output.ByteArrayOutputStream; import org.apache.commons.io.test.ThrowOnCloseOutputStream; import org.junit.jupiter.api.Test; /** * Tests {@link HexDump}. */ public class HexDumpTest { @Test public void testDumpAppendable() throws IOException { final byte[] testArray = new byte[256]; for (int j = 0; j < 256; j++) { testArray[j] = (byte) j; } // verify proper behavior dumping the entire array StringBuilder out = new StringBuilder(); HexDump.dump(testArray, out); assertEquals( "00000000 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ................" + System.lineSeparator() + "00000010 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F ................" + System.lineSeparator() + "00000020 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F !\"#$%&'()*+,-./" + System.lineSeparator() + "00000030 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 0123456789:;<=>?" + System.lineSeparator() + "00000040 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F @ABCDEFGHIJKLMNO" + System.lineSeparator() + "00000050 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F PQRSTUVWXYZ[\\]^_" + System.lineSeparator() + "00000060 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F `abcdefghijklmno" + System.lineSeparator() + "00000070 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F pqrstuvwxyz{|}~." + System.lineSeparator() + "00000080 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F ................" + System.lineSeparator() + "00000090 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F ................" + System.lineSeparator() + "000000A0 A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF ................" + System.lineSeparator() + "000000B0 B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF ................" + System.lineSeparator() + "000000C0 C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF ................" + System.lineSeparator() + "000000D0 D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF ................" + System.lineSeparator() + "000000E0 E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF ................" + System.lineSeparator() + "000000F0 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF ................" + System.lineSeparator(), out.toString()); // verify proper behavior with non-zero offset, non-zero index and length shorter than array size out = new StringBuilder(); HexDump.dump(testArray, 0x10000000, out, 0x28, 32); assertEquals( "10000028 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 ()*+,-./01234567" + System.lineSeparator() + "10000038 38 39 3A 3B 3C 3D 3E 3F 40 41 42 43 44 45 46 47 89:;<=>?@ABCDEFG" + System.lineSeparator(), out.toString()); // verify proper behavior with non-zero index and length shorter than array size out = new StringBuilder(); HexDump.dump(testArray, 0, out, 0x40, 24); assertEquals( "00000040 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F @ABCDEFGHIJKLMNO" + System.lineSeparator() + "00000050 50 51 52 53 54 55 56 57 PQRSTUVW" + System.lineSeparator(), out.toString()); // verify proper behavior with negative index assertThrows(ArrayIndexOutOfBoundsException.class, () -> HexDump.dump(testArray, 0x10000000, new StringBuilder(), -1, testArray.length)); // verify proper behavior with index that is too large assertThrows(ArrayIndexOutOfBoundsException.class, () -> HexDump.dump(testArray, 0x10000000, new StringBuilder(), testArray.length, testArray.length)); // verify proper behavior with length that is negative assertThrows(ArrayIndexOutOfBoundsException.class, () -> HexDump.dump(testArray, 0, new StringBuilder(), 0, -1)); // verify proper behavior with length that is too large final Exception exception = assertThrows(ArrayIndexOutOfBoundsException.class, () -> HexDump.dump(testArray, 0, new StringBuilder(), 1, testArray.length)); assertEquals("Range [1, 1 + 256) out of bounds for length 256", exception.getMessage()); // verify proper behavior with null appendable assertThrows(NullPointerException.class, () -> HexDump.dump(testArray, 0x10000000, null, 0, testArray.length)); } @Test public void testDumpOutputStream() 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 + System.lineSeparator().length())]; for (int j = 0; j < 16; j++) { int offset = (73 + System.lineSeparator().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(System.lineSeparator().getBytes(), 0, outputArray, offset, System.lineSeparator().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 + System.lineSeparator().length())]; for (int j = 0; j < 16; j++) { int offset = (73 + System.lineSeparator().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(System.lineSeparator().getBytes(), 0, outputArray, offset, System.lineSeparator().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 + System.lineSeparator().length())]; for (int j = 0; j < 16; j++) { int offset = (73 + System.lineSeparator().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(System.lineSeparator().getBytes(), 0, outputArray, offset, System.lineSeparator().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 + System.lineSeparator().length()) - 1]; for (int j = 0; j < 8; j++) { int offset = (73 + System.lineSeparator().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(System.lineSeparator().getBytes(), 0, outputArray, offset, System.lineSeparator().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 assertThrows(ArrayIndexOutOfBoundsException.class, () -> HexDump.dump(testArray, 0x10000000, new ByteArrayOutputStream(), -1)); // verify proper behavior with index that is too large assertThrows(ArrayIndexOutOfBoundsException.class, () -> HexDump.dump(testArray, 0x10000000, new ByteArrayOutputStream(), testArray.length)); // verify proper behavior with null stream assertThrows(NullPointerException.class, () -> HexDump.dump(testArray, 0x10000000, null, 0)); // verify output stream is not closed by the dump method HexDump.dump(testArray, 0, new ThrowOnCloseOutputStream(new ByteArrayOutputStream()), 0); } private char toAscii(final int c) { char rval = '.'; if (c >= 32 && c <= 126) { rval = (char) c; } return rval; } 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]; } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/IOCaseTest.java0100644 0000000 0000000 00000037041 14603604450 026403 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.Arrays; import org.junit.jupiter.api.Test; /** * Tests {@link IOCase}. */ public class IOCaseTest { private static final boolean WINDOWS = File.separatorChar == '\\'; private void assert0(final byte[] arr) { for (final byte e : arr) { assertEquals(0, e); } } private void assert0(final char[] arr) { for (final char e : arr) { assertEquals(0, e); } } private IOCase serialize(final IOCase value) throws Exception { final ByteArrayOutputStream buf = new ByteArrayOutputStream(); try (final ObjectOutputStream out = new ObjectOutputStream(buf)) { out.writeObject(value); out.flush(); } final ByteArrayInputStream bufin = new ByteArrayInputStream(buf.toByteArray()); final ObjectInputStream in = new ObjectInputStream(bufin); return (IOCase) in.readObject(); } @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_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("", "")); assertThrows(NullPointerException.class, () -> IOCase.SENSITIVE.checkCompareTo("ABC", null)); assertThrows(NullPointerException.class, () -> IOCase.SENSITIVE.checkCompareTo(null, "ABC")); assertThrows(NullPointerException.class, () -> IOCase.SENSITIVE.checkCompareTo(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_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_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_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("", "")); assertFalse(IOCase.SENSITIVE.checkEquals("ABC", null)); assertFalse(IOCase.SENSITIVE.checkEquals(null, "ABC")); assertTrue(IOCase.SENSITIVE.checkEquals(null, null)); } @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.SENSITIVE.checkIndexOf(null, 0, "Bc")); assertEquals(-1, IOCase.SENSITIVE.checkIndexOf(null, 0, null)); assertEquals(-1, IOCase.SENSITIVE.checkIndexOf("ABC", 0, null)); 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_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")); assertEquals(-1, IOCase.SENSITIVE.checkIndexOf("ABC", 0, null)); assertEquals(-1, IOCase.SENSITIVE.checkIndexOf(null, 0, "ABC")); assertEquals(-1, IOCase.SENSITIVE.checkIndexOf(null, 0, null)); } @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")); } @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, "")); assertFalse(IOCase.SENSITIVE.checkRegionMatches("ABC", 0, null)); assertFalse(IOCase.SENSITIVE.checkRegionMatches(null, 0, "ABC")); assertFalse(IOCase.SENSITIVE.checkRegionMatches(null, 0, null)); assertFalse(IOCase.SENSITIVE.checkRegionMatches("ABC", 1, null)); assertFalse(IOCase.SENSITIVE.checkRegionMatches(null, 1, "ABC")); assertFalse(IOCase.SENSITIVE.checkRegionMatches(null, 1, 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_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_forName() { assertEquals(IOCase.SENSITIVE, IOCase.forName("Sensitive")); assertEquals(IOCase.INSENSITIVE, IOCase.forName("Insensitive")); assertEquals(IOCase.SYSTEM, IOCase.forName("System")); assertThrows(IllegalArgumentException.class, () -> IOCase.forName("Blah")); assertThrows(IllegalArgumentException.class, () -> IOCase.forName(null)); } @Test public void test_getName() { assertEquals("Sensitive", IOCase.SENSITIVE.getName()); assertEquals("Insensitive", IOCase.INSENSITIVE.getName()); assertEquals("System", IOCase.SYSTEM.getName()); } @Test public void test_getScratchByteArray() { final byte[] array = IOUtils.getScratchByteArray(); assert0(array); Arrays.fill(array, (byte) 1); assert0(IOUtils.getScratchCharArray()); } @Test public void test_getScratchByteArrayWriteOnly() { final byte[] array = IOUtils.getScratchByteArrayWriteOnly(); assert0(array); Arrays.fill(array, (byte) 1); assert0(IOUtils.getScratchCharArray()); } @Test public void test_getScratchCharArray() { final char[] array = IOUtils.getScratchCharArray(); assert0(array); Arrays.fill(array, (char) 1); assert0(IOUtils.getScratchCharArray()); } @Test public void test_getScratchCharArrayWriteOnly() { final char[] array = IOUtils.getScratchCharArrayWriteOnly(); assert0(array); Arrays.fill(array, (char) 1); assert0(IOUtils.getScratchCharArray()); } @Test public void test_isCaseSensitive() { assertTrue(IOCase.SENSITIVE.isCaseSensitive()); assertFalse(IOCase.INSENSITIVE.isCaseSensitive()); assertEquals(!WINDOWS, IOCase.SYSTEM.isCaseSensitive()); } @Test public void test_isCaseSensitive_static() { assertTrue(IOCase.isCaseSensitive(IOCase.SENSITIVE)); assertFalse(IOCase.isCaseSensitive(IOCase.INSENSITIVE)); assertEquals(!WINDOWS, IOCase.isCaseSensitive(IOCase.SYSTEM)); } @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_toString() { assertEquals("Sensitive", IOCase.SENSITIVE.toString()); assertEquals("Insensitive", IOCase.INSENSITIVE.toString()); assertEquals("System", IOCase.SYSTEM.toString()); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/IOExceptionListTest.java0100644 0000000 0000000 00000012670 14603604450 030323 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.EOFException; import java.io.PrintWriter; import java.io.StringWriter; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.junit.jupiter.api.Test; /** * Tests {@link IOExceptionList}. */ public class IOExceptionListTest { @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 testCheckEmpty() throws IOExceptionList { IOExceptionList.checkEmpty(null, ""); IOExceptionList.checkEmpty(null, null); IOExceptionList.checkEmpty(Collections.emptyList(), ""); IOExceptionList.checkEmpty(Collections.emptyList(), null); assertThrows(IOExceptionList.class, () -> IOExceptionList.checkEmpty(Collections.singletonList(new Exception()), "")); assertThrows(IOExceptionList.class, () -> IOExceptionList.checkEmpty(Collections.singletonList(new Exception()), null)); } @Test public void testEmptyList() { new IOExceptionList(Collections.emptyList()); new IOExceptionList("foo", Collections.emptyList()); } @Test public void testIterable() { final EOFException cause = new EOFException(); final List list = Collections.singletonList(cause); final IOExceptionList sqlExceptionList = new IOExceptionList("Hello", list); // assertEquals(list, sqlExceptionList.getCauseList()); // No CCE: final List causeList = sqlExceptionList.getCauseList(); assertEquals(list, causeList); // final List list2 = new ArrayList<>(); sqlExceptionList.forEach(list2::add); assertEquals(list2, causeList); } @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 testNullMessageArg() { assertNotNull(new IOExceptionList(null, Collections.emptyList()).getMessage()); assertNotNull(new IOExceptionList(null, null).getMessage()); assertEquals("A", new IOExceptionList("A", Collections.emptyList()).getMessage()); assertEquals("A", new IOExceptionList("A", null).getMessage()); } @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 exception(s): [java.io.EOFException]")); assertTrue(st.contains("Caused by: java.io.EOFException")); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/IOExceptionWithCauseTest.java0100644 0000000 0000000 00000004173 14603604450 031303 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 {@link IOExceptionWithCause}. */ public class IOExceptionWithCauseTest { /** * 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.16.1-src/src/test/java/org/apache/commons/io/IOIndexedExceptionTest.java0100644 0000000 0000000 00000003327 14603604450 030767 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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}. */ public class IOIndexedExceptionTest { @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.16.1-src/src/test/java/org/apache/commons/io/IOUtilsCopyTest.java0100644 0000000 0000000 00000051015 14603604450 027460 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.Paths; import org.apache.commons.io.file.TempFile; 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; /** * Tests {@link IOUtils} copy methods. */ public class IOUtilsCopyTest { /* * 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_byteArrayOutputStreamToInputStream() throws Exception { final java.io.ByteArrayOutputStream out = new java.io.ByteArrayOutputStream(); out.write(inData); final InputStream in = IOUtils.copy(out); final byte[] inData2 = new byte[FILE_SIZE]; final int inSize = in.read(inData2); assertEquals(0, in.available(), "Not all bytes were read"); assertEquals(inData.length, inSize, "Sizes differ"); assertArrayEquals(inData, inData2, "Content differs"); } @Test public void testCopy_byteArrayOutputStreamToInputStream_nullOutputStream() { assertThrows(NullPointerException.class, () -> IOUtils.copy(null)); } @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.INSTANCE; // 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(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"); } /** * Tests 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); try (TempFile path = TempFile.create("testCopy_URLToFile", ".txt")) { IOUtils.copy(in, path.toFile()); assertArrayEquals(Files.readAllBytes(Paths.get("src/test/resources" + name)), Files.readAllBytes(path.get())); } } @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.16.1-src/src/test/java/org/apache/commons/io/IOUtilsMultithreadedSkipTest.java0100644 0000000 0000000 00000013270 14603604450 032171 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 java.io.InputStream; import java.util.Random; import java.util.concurrent.ExecutorCompletionService; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.function.Supplier; import java.util.zip.Inflater; import java.util.zip.InflaterInputStream; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * See Jira ticket IO-802. */ public class IOUtilsMultithreadedSkipTest { private static final String FIXTURE = "TIKA-4065.bin"; long seed = 1; private final ThreadLocal threadLocal = ThreadLocal.withInitial(() -> new byte[4096]); private int[] generateExpected(final InputStream is, final int[] skips) throws IOException { final int[] testBytes = new int[skips.length]; for (int i = 0; i < skips.length; i++) { try { IOUtils.skipFully(is, skips[i]); testBytes[i] = is.read(); } catch (final EOFException e) { testBytes[i] = -1; } } return testBytes; } private int[] generateSkips(final byte[] bytes, final int numSkips, final Random random) { final int[] skips = new int[numSkips]; for (int i = 0; i < skips.length; i++) { skips[i] = random.nextInt(bytes.length / numSkips) + bytes.length / 10; } return skips; } private InputStream inflate(final byte[] deflated) throws IOException { final ByteArrayOutputStream bos = new ByteArrayOutputStream(); IOUtils.copy(new InflaterInputStream(new ByteArrayInputStream(deflated), new Inflater(true)), bos); return new ByteArrayInputStream(bos.toByteArray()); } @BeforeEach public void setUp() { // Not the best random we can use but good enough here. seed = new Random().nextLong(); } private void testSkipFullyOnInflaterInputStream(final Supplier baSupplier) throws Exception { final long thisSeed = seed; // thisSeed = -727624427837034313l; final Random random = new Random(thisSeed); final byte[] bytes; try (final InputStream inputStream = getClass().getResourceAsStream(FIXTURE)) { bytes = IOUtils.toByteArray(inputStream); } final int numSkips = random.nextInt(bytes.length) / 100 + 1; final int[] skips = generateSkips(bytes, numSkips, random); final int[] expected; try (final InputStream inflate = inflate(bytes)) { expected = generateExpected(inflate, skips); } final int numThreads = 2; final int iterations = 100; final ExecutorService executorService = Executors.newFixedThreadPool(numThreads); final ExecutorCompletionService executorCompletionService = new ExecutorCompletionService<>(executorService); for (int i = 0; i < numThreads; i++) { executorCompletionService.submit(() -> { for (int iteration = 0; iteration < iterations; iteration++) { try (InputStream is = new InflaterInputStream(new ByteArrayInputStream(bytes), new Inflater(true))) { for (int skipIndex = 0; skipIndex < skips.length; skipIndex++) { try { IOUtils.skipFully(is, skips[skipIndex], baSupplier); final int c = is.read(); assertEquals(expected[skipIndex], c, "failed on seed=" + seed + " iteration=" + iteration); } catch (final EOFException e) { assertEquals(expected[skipIndex], is.read(), "failed on " + "seed=" + seed + " iteration=" + iteration); } } } } return 1; }); } int finished = 0; while (finished < numThreads) { // blocking final Future future = executorCompletionService.take(); try { future.get(); } catch (final Exception e) { // printStackTrace() for simpler debugging e.printStackTrace(); fail("failed on seed=" + seed); } finished++; } } @Test public void testSkipFullyOnInflaterInputStream_New_bytes() throws Exception { testSkipFullyOnInflaterInputStream(() -> new byte[4096]); } @Test public void testSkipFullyOnInflaterInputStream_ThreadLocal() throws Exception { testSkipFullyOnInflaterInputStream(threadLocal::get); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/IOUtilsTest.java0100644 0000000 0000000 00000215000 14603604450 026621 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.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.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.Charset; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.Arrays; import java.util.List; import java.util.function.Supplier; import java.util.stream.Stream; import org.apache.commons.io.function.IOConsumer; import org.apache.commons.io.input.BrokenInputStream; import org.apache.commons.io.input.CharSequenceInputStream; import org.apache.commons.io.input.CircularInputStream; import org.apache.commons.io.input.NullInputStream; import org.apache.commons.io.input.NullReader; import org.apache.commons.io.output.AppendableWriter; import org.apache.commons.io.output.BrokenOutputStream; import org.apache.commons.io.output.CountingOutputStream; import org.apache.commons.io.output.NullOutputStream; import org.apache.commons.io.output.NullWriter; import org.apache.commons.io.output.StringBuilderWriter; import org.apache.commons.io.test.TestUtils; import org.apache.commons.io.test.ThrowOnCloseReader; import org.apache.commons.lang3.StringUtils; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; 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 {@link 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 IOUtilsTest, one bug may cause multiple tests to fail. */ @SuppressWarnings("deprecation") // deliberately testing deprecated code public class IOUtilsTest { private static final String UTF_8 = StandardCharsets.UTF_8.name(); 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) */ @BeforeAll @AfterAll public static void beforeAll() { // Not required, just to exercise the method and make sure there are no adverse side-effect when recycling thread locals. IO.clear(); } @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"); } try (BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(testFilePath))) { TestUtils.generateTestData(output, FILE_SIZE); } } catch (final IOException e) { fail("Can't run this test because the environment could not be built: " + e.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() { final String npeExpectedMessage = "Expected NullPointerException"; assertThrows(NullPointerException.class, () -> IOUtils.buffer((InputStream) null), npeExpectedMessage); assertThrows(NullPointerException.class, () -> IOUtils.buffer((OutputStream) null), npeExpectedMessage); assertThrows(NullPointerException.class, () -> IOUtils.buffer((Reader) null), npeExpectedMessage); assertThrows(NullPointerException.class, () -> IOUtils.buffer((Writer) null), npeExpectedMessage); } @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 nullWriter = NullWriter.INSTANCE; final BufferedWriter bis = IOUtils.buffer(nullWriter); assertNotSame(nullWriter, bis); assertSame(bis, IOUtils.buffer(bis)); } @Test public void testAsBufferedWriterWithBufferSize() { final Writer nullWriter = NullWriter.INSTANCE; final BufferedWriter bw = IOUtils.buffer(nullWriter, 2024); assertNotSame(nullWriter, bw); assertSame(bw, IOUtils.buffer(bw)); assertSame(bw, IOUtils.buffer(bw, 1024)); } @Test public void testAsWriterAppendable() throws IOException { final Appendable a = new StringBuffer(); try (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() throws IOException { final Appendable a = new StringBuilder(); try (Writer w = IOUtils.writer(a)) { assertNotSame(w, a); assertEquals(StringBuilderWriter.class, w.getClass()); assertSame(w, IOUtils.writer(w)); } } @Test public void testByteArrayWithNegativeSize() { assertThrows(NegativeArraySizeException.class, () -> IOUtils.byteArray(-1)); } @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 = BrokenInputStream.INSTANCE; assertDoesNotThrow(() -> IOUtils.closeQuietly(closeable, null, closeable)); assertDoesNotThrow(() -> IOUtils.closeQuietly(Arrays.asList(closeable, null, closeable))); assertDoesNotThrow(() -> IOUtils.closeQuietly(Stream.of(closeable, null, closeable))); assertDoesNotThrow(() -> IOUtils.closeQuietly((Iterable) null)); } @Test public void testCloseQuietly_CloseableIOException() { assertDoesNotThrow(() -> { IOUtils.closeQuietly(BrokenInputStream.INSTANCE); }); assertDoesNotThrow(() -> { IOUtils.closeQuietly(BrokenOutputStream.INSTANCE); }); } @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 testCloseURLConnection() { assertDoesNotThrow(() -> IOUtils.close((URLConnection) null)); assertDoesNotThrow(() -> IOUtils.close(new URL("https://www.apache.org/").openConnection())); assertDoesNotThrow(() -> IOUtils.close(new URL("file:///").openConnection())); } @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 testConsumeInputStream() throws Exception { final long size = (long) Integer.MAX_VALUE + (long) 1; final InputStream in = new NullInputStream(size); final OutputStream out = NullOutputStream.INSTANCE; // 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 testConsumeReader() throws Exception { final long size = (long) Integer.MAX_VALUE + (long) 1; final Reader in = new NullReader(size); final Writer out = NullWriter.INSTANCE; // 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))); assertFalse(IOUtils.contentEquals(new ByteArrayInputStream("apache".getBytes(StandardCharsets.UTF_8)), new ByteArrayInputStream("apacha".getBytes(StandardCharsets.UTF_8)))); // 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"))); assertFalse(IOUtils.contentEquals(new StringReader("apache"), new StringReader("apacha"))); } @Test public void testContentEqualsIgnoreEOL() throws Exception { { assertTrue(IOUtils.contentEqualsIgnoreEOL(null, null)); } final char[] empty = {}; { final Reader input1 = new CharArrayReader(empty); assertFalse(IOUtils.contentEqualsIgnoreEOL(null, input1)); } { final Reader input1 = new CharArrayReader(empty); assertFalse(IOUtils.contentEqualsIgnoreEOL(input1, null)); } { final Reader input1 = new CharArrayReader(empty); assertTrue(IOUtils.contentEqualsIgnoreEOL(input1, input1)); } { final Reader input1 = new CharArrayReader("321\r\n".toCharArray()); assertTrue(IOUtils.contentEqualsIgnoreEOL(input1, input1)); } testSingleEOL("", "", true); testSingleEOL("", "\n", false); testSingleEOL("", "\r", false); testSingleEOL("", "\r\n", false); testSingleEOL("", "\r\r", false); testSingleEOL("", "\n\n", false); testSingleEOL("1", "1", true); testSingleEOL("1", "2", false); testSingleEOL("123\rabc", "123\nabc", true); testSingleEOL("321", "321\r\n", true); testSingleEOL("321", "321\r\naabb", false); testSingleEOL("321", "321\n", true); testSingleEOL("321", "321\r", true); testSingleEOL("321", "321\r\n", true); testSingleEOL("321", "321\r\r", false); testSingleEOL("321", "321\n\r", false); testSingleEOL("321\n", "321", true); testSingleEOL("321\n", "321\n\r", false); testSingleEOL("321\n", "321\r\n", true); testSingleEOL("321\r", "321\r\n", true); testSingleEOL("321\r\n", "321\r\n\r", false); testSingleEOL("123", "1234", false); testSingleEOL("1235", "1234", false); } @Test public void testCopy_ByteArray_OutputStream() throws Exception { final File destination = TestUtils.newFile(temporaryFolder, "copy8.txt"); final 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"); final 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"); final 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(); assertThrows(EOFException.class, () -> IOUtils.readFully(input, buffer), "Should have failed with EOFException"); } 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]); assertThrows(IllegalArgumentException.class, () -> IOUtils.readFully(input, buffer, 0, -1), "Should have failed with IllegalArgumentException"); IOUtils.readFully(input, buffer, 0, 0); IOUtils.readFully(input, buffer, 0, size - 1); assertThrows(EOFException.class, () -> IOUtils.readFully(input, buffer, 0, 2), "Should have failed with EOFException"); IOUtils.closeQuietly(input); } @Test public void testReadFully_InputStream_Offset() throws Exception { final InputStream stream = CharSequenceInputStream.builder().setCharSequence("abcd1234").setCharset(StandardCharsets.UTF_8).get(); 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(); assertThrows(EOFException.class, () -> IOUtils.readFully(input, buffer), "Should have failed with EOFxception"); } 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); assertThrows(IllegalArgumentException.class, () -> IOUtils.readFully(input, buffer, 0, -1), "Should have failed with IllegalArgumentException"); assertThrows(EOFException.class, () -> IOUtils.readFully(input, buffer, 0, 5), "Should have failed with EOFException"); 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())); } public void testSingleEOL(final String s1, final String s2, final boolean ifEquals) { assertEquals(ifEquals, IOUtils.contentEqualsIgnoreEOL( new CharArrayReader(s1.toCharArray()), new CharArrayReader(s2.toCharArray()) ), "failed at :{" + s1 + "," + s2 + "}"); assertEquals(ifEquals, IOUtils.contentEqualsIgnoreEOL( new CharArrayReader(s2.toCharArray()), new CharArrayReader(s1.toCharArray()) ), "failed at :{" + s2 + "," + s1 + "}"); assertTrue(IOUtils.contentEqualsIgnoreEOL( new CharArrayReader(s1.toCharArray()), new CharArrayReader(s1.toCharArray()) ), "failed at :{" + s1 + "," + s1 + "}"); assertTrue(IOUtils.contentEqualsIgnoreEOL( new CharArrayReader(s2.toCharArray()), new CharArrayReader(s2.toCharArray()) ), "failed at :{" + s2 + "," + s2 + "}"); } @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; try (final InputStream input = new ByteArrayInputStream(new byte[size])) { assertThrows(IllegalArgumentException.class, () -> IOUtils.skipFully(input, -1), "Should have failed with IllegalArgumentException"); IOUtils.skipFully(input, 0); IOUtils.skipFully(input, size - 1); assertThrows(IOException.class, () -> IOUtils.skipFully(input, 2), "Should have failed with IOException"); } } @Test public void testSkipFully_InputStream_Buffer_New_bytes() throws Exception { final int size = 1027; final Supplier bas = () -> new byte[size]; try (final InputStream input = new ByteArrayInputStream(new byte[size])) { assertThrows(IllegalArgumentException.class, () -> IOUtils.skipFully(input, -1, bas), "Should have failed with IllegalArgumentException"); IOUtils.skipFully(input, 0, bas); IOUtils.skipFully(input, size - 1, bas); assertThrows(IOException.class, () -> IOUtils.skipFully(input, 2, bas), "Should have failed with IOException"); } } @Test public void testSkipFully_InputStream_Buffer_Reuse_bytes() throws Exception { final int size = 1027; final byte[] ba = new byte[size]; final Supplier bas = () -> ba; try (final InputStream input = new ByteArrayInputStream(new byte[size])) { assertThrows(IllegalArgumentException.class, () -> IOUtils.skipFully(input, -1, bas), "Should have failed with IllegalArgumentException"); IOUtils.skipFully(input, 0, bas); IOUtils.skipFully(input, size - 1, bas); assertThrows(IOException.class, () -> IOUtils.skipFully(input, 2, bas), "Should have failed with IOException"); } } @Test public void testSkipFully_InputStream_Buffer_Reuse_ThreadLocal() throws Exception { final int size = 1027; final ThreadLocal tl = ThreadLocal.withInitial(() -> new byte[size]); try (final InputStream input = new ByteArrayInputStream(new byte[size])) { assertThrows(IllegalArgumentException.class, () -> IOUtils.skipFully(input, -1, tl::get), "Should have failed with IllegalArgumentException"); IOUtils.skipFully(input, 0, tl::get); IOUtils.skipFully(input, size - 1, tl::get); assertThrows(IOException.class, () -> IOUtils.skipFully(input, 2, tl::get), "Should have failed with IOException"); } } @Test public void testSkipFully_ReadableByteChannel() throws Exception { final FileInputStream fileInputStream = new FileInputStream(testFile); final FileChannel fileChannel = fileInputStream.getChannel(); try { assertThrows(IllegalArgumentException.class, () -> IOUtils.skipFully(fileChannel, -1), "Should have failed with IllegalArgumentException"); IOUtils.skipFully(fileChannel, 0); IOUtils.skipFully(fileChannel, FILE_SIZE - 1); assertThrows(IOException.class, () -> IOUtils.skipFully(fileChannel, 2), "Should have failed with IOException"); } finally { IOUtils.closeQuietly(fileChannel, fileInputStream); } } @Test public void testSkipFully_Reader() throws Exception { final int size = 1027; try (final Reader input = new CharArrayReader(new char[size])) { IOUtils.skipFully(input, 0); IOUtils.skipFully(input, size - 3); assertThrows(IllegalArgumentException.class, () -> IOUtils.skipFully(input, -1), "Should have failed with IllegalArgumentException"); assertThrows(IOException.class, () -> IOUtils.skipFully(input, 5), "Should have failed with IOException"); } } @Test public void testStringToOutputStream() throws Exception { final File destination = TestUtils.newFile(temporaryFolder, "copy5.txt"); final 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)) { final IllegalArgumentException exc = assertThrows(IllegalArgumentException.class, () -> IOUtils.toByteArray(fin, -1), "Should have failed with IllegalArgumentException"); 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)) { final IOException exc = assertThrows(IOException.class, () -> IOUtils.toByteArray(fin, testFile.length() + 1), "Should have failed with IOException"); 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)) { final IllegalArgumentException exc = assertThrows(IllegalArgumentException.class, () -> IOUtils.toByteArray(fin, (long) Integer.MAX_VALUE + 1), "Should have failed with IllegalArgumentException"); 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_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_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_Reader() throws IOException { final String charsetName = UTF_8; final byte[] expected = charsetName.getBytes(charsetName); byte[] actual = IOUtils.toByteArray(new InputStreamReader(new ByteArrayInputStream(expected))); assertArrayEquals(expected, actual); actual = IOUtils.toByteArray(new InputStreamReader(new ByteArrayInputStream(expected)), charsetName); assertArrayEquals(expected, actual); } @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 byte[] actual; try (CloseableURLConnection urlConnection = CloseableURLConnection.open(testFile.toURI())) { actual = IOUtils.toByteArray(urlConnection); } 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(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(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_InputStreamSupplier() throws Exception { final String out = IOUtils.toString(() -> Files.newInputStream(testFilePath), Charset.defaultCharset()); assertNotNull(out); assertEquals(FILE_SIZE, out.length(), "Wrong output size"); assertNull(IOUtils.toString(null, Charset.defaultCharset(), () -> null)); assertNull(IOUtils.toString(() -> null, Charset.defaultCharset(), () -> null)); assertEquals("A", IOUtils.toString(null, Charset.defaultCharset(), () -> "A")); } @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(StandardCharsets.US_ASCII.name()); } @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(StandardCharsets.US_ASCII.name()); } @Test public void testToString_URL_CharsetNameNull() throws Exception { testToString_URL(null); } /** * IO-764 IOUtils.write() throws NegativeArraySizeException while writing big strings. *
     * java.lang.OutOfMemoryError: Java heap space
     *     at java.lang.StringCoding.encode(StringCoding.java:350)
     *     at java.lang.String.getBytes(String.java:941)
     *     at org.apache.commons.io.IOUtils.write(IOUtils.java:3367)
     *     at org.apache.commons.io.IOUtilsTest.testBigString(IOUtilsTest.java:1659)
     * 
*/ @Test public void testWriteBigString() throws IOException { // 3_000_000 is a size that we can allocate for the test string with Java 8 on the command line as: // mvn clean test -Dtest=IOUtilsTest -DtestBigString=3000000 // 6_000_000 failed with the above // // TODO Can we mock the test string for this test to pretend to be larger? // Mocking the length seems simple but how about the data? final int repeat = Integer.getInteger("testBigString", 3_000_000); final String data; try { data = StringUtils.repeat("\uD83D", repeat); } catch (final OutOfMemoryError e) { System.err.printf("Don't fail the test if we cannot build the fixture, just log, fixture size = %,d%n.", repeat); e.printStackTrace(); return; } try (CountingOutputStream os = new CountingOutputStream(NullOutputStream.INSTANCE)) { IOUtils.write(data, os, StandardCharsets.UTF_8); assertEquals(repeat, os.getByteCount()); } } @Test public void testWriteLines() throws IOException { final String[] data = {"The", "quick"}; final ByteArrayOutputStream out = new ByteArrayOutputStream(); IOUtils.writeLines(Arrays.asList(data), "\n", out, StandardCharsets.UTF_16.name()); final String result = new String(out.toByteArray(), StandardCharsets.UTF_16); assertEquals("The\nquick\n", result); } @Test public void testWriteLittleString() throws IOException { final String data = "\uD83D"; // White-box test to check that not closing the internal channel is not a problem. for (int i = 0; i < 1_000_000; i++) { try (CountingOutputStream os = new CountingOutputStream(NullOutputStream.INSTANCE)) { IOUtils.write(data, os, StandardCharsets.UTF_8); assertEquals(data.length(), os.getByteCount()); } } } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/IOUtilsWriteTest.java0100644 0000000 0000000 00000067556 14603604450 027661 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.assertThrows; 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; /** * Tests IOUtils write methods. * * @see IOUtils */ @SuppressWarnings("deprecation") // includes tests for deprecated methods public class IOUtilsWriteTest { 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 { assertThrows(NullPointerException.class, () -> IOUtils.write(inData, (OutputStream) null)); } @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_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_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_byteArrayToWriter_Encoding_nullWriter() throws Exception { assertThrows(NullPointerException.class, () -> IOUtils.write(inData, null, "UTF8")); } @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 { assertThrows(NullPointerException.class, () -> IOUtils.write(inData, (Writer) null)); } @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_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); assertThrows(NullPointerException.class, () -> IOUtils.write(str.toCharArray(), (OutputStream) null)); } @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_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_charArrayToOutputStream_nullStream() throws Exception { final String str = new String(inData, StandardCharsets.US_ASCII); assertThrows(NullPointerException.class, () -> IOUtils.write(str.toCharArray(), (OutputStream) null)); } @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); assertThrows(NullPointerException.class, () -> IOUtils.write(str.toCharArray(), (Writer) null)); } @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_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)); assertThrows(NullPointerException.class, () -> IOUtils.write(csq, (OutputStream) null)); } @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_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_charSequenceToOutputStream_nullStream() throws Exception { final CharSequence csq = new StringBuilder(new String(inData, StandardCharsets.US_ASCII)); assertThrows(NullPointerException.class, () -> IOUtils.write(csq, (OutputStream) null)); } @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)); assertThrows(NullPointerException.class, () -> IOUtils.write(csq, (Writer) null)); } @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_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); assertThrows(NullPointerException.class, () -> IOUtils.write(str, (OutputStream) null)); } @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_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_stringToOutputStream_nullStream() throws Exception { final String str = new String(inData, StandardCharsets.US_ASCII); assertThrows(NullPointerException.class, () -> IOUtils.write(str, (OutputStream) null)); } @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); assertThrows(NullPointerException.class, () -> IOUtils.write(str, (Writer) null)); } @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_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, StandardCharsets.UTF_8.name()); out.off(); out.flush(); final String expected = "hello\u8364*world**this is**some text*"; final String actual = baout.toString(StandardCharsets.UTF_8.name()); 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, StandardCharsets.US_ASCII.name()); out.off(); out.flush(); assertEquals(0, baout.size(), "Sizes differ"); } @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_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, StandardCharsets.US_ASCII.name()); 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); assertThrows(NullPointerException.class, () -> IOUtils.writeLines(list, "*", null, StandardCharsets.US_ASCII.name())); } @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); assertThrows(NullPointerException.class, () -> IOUtils.writeLines(list, "*", (OutputStream) null)); } @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); assertThrows(NullPointerException.class, () -> IOUtils.writeLines(list, "*", (Writer) null)); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/LineIteratorTest.java0100644 0000000 0000000 00000027657 14603604450 027715 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.nio.charset.StandardCharsets; import java.nio.charset.UnsupportedCharsetException; import java.nio.file.Files; import java.nio.file.NoSuchFileException; 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; /** * Tests {@link LineIterator}. */ public class LineIteratorTest { private static final String UTF_8 = StandardCharsets.UTF_8.name(); @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 { IOUtils.closeQuietly(iterator); } } /** * 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; } /** * 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 (LineIterator iterator = FileUtils.lineIterator(testFile, encoding)) { assertThrows(UnsupportedOperationException.class, iterator::remove); 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 assertThrows(NoSuchElementException.class, iterator::next); assertThrows(NoSuchElementException.class, iterator::nextLine); } } @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 (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"); assertThrows(NoSuchElementException.class, iterator::next); assertThrows(NoSuchElementException.class, iterator::nextLine); // try closing again iterator.close(); assertThrows(NoSuchElementException.class, iterator::next); assertThrows(NoSuchElementException.class, iterator::nextLine); } } @Test public void testConstructor() { assertThrows(NullPointerException.class, () -> new LineIterator(null)); } private void testFiltering(final List lines, final Reader reader) throws IOException { try (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; } }) { assertThrows(UnsupportedOperationException.class, iterator::remove); 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 assertThrows(NoSuchElementException.class, iterator::next); assertThrows(NoSuchElementException.class, iterator::nextLine); } } @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); } @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 testInvalidEncoding() throws Exception { final String encoding = "XXXXXXXX"; final File testFile = new File(temporaryFolder, "LineIterator-invalidEncoding.txt"); createLinesFile(testFile, UTF_8, 3); assertThrows(UnsupportedCharsetException.class, () -> FileUtils.lineIterator(testFile, encoding)); } @Test public void testMissingFile() throws Exception { final File testFile = new File(temporaryFolder, "dummy-missing-file.txt"); assertThrows(NoSuchFileException.class, () -> FileUtils.lineIterator(testFile, UTF_8)); } @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 (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 testOneLines() throws Exception { doTestFileWithSpecifiedLines(1); } @Test public void testThreeLines() throws Exception { doTestFileWithSpecifiedLines(3); } @Test public void testTwoLines() throws Exception { doTestFileWithSpecifiedLines(2); } @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 (LineIterator iterator = FileUtils.lineIterator(testFile, encoding)) { int count = 0; while (iterator.hasNext()) { assertNotNull(iterator.next()); count++; } assertEquals(3, count); } } @Test public void testZeroLines() throws Exception { doTestFileWithSpecifiedLines(0); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/RandomAccessFilesTest.java0100644 0000000 0000000 00000015772 14603604450 030634 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.file.Files; import java.nio.file.Path; import java.util.Arrays; import org.junit.jupiter.api.Test; /** * Tests {@link RandomAccessFiles}. */ public class RandomAccessFilesTest { private static final String FILE_NAME_RO_20 = "src/test/resources/org/apache/commons/io/test-file-20byteslength.bin"; private static final String FILE_NAME_RO_0 = "src/test/resources/org/apache/commons/io/test-file-empty.bin"; private static final String FILE_NAME_RO_0_BIS = "src/test/resources/org/apache/commons/io/test-file-empty2.bin"; @Test public void testContentEquals() throws IOException { try (RandomAccessFile raf1 = RandomAccessFileMode.READ_ONLY.create(FILE_NAME_RO_20)) { assertEquals(raf1, raf1); assertTrue(RandomAccessFiles.contentEquals(raf1, raf1)); } // as above, to make sure resources are OK try (RandomAccessFile raf1 = RandomAccessFileMode.READ_ONLY.create(FILE_NAME_RO_20)) { assertEquals(raf1, raf1); assertTrue(RandomAccessFiles.contentEquals(raf1, raf1)); } // same 20 bytes try (RandomAccessFile raf1 = RandomAccessFileMode.READ_ONLY.create(FILE_NAME_RO_20); RandomAccessFile raf2 = RandomAccessFileMode.READ_ONLY.create(FILE_NAME_RO_20)) { assertTrue(RandomAccessFiles.contentEquals(raf1, raf2)); } // same empty file try (RandomAccessFile raf1 = RandomAccessFileMode.READ_ONLY.create(FILE_NAME_RO_0); RandomAccessFile raf2 = RandomAccessFileMode.READ_ONLY.create(FILE_NAME_RO_0)) { assertTrue(RandomAccessFiles.contentEquals(raf1, raf2)); assertTrue(RandomAccessFiles.contentEquals(RandomAccessFiles.reset(raf2), RandomAccessFiles.reset(raf1))); } // diff empty file try (RandomAccessFile raf1 = RandomAccessFileMode.READ_ONLY.create(FILE_NAME_RO_0); RandomAccessFile raf2 = RandomAccessFileMode.READ_ONLY.create(FILE_NAME_RO_0_BIS)) { assertTrue(RandomAccessFiles.contentEquals(raf1, raf2)); assertTrue(RandomAccessFiles.contentEquals(RandomAccessFiles.reset(raf2), RandomAccessFiles.reset(raf1))); } try (RandomAccessFile raf1 = RandomAccessFileMode.READ_ONLY.create(FILE_NAME_RO_0); RandomAccessFile raf2 = RandomAccessFileMode.READ_ONLY.create(FILE_NAME_RO_20)) { assertFalse(RandomAccessFiles.contentEquals(raf1, raf2)); assertFalse(RandomAccessFiles.contentEquals(RandomAccessFiles.reset(raf2), RandomAccessFiles.reset(raf1))); } // final Path bigFile1 = Files.createTempFile(getClass().getSimpleName(), "-1.bin"); final Path bigFile2 = Files.createTempFile(getClass().getSimpleName(), "-2.bin"); final Path bigFile3 = Files.createTempFile(getClass().getSimpleName(), "-3.bin"); try { final int newLength = 1_000_000; final byte[] bytes1 = new byte[newLength]; final byte[] bytes2 = new byte[newLength]; Arrays.fill(bytes1, (byte) 1); Arrays.fill(bytes2, (byte) 2); Files.write(bigFile1, bytes1); Files.write(bigFile2, bytes2); try (RandomAccessFile raf1 = RandomAccessFileMode.READ_ONLY.create(bigFile1); RandomAccessFile raf2 = RandomAccessFileMode.READ_ONLY.create(bigFile2)) { assertFalse(RandomAccessFiles.contentEquals(raf1, raf2)); assertFalse(RandomAccessFiles.contentEquals(RandomAccessFiles.reset(raf2), RandomAccessFiles.reset(raf1))); assertTrue(RandomAccessFiles.contentEquals(RandomAccessFiles.reset(raf1), RandomAccessFiles.reset(raf1))); } // Make the last byte different final byte[] bytes3 = bytes1.clone(); bytes3[bytes3.length - 1] = 9; Files.write(bigFile3, bytes3); try (RandomAccessFile raf1 = RandomAccessFileMode.READ_ONLY.create(bigFile1); RandomAccessFile raf3 = RandomAccessFileMode.READ_ONLY.create(bigFile3)) { assertFalse(RandomAccessFiles.contentEquals(raf1, raf3)); assertFalse(RandomAccessFiles.contentEquals(RandomAccessFiles.reset(raf3), RandomAccessFiles.reset(raf1))); } } finally { // Delete ASAP Files.deleteIfExists(bigFile1); Files.deleteIfExists(bigFile2); Files.deleteIfExists(bigFile3); } } @Test public void testRead() throws IOException { try (final RandomAccessFile raf = RandomAccessFileMode.READ_ONLY.create(FILE_NAME_RO_20)) { final byte[] buffer = RandomAccessFiles.read(raf, 0, 0); assertArrayEquals(new byte[] {}, buffer); } try (final RandomAccessFile raf = RandomAccessFileMode.READ_ONLY.create(FILE_NAME_RO_20)) { final byte[] buffer = RandomAccessFiles.read(raf, 1, 0); assertArrayEquals(new byte[] {}, buffer); } try (final RandomAccessFile raf = RandomAccessFileMode.READ_ONLY.create(FILE_NAME_RO_20)) { final byte[] buffer = RandomAccessFiles.read(raf, 0, 1); assertArrayEquals(new byte[] { '1' }, buffer); } try (final RandomAccessFile raf = RandomAccessFileMode.READ_ONLY.create(FILE_NAME_RO_20)) { final byte[] buffer = RandomAccessFiles.read(raf, 1, 1); assertArrayEquals(new byte[] { '2' }, buffer); } try (final RandomAccessFile raf = RandomAccessFileMode.READ_ONLY.create(FILE_NAME_RO_20)) { final byte[] buffer = RandomAccessFiles.read(raf, 0, 20); assertEquals(20, buffer.length); } try (final RandomAccessFile raf = RandomAccessFileMode.READ_ONLY.create(FILE_NAME_RO_20)) { assertThrows(IOException.class, () -> RandomAccessFiles.read(raf, 0, 21)); } } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/SelectorAdapter.java0100644 0000000 0000000 00000003477 14603604450 027527 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 void close() throws IOException { } @Override public boolean isOpen() { return false; } @Override public Set keys() { return null; } @Override public SelectorProvider provider() { return null; } @Override public int select() throws IOException { return 0; } @Override public int select(final long timeout) throws IOException { return 0; } @Override public Set selectedKeys() { return null; } @Override public int selectNow() throws IOException { return 0; } @Override public Selector wakeup() { return null; } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/StandardLineSeparatorTest.java0100644 0000000 0000000 00000004061 14603604450 031525 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.16.1-src/src/test/java/org/apache/commons/io/StreamIteratorTest.java0100644 0000000 0000000 00000003745 14603604450 030251 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 java.util.Iterator; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Stream; import org.junit.jupiter.api.Test; /** * Tests {@link StreamIterator}. */ public class StreamIteratorTest { @Test public void testForEachRemaining() { final AtomicBoolean closed = new AtomicBoolean(); final Iterator iter = StreamIterator.iterator(Stream.of(1, 2, 3).onClose(() -> closed.set(true))); final AtomicInteger sum = new AtomicInteger(); iter.forEachRemaining(sum::addAndGet); assertEquals(6, sum.get()); assertTrue(closed.get()); } @Test public void testHasNext() { final AtomicBoolean closed = new AtomicBoolean(); final Iterator iter = StreamIterator.iterator(Stream.of(1, 2, 3).onClose(() -> closed.set(true))); int sum = 0; while (iter.hasNext()) { sum += iter.next(); } assertEquals(6, sum); assertTrue(closed.get()); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/TaggedIOExceptionTest.java0100644 0000000 0000000 00000003320 14603604450 030573 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; /** * Tests {@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.16.1-src/src/test/java/org/apache/commons/io/TestResources.java0100644 0000000 0000000 00000003466 14603604450 027256 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 InputStream getInputStream(final String fileName) { return TestResources.class.getResourceAsStream(ROOT + 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); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/ThreadMonitorTest.java0100644 0000000 0000000 00000005344 14603604450 030060 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.assertThrows; 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 ThreadMonitorTest { /** * Test task completed before timeout. */ @Test public void testCompletedWithoutTimeout() { try { final Thread monitor = ThreadMonitor.start(Duration.ofMillis(400)); TestUtils.sleep(1); ThreadMonitor.stop(monitor); } catch (final InterruptedException e) { fail("Timed Out", e); } } /** * Test No timeout. */ @Test public void testNoTimeoutMinus1() { // 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, e); } } /** * Test No timeout. */ @Test public void testNoTimeoutZero() { // 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, e); } } /** * Test timeout. */ @Test public void testTimeout() { assertThrows(InterruptedException.class, () -> { final Thread monitor = ThreadMonitor.start(Duration.ofMillis(100)); TestUtils.sleep(400); ThreadMonitor.stop(monitor); }); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/UncheckedIOExceptionsTest.java0100644 0000000 0000000 00000003710 14603604450 031457 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.io.IOException; import java.io.UncheckedIOException; import org.junit.jupiter.api.Test; /** * Tests {@link UncheckedIOExceptions}. */ public class UncheckedIOExceptionsTest { /** * Tests {@link UncheckedIOExceptions#create(Object)}. */ @Test public void testCreate() { final Object message = "test"; try { throw UncheckedIOExceptions.create(message); } catch (final UncheckedIOException e) { assertEquals(message, e.getMessage()); assertEquals(message, e.getCause().getMessage()); } } /** * Tests {@link UncheckedIOExceptions#wrap(IOException, Object)}. */ @Test public void testWrap() { final Object message1 = "test1"; final Object message2 = "test2"; try { throw UncheckedIOExceptions.wrap(new IOException(message2.toString()), message1); } catch (final UncheckedIOException e) { assertEquals(message1, e.getMessage()); assertEquals(message2, e.getCause().getMessage()); } } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/build/AbstractOriginTest.java0100644 0000000 0000000 00000010402 14603604450 031302 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.build; 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 java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.Reader; import java.io.Writer; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Paths; import java.util.Objects; import org.junit.jupiter.api.Test; /** * Tests {@link AbstractOrigin} and subclasses. * * @param the type of instances to build. * @param the type of builder subclass. */ public abstract class AbstractOriginTest> { protected static final String FILE_RES_RO = "/org/apache/commons/io/test-file-20byteslength.bin"; protected static final String FILE_NAME_RO = "src/test/resources" + FILE_RES_RO; protected static final String FILE_NAME_RW = "target/" + AbstractOriginTest.class.getSimpleName() + ".txt"; protected AbstractOrigin originRo; protected AbstractOrigin originRw; protected AbstractOrigin getOriginRo() { return Objects.requireNonNull(originRo, "originRo"); } protected AbstractOrigin getOriginRw() { return Objects.requireNonNull(originRw, "originRw"); } protected void setOriginRo(final AbstractOrigin origin) { this.originRo = origin; } protected void setOriginRw(final AbstractOrigin origin) { this.originRw = origin; } @Test public void testGetByteArray() throws IOException { assertArrayEquals(Files.readAllBytes(Paths.get(FILE_NAME_RO)), getOriginRo().getByteArray()); } @Test public void testGetByteArrayAt_0_0() throws IOException { assertArrayEquals(new byte[] {}, getOriginRo().getByteArray(0, 0)); } @Test public void testGetByteArrayAt_0_1() throws IOException { assertArrayEquals(new byte[] { '1' }, getOriginRo().getByteArray(0, 1)); } @Test public void testGetByteArrayAt_1_1() throws IOException { assertArrayEquals(new byte[] { '2' }, getOriginRo().getByteArray(1, 1)); } @Test public void testGetCharSequence() throws IOException { assertNotNull(getOriginRo().getCharSequence(Charset.defaultCharset())); } @Test public void testGetFile() { assertNotNull(getOriginRo().getFile()); } @Test public void testGetInputStream() throws IOException { try (final InputStream inputStream = getOriginRo().getInputStream()) { assertNotNull(inputStream); } } @Test public void testGetOutputStream() throws IOException { try (final OutputStream output = getOriginRw().getOutputStream()) { assertNotNull(output); } } @Test public void testGetPath() { assertNotNull(getOriginRo().getPath()); } @Test public void testGetReader() throws IOException { try (final Reader reader = getOriginRo().getReader(Charset.defaultCharset())) { assertNotNull(reader); } } @Test public void testGetWriter() throws IOException { try (final Writer writer = getOriginRw().getWriter(Charset.defaultCharset())) { assertNotNull(writer); } } @Test public void testSize() throws IOException { assertEquals(Files.size(Paths.get(FILE_NAME_RO)), getOriginRo().getByteArray().length); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/build/AbstractStreamBuilderTest.java0100644 0000000 0000000 00000004367 14603604450 032632 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.build; 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.util.Arrays; import org.junit.jupiter.api.Test; /** * Tests {@link AbstractStreamBuilder}. */ public class AbstractStreamBuilderTest { public static class Builder extends AbstractStreamBuilder { @Override public char[] get() { final char[] arr = new char[getBufferSize()]; Arrays.fill(arr, 'a'); return arr; } } private void assertResult(final char[] arr, final int size) { assertNotNull(arr); assertEquals(size, arr.length); for (final char c : arr) { assertEquals('a', c); } } protected Builder builder() { return new Builder(); } @Test public void testBufferSizeChecker() { // sanity final Builder builder = builder(); assertResult(builder.get(), builder.getBufferSize()); // basic failure assertThrows(IllegalArgumentException.class, () -> builder().setBufferSizeMax(2).setBufferSize(3)); // reset assertResult(builder.setBufferSizeMax(2).setBufferSizeMax(0).setBufferSize(3).get(), 3); // resize assertResult(builder().setBufferSizeMax(2).setBufferSizeChecker(i -> 100).setBufferSize(3).get(), 100); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/build/ByteArrayOriginTest.java0100644 0000000 0000000 00000004437 14603604450 031454 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.build; import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import org.apache.commons.io.build.AbstractOrigin.ByteArrayOrigin; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Tests {@link ByteArrayOrigin}. * * A ByteArrayOrigin can convert into some of the other aspects. */ public class ByteArrayOriginTest extends AbstractOriginTest { @BeforeEach public void beforeEach() throws IOException { setOriginRo(new ByteArrayOrigin(Files.readAllBytes(Paths.get(FILE_NAME_RO)))); setOriginRw(new ByteArrayOrigin(new byte[] { 1 })); } @Override @Test public void testGetFile() { // Cannot convert a byte[] to a File. assertThrows(UnsupportedOperationException.class, super::testGetFile); } @Override @Test public void testGetOutputStream() { // Cannot convert a byte[] to an OutputStream. assertThrows(UnsupportedOperationException.class, super::testGetOutputStream); } @Override @Test public void testGetPath() { // Cannot convert a byte[] to a Path. assertThrows(UnsupportedOperationException.class, super::testGetPath); } @Override @Test public void testGetWriter() { // Cannot convert a byte[] to a Writer. assertThrows(UnsupportedOperationException.class, super::testGetWriter); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/build/CharSequenceOriginTest.java0100644 0000000 0000000 00000006035 14603604450 032114 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.build; 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.FileNotFoundException; import java.io.IOException; import java.io.Reader; import java.nio.charset.StandardCharsets; import org.apache.commons.io.IOUtils; import org.apache.commons.io.build.AbstractOrigin.CharSequenceOrigin; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Tests {@link CharSequenceOrigin}. * * A CharSequenceOrigin can convert into some of the other aspects. */ public class CharSequenceOriginTest extends AbstractOriginTest { @BeforeEach public void beforeEach() throws FileNotFoundException, IOException { setOriginRo(new CharSequenceOrigin(getFixtureStringFromFile())); setOriginRw(new CharSequenceOrigin("World")); } private String getFixtureStringFromFile() throws IOException { return IOUtils.resourceToString(FILE_RES_RO, StandardCharsets.UTF_8); } @Override @Test public void testGetFile() { // Cannot convert a CharSequence to a File. assertThrows(UnsupportedOperationException.class, super::testGetFile); } @Override @Test public void testGetOutputStream() { // Cannot convert a CharSequence to an OutputStream. assertThrows(UnsupportedOperationException.class, super::testGetOutputStream); } @Override @Test public void testGetPath() { // Cannot convert a CharSequence to a Path. assertThrows(UnsupportedOperationException.class, super::testGetPath); } @Test public void testGetReaderIgnoreCharset() throws IOException { // The CharSequenceOrigin ignores the given Charset. try (final Reader reader = getOriginRo().getReader(StandardCharsets.UTF_16LE)) { assertNotNull(reader); assertEquals(getFixtureStringFromFile(), IOUtils.toString(reader)); } } @Override @Test public void testGetWriter() { // Cannot convert a CharSequence to a Writer. assertThrows(UnsupportedOperationException.class, super::testGetWriter); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/build/FileOriginTest.java0100644 0000000 0000000 00000002441 14603604450 030422 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.build; import java.io.File; import org.apache.commons.io.build.AbstractOrigin.FileOrigin; import org.junit.jupiter.api.BeforeEach; /** * Tests {@link FileOrigin}. * * A FileOrigin can convert into all other aspects. */ public class FileOriginTest extends AbstractOriginTest { @BeforeEach public void beforeEach() { setOriginRo(new FileOrigin(new File(FILE_NAME_RO))); setOriginRw(new FileOrigin(new File(FILE_NAME_RW))); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/build/InputStreamOriginTest.java0100644 0000000 0000000 00000004742 14603604450 032024 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.build; import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; import org.apache.commons.io.build.AbstractOrigin.InputStreamOrigin; import org.apache.commons.io.input.CharSequenceInputStream; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Tests {@link InputStreamOrigin}. * * A InputStreamOrigin can convert into some of the other aspects. */ public class InputStreamOriginTest extends AbstractOriginTest { @SuppressWarnings("resource") @BeforeEach public void beforeEach() throws FileNotFoundException { setOriginRo(new InputStreamOrigin(new FileInputStream(FILE_NAME_RO))); setOriginRw(new InputStreamOrigin(CharSequenceInputStream.builder().setCharSequence("World").get())); } @Override @Test public void testGetFile() { // Cannot convert a InputStream to a File. assertThrows(UnsupportedOperationException.class, super::testGetFile); } @Override @Test public void testGetOutputStream() { // Cannot convert a InputStream to an OutputStream. assertThrows(UnsupportedOperationException.class, super::testGetOutputStream); } @Override @Test public void testGetPath() { // Cannot convert a InputStream to a Path. assertThrows(UnsupportedOperationException.class, super::testGetPath); } @Override @Test public void testGetWriter() { // Cannot convert a InputStream to a Writer. assertThrows(UnsupportedOperationException.class, super::testGetWriter); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/build/OutputStreamOriginTest.java0100644 0000000 0000000 00000007111 14603604450 032216 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.build; import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.OutputStream; import org.apache.commons.io.build.AbstractOrigin.OutputStreamOrigin; import org.apache.commons.io.output.ByteArrayOutputStream; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Tests {@link OutputStreamOrigin}. * * A OutputStreamOrigin can convert into some of the other aspects. */ public class OutputStreamOriginTest extends AbstractOriginTest { @SuppressWarnings("resource") @BeforeEach public void beforeEach() { setOriginRo(new OutputStreamOrigin(new ByteArrayOutputStream())); setOriginRw(new OutputStreamOrigin(new ByteArrayOutputStream())); } @Override @Test public void testGetByteArray() { // Cannot convert a OutputStream to a byte[]. assertThrows(UnsupportedOperationException.class, super::testGetByteArray); } @Override @Test public void testGetByteArrayAt_0_0() { // Cannot convert a OutputStream to a byte[]. assertThrows(UnsupportedOperationException.class, super::testGetByteArrayAt_0_0); } @Override @Test public void testGetByteArrayAt_0_1() { // Cannot convert a OutputStream to a byte[]. assertThrows(UnsupportedOperationException.class, super::testGetByteArrayAt_0_1); } @Override @Test public void testGetByteArrayAt_1_1() { // Cannot convert a OutputStream to a byte[]. assertThrows(UnsupportedOperationException.class, super::testGetByteArrayAt_1_1); } @Override @Test public void testGetCharSequence() { // Cannot convert a OutputStream to a CharSequence. assertThrows(UnsupportedOperationException.class, super::testGetCharSequence); } @Override @Test public void testGetFile() { // Cannot convert a OutputStream to a File. assertThrows(UnsupportedOperationException.class, super::testGetFile); } @Override @Test public void testGetInputStream() { // Cannot convert a OutputStream to an InputStream. assertThrows(UnsupportedOperationException.class, super::testGetInputStream); } @Override @Test public void testGetPath() { // Cannot convert a OutputStream to a Path. assertThrows(UnsupportedOperationException.class, super::testGetPath); } @Override @Test public void testGetReader() { // Cannot convert a OutputStream to a Reader. assertThrows(UnsupportedOperationException.class, super::testGetReader); } @Override @Test public void testSize() { // Cannot convert a Writer to a size. assertThrows(UnsupportedOperationException.class, super::testSize); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/build/PathOriginTest.java0100644 0000000 0000000 00000002505 14603604450 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.build; import java.nio.file.Path; import java.nio.file.Paths; import org.apache.commons.io.build.AbstractOrigin.PathOrigin; import org.junit.jupiter.api.BeforeEach; /** * Tests {@link PathOrigin}. * * A PathOrigin can convert into all other aspects. */ public class PathOriginTest extends AbstractOriginTest { @BeforeEach public void beforeEach() { setOriginRo(new PathOrigin(Paths.get(FILE_NAME_RO))); setOriginRw(new PathOrigin(Paths.get(FILE_NAME_RW))); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/build/ReaderOriginTest.java0100644 0000000 0000000 00000004561 14603604450 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.build; import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.Reader; import org.apache.commons.io.build.AbstractOrigin.ReaderOrigin; import org.apache.commons.io.input.CharSequenceReader; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Tests {@link ReaderOrigin}. * * A ReaderOrigin can convert into some of the other aspects. */ public class ReaderOriginTest extends AbstractOriginTest { @SuppressWarnings("resource") @BeforeEach public void beforeEach() throws FileNotFoundException { setOriginRo(new ReaderOrigin(new FileReader(FILE_NAME_RO))); setOriginRw(new ReaderOrigin(new CharSequenceReader("World"))); } @Override @Test public void testGetFile() { // Cannot convert a Reader to a File. assertThrows(UnsupportedOperationException.class, super::testGetFile); } @Override @Test public void testGetOutputStream() { // Cannot convert a Reader to an OutputStream. assertThrows(UnsupportedOperationException.class, super::testGetOutputStream); } @Override @Test public void testGetPath() { // Cannot convert a Reader to a Path. assertThrows(UnsupportedOperationException.class, super::testGetPath); } @Override @Test public void testGetWriter() { // Cannot convert a Reader to a Writer. assertThrows(UnsupportedOperationException.class, super::testGetWriter); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/build/URIOriginTest.java0100644 0000000 0000000 00000002507 14603604450 030205 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.build; import java.net.URI; import java.nio.file.Paths; import org.apache.commons.io.build.AbstractOrigin.URIOrigin; import org.junit.jupiter.api.BeforeEach; /** * Tests {@link URIOrigin}. * * A URIOrigin can convert into all other aspects. */ public class URIOriginTest extends AbstractOriginTest { @BeforeEach public void beforeEach() { setOriginRo(new URIOrigin(Paths.get(FILE_NAME_RO).toUri())); setOriginRw(new URIOrigin(Paths.get(FILE_NAME_RW).toUri())); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/build/WriterStreamOriginTest.java0100644 0000000 0000000 00000006643 14603604450 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.build; import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.StringWriter; import java.io.Writer; import org.apache.commons.io.build.AbstractOrigin.WriterOrigin; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Tests {@link WriterOrigin}. * * A WriterOrigin can convert into some of the other aspects. */ public class WriterStreamOriginTest extends AbstractOriginTest { @BeforeEach public void beforeEach() { setOriginRo(new WriterOrigin(new StringWriter())); setOriginRw(new WriterOrigin(new StringWriter())); } @Override @Test public void testGetByteArray() { // Cannot convert a Writer to a byte[]. assertThrows(UnsupportedOperationException.class, super::testGetByteArray); } @Override @Test public void testGetByteArrayAt_0_0() { // Cannot convert a OutputStream to a byte[]. assertThrows(UnsupportedOperationException.class, super::testGetByteArrayAt_0_0); } @Override @Test public void testGetByteArrayAt_0_1() { // Cannot convert a OutputStream to a byte[]. assertThrows(UnsupportedOperationException.class, super::testGetByteArrayAt_0_1); } @Override @Test public void testGetByteArrayAt_1_1() { // Cannot convert a OutputStream to a byte[]. assertThrows(UnsupportedOperationException.class, super::testGetByteArrayAt_1_1); } @Override @Test public void testGetCharSequence() { // Cannot convert a Writer to a CharSequence. assertThrows(UnsupportedOperationException.class, super::testGetCharSequence); } @Override @Test public void testGetFile() { // Cannot convert a Writer to a File. assertThrows(UnsupportedOperationException.class, super::testGetFile); } @Override @Test public void testGetInputStream() { // Cannot convert a Writer to an InputStream. assertThrows(UnsupportedOperationException.class, super::testGetInputStream); } @Override @Test public void testGetPath() { // Cannot convert a Writer to a Path. assertThrows(UnsupportedOperationException.class, super::testGetPath); } @Override @Test public void testGetReader() { // Cannot convert a Writer to a Reader. assertThrows(UnsupportedOperationException.class, super::testGetReader); } @Override @Test public void testSize() { // Cannot convert a Writer to a size. assertThrows(UnsupportedOperationException.class, super::testSize); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/channels/FileChannelsTest.java0100644 0000000 0000000 00000011754 14603604450 031431 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.channels; import static java.nio.charset.StandardCharsets.US_ASCII; 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.FileInputStream; import java.io.IOException; import java.nio.channels.FileChannel; import org.apache.commons.io.FileUtils; import org.apache.commons.io.file.AbstractTempDirTest; import org.apache.commons.lang3.StringUtils; import org.junit.jupiter.api.Test; /** * Tests {@link FileChannels}. */ public class FileChannelsTest extends AbstractTempDirTest { private static final int BUFFER_SIZE = 1024; private static final String CONTENT = StringUtils.repeat("x", BUFFER_SIZE); private boolean isEmpty(final File empty) { return empty.length() == 0; } private void testContentEquals(final String content1, final String content2) throws IOException { assertTrue(FileChannels.contentEquals(null, null, BUFFER_SIZE)); // Prepare test files with same size but different content // (first 3 bytes are different, followed by a large amount of equal content) final File file1 = new File(tempDirFile, "test1.txt"); final File file2 = new File(tempDirFile, "test2.txt"); FileUtils.writeStringToFile(file1, content1, US_ASCII); FileUtils.writeStringToFile(file2, content2, US_ASCII); // File checksums are different assertNotEquals(FileUtils.checksumCRC32(file1), FileUtils.checksumCRC32(file2)); try (FileInputStream stream1 = new FileInputStream(file1); FileInputStream stream2 = new FileInputStream(file2); FileChannel channel1 = stream1.getChannel(); FileChannel channel2 = stream2.getChannel()) { assertFalse(FileChannels.contentEquals(channel1, channel2, BUFFER_SIZE)); } try (FileInputStream stream1 = new FileInputStream(file1); FileInputStream stream2 = new FileInputStream(file2); FileChannel channel1 = stream1.getChannel(); FileChannel channel2 = stream2.getChannel()) { assertTrue(FileChannels.contentEquals(channel1, channel1, BUFFER_SIZE)); assertTrue(FileChannels.contentEquals(channel2, channel2, BUFFER_SIZE)); } } @Test public void testContentEqualsDifferentPostfix() throws IOException { testContentEquals(CONTENT + "ABC", CONTENT + "XYZ"); } @Test public void testContentEqualsDifferentPrefix() throws IOException { testContentEquals("ABC" + CONTENT, "XYZ" + CONTENT); } @Test public void testContentEqualsEmpty() throws IOException { assertTrue(FileChannels.contentEquals(null, null, BUFFER_SIZE)); final File empty = new File(tempDirFile, "empty.txt"); final File notEmpty = new File(tempDirFile, "not-empty.txt"); FileUtils.writeStringToFile(empty, StringUtils.EMPTY, US_ASCII); FileUtils.writeStringToFile(notEmpty, "X", US_ASCII); assertTrue(isEmpty(empty)); assertFalse(isEmpty(notEmpty)); // File checksums are different assertNotEquals(FileUtils.checksumCRC32(empty), FileUtils.checksumCRC32(notEmpty)); try (FileInputStream streamEmpty = new FileInputStream(empty); FileInputStream streamNotEmpty = new FileInputStream(notEmpty); FileChannel channelEmpty = streamEmpty.getChannel(); FileChannel channelNotEmpty = streamNotEmpty.getChannel()) { assertFalse(FileChannels.contentEquals(channelEmpty, channelNotEmpty, BUFFER_SIZE)); assertFalse(FileChannels.contentEquals(null, channelNotEmpty, BUFFER_SIZE)); assertFalse(FileChannels.contentEquals(channelNotEmpty, null, BUFFER_SIZE)); assertTrue(FileChannels.contentEquals(channelEmpty, channelEmpty, BUFFER_SIZE)); assertTrue(FileChannels.contentEquals(null, channelEmpty, BUFFER_SIZE)); assertTrue(FileChannels.contentEquals(channelEmpty, null, BUFFER_SIZE)); assertTrue(FileChannels.contentEquals(channelNotEmpty, channelNotEmpty, BUFFER_SIZE)); } } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/charset/CharsetDecodersTest.java0100644 0000000 0000000 00000004025 14603604450 031767 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.charset; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.nio.charset.StandardCharsets; import org.junit.jupiter.api.Test; /** * Tests {@link CharsetDecoders}. */ public class CharsetDecodersTest { @Test public void testToCharsetDecoders_default() { final CharsetDecoder charsetEncoder = CharsetDecoders.toCharsetDecoder(Charset.defaultCharset().newDecoder()); assertNotNull(charsetEncoder); assertEquals(Charset.defaultCharset(), charsetEncoder.charset()); } @Test public void testToCharsetDecoders_ISO_8859_1() { final CharsetDecoder charsetEncoder = CharsetDecoders.toCharsetDecoder(StandardCharsets.ISO_8859_1.newDecoder()); assertNotNull(charsetEncoder); assertEquals(StandardCharsets.ISO_8859_1, charsetEncoder.charset()); } @Test public void testToCharsetDecoders_null() { final CharsetDecoder charsetEncoder = CharsetDecoders.toCharsetDecoder(null); assertNotNull(charsetEncoder); assertEquals(Charset.defaultCharset(), charsetEncoder.charset()); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/charset/CharsetEncodersTest.java0100644 0000000 0000000 00000004025 14603604450 032001 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.charset; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; import java.nio.charset.StandardCharsets; import org.junit.jupiter.api.Test; /** * Tests {@link CharsetEncoders}. */ public class CharsetEncodersTest { @Test public void testToCharsetEncoders_default() { final CharsetEncoder charsetEncoder = CharsetEncoders.toCharsetEncoder(Charset.defaultCharset().newEncoder()); assertNotNull(charsetEncoder); assertEquals(Charset.defaultCharset(), charsetEncoder.charset()); } @Test public void testToCharsetEncoders_ISO_8859_1() { final CharsetEncoder charsetEncoder = CharsetEncoders.toCharsetEncoder(StandardCharsets.ISO_8859_1.newEncoder()); assertNotNull(charsetEncoder); assertEquals(StandardCharsets.ISO_8859_1, charsetEncoder.charset()); } @Test public void testToCharsetEncoders_null() { final CharsetEncoder charsetEncoder = CharsetEncoders.toCharsetEncoder(null); assertNotNull(charsetEncoder); assertEquals(Charset.defaultCharset(), charsetEncoder.charset()); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/comparator/ComparatorAbstractTest.java0100644 0000000 0000000 00000007720 14603604450 033243 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 ComparatorAbstractTest { @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 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 comparator array sort is null safe. */ @Test public void testSortArrayNull() { assertNull(comparator.sort((File[]) null)); } /** * 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 14603604450 011636 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/comparator/CompositeFileComparatorTest.javacommons-io-2.16.1-src/src/test/java/org/apache/commons/io/comparator/CompositeFileComparatorTest.jav0100644 0000000 0000000 00000011355 14603604450 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.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; /** * Tests {@link CompositeFileComparator}. */ public class CompositeFileComparatorTest extends ComparatorAbstractTest { @BeforeEach public void setUp() throws Exception { comparator = new CompositeFileComparator(SizeFileComparator.SIZE_COMPARATOR, 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 (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 (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 (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 (BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(moreFile.toPath()))) { TestUtils.generateTestData(output, 48); } } /** * Test Constructor with null array */ @Test public void testConstructorArray_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"); } /** * Test Constructor with null Iterable */ @Test public void testConstructorIterable_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 Iterable */ @Test public void testConstructorIterable_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"); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/comparator/DefaultFileComparatorTest.java0100644 0000000 0000000 00000002542 14603604450 033661 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; /** * Tests {@link DefaultFileComparator}. */ public class DefaultFileComparatorTest extends ComparatorAbstractTest { @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 14603604450 011636 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/comparator/DirectoryFileComparatorTest.javacommons-io-2.16.1-src/src/test/java/org/apache/commons/io/comparator/DirectoryFileComparatorTest.jav0100644 0000000 0000000 00000003506 14603604450 034101 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.apache.commons.io.FileUtils; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Tests {@link DirectoryFileComparator}. */ public class DirectoryFileComparatorTest extends ComparatorAbstractTest { @BeforeEach public void setUp() { comparator = (AbstractFileComparator) DirectoryFileComparator.DIRECTORY_COMPARATOR; reverse = DirectoryFileComparator.DIRECTORY_REVERSE; final File currentDir = FileUtils.current(); 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 14603604450 011636 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/comparator/ExtensionFileComparatorTest.javacommons-io-2.16.1-src/src/test/java/org/apache/commons/io/comparator/ExtensionFileComparatorTest.jav0100644 0000000 0000000 00000005073 14603604450 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.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; /** * Tests {@link ExtensionFileComparator}. */ public class ExtensionFileComparatorTest extends ComparatorAbstractTest { @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 14603604450 011632 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/comparator/LastModifiedFileComparatorTest.javacommons-io-2.16.1-src/src/test/java/org/apache/commons/io/comparator/LastModifiedFileComparatorTest.0100644 0000000 0000000 00000006237 14603604450 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; /** * Tests {@link LastModifiedFileComparator}. */ public class LastModifiedFileComparatorTest extends ComparatorAbstractTest { @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 (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 (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 (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.16.1-src/src/test/java/org/apache/commons/io/comparator/NameFileComparatorTest.java0100644 0000000 0000000 00000005044 14603604450 033155 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; /** * Tests {@link NameFileComparator}. */ public class NameFileComparatorTest extends ComparatorAbstractTest { @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.16.1-src/src/test/java/org/apache/commons/io/comparator/PathFileComparatorTest.java0100644 0000000 0000000 00000005047 14603604450 033174 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; /** * Tests {@link PathFileComparator}. */ public class PathFileComparatorTest extends ComparatorAbstractTest { @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.16.1-src/src/test/java/org/apache/commons/io/comparator/SizeFileComparatorTest.java0100644 0000000 0000000 00000010034 14603604450 033202 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.FileUtils; import org.apache.commons.io.test.TestUtils; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Tests {@link SizeFileComparator}. */ public class SizeFileComparatorTest extends ComparatorAbstractTest { 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 (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 (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 (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 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"); } /** * Test a file which doesn't exist. */ @Test public void testNonExistentFile() { final File nonExistentFile = new File(FileUtils.current(), "non-existent.txt"); assertFalse(nonExistentFile.exists()); assertTrue(comparator.compare(nonExistentFile, moreFile) < 0, "less"); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/file/AbstractPathWrapper.java0100644 0000000 0000000 00000013104 14603604450 031272 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.net.URI; import java.nio.file.FileSystem; import java.nio.file.Files; import java.nio.file.LinkOption; import java.nio.file.Path; import java.nio.file.WatchEvent.Kind; import java.nio.file.WatchEvent.Modifier; import java.nio.file.WatchKey; import java.nio.file.WatchService; import java.util.Iterator; import java.util.Objects; import java.util.Spliterator; import java.util.function.Consumer; /** * Wraps and delegates to a Path for subclasses. * * @since 2.12.0 */ public abstract class AbstractPathWrapper implements Path { /** * The path delegate. */ private final Path path; /** * Constructs a new instance. * * @param path The path to wrap. */ protected AbstractPathWrapper(final Path path) { this.path = Objects.requireNonNull(path, "path"); } @Override public int compareTo(final Path other) { return path.compareTo(other); } @Override public boolean endsWith(final Path other) { return path.endsWith(other); } @Override public boolean endsWith(final String other) { return path.endsWith(other); } @Override public boolean equals(final Object obj) { if (this == obj) { return true; } if (!(obj instanceof AbstractPathWrapper)) { return false; } final AbstractPathWrapper other = (AbstractPathWrapper) obj; return Objects.equals(path, other.path); } /** * Delegates to {@link Files#exists(Path, LinkOption...)}. * * @param options See {@link Files#exists(Path, LinkOption...)}. * @return See {@link Files#exists(Path, LinkOption...)}. */ public boolean exists(final LinkOption... options) { return Files.exists(path, options); } @Override public void forEach(final Consumer action) { path.forEach(action); } /** * Gets the delegate Path. * * @return the delegate Path. */ public Path get() { return path; } @Override public Path getFileName() { return path.getFileName(); } @Override public FileSystem getFileSystem() { return path.getFileSystem(); } @Override public Path getName(final int index) { return path.getName(index); } @Override public int getNameCount() { return path.getNameCount(); } @Override public Path getParent() { return path.getParent(); } @Override public Path getRoot() { return path.getRoot(); } @Override public int hashCode() { return Objects.hash(path); } @Override public boolean isAbsolute() { return path.isAbsolute(); } @Override public Iterator iterator() { return path.iterator(); } @Override public Path normalize() { return path.normalize(); } @Override public WatchKey register(final WatchService watcher, final Kind... events) throws IOException { return path.register(watcher, events); } @Override public WatchKey register(final WatchService watcher, final Kind[] events, final Modifier... modifiers) throws IOException { return path.register(watcher, events, modifiers); } @Override public Path relativize(final Path other) { return path.relativize(other); } @Override public Path resolve(final Path other) { return path.resolve(other); } @Override public Path resolve(final String other) { return path.resolve(other); } @Override public Path resolveSibling(final Path other) { return path.resolveSibling(other); } @Override public Path resolveSibling(final String other) { return path.resolveSibling(other); } @Override public Spliterator spliterator() { return path.spliterator(); } @Override public boolean startsWith(final Path other) { return path.startsWith(other); } @Override public boolean startsWith(final String other) { return path.startsWith(other); } @Override public Path subpath(final int beginIndex, final int endIndex) { return path.subpath(beginIndex, endIndex); } @Override public Path toAbsolutePath() { return path.toAbsolutePath(); } @Override public File toFile() { return path.toFile(); } @Override public Path toRealPath(final LinkOption... options) throws IOException { return path.toRealPath(options); } @Override public String toString() { return path.toString(); } @Override public URI toUri() { return path.toUri(); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/file/AbstractTempDirTest.java0100644 0000000 0000000 00000005447 14603604450 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.File; import java.io.IOException; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.io.TempDir; /** * Provides services for test subclasses. */ public abstract class AbstractTempDirTest { protected static final String SUB_DIR = "subdir"; protected static final String SYMLINKED_DIR = "symlinked-dir"; /** * Creates directory test fixtures in the given directory {@code rootDir}. *
    *
  1. {@code rootDir/subdir}
  2. *
  3. {@code rootDir/symlinked-dir} -> {@code rootDir/subdir}
  4. *
* @param rootDir Root for directory entries. * @return Path for {@code tempDirPath/subdir}. * @throws IOException if an I/O error occurs or the parent directory does not exist. */ protected static Path createTempSymlinkedRelativeDir(final Path rootDir) throws IOException { final Path targetDir = rootDir.resolve(SUB_DIR); final Path symlinkDir = rootDir.resolve(SYMLINKED_DIR); Files.createDirectory(targetDir); return Files.createSymbolicLink(symlinkDir, targetDir); } /** * A temporary directory managed by JUnit. */ @TempDir public Path managedTempDirPath; /** * A File version of this test's Path object. */ public File tempDirFile; /** * A temporary directory managed by each test so we can optionally fiddle with its permissions independently. */ public Path tempDirPath; @BeforeEach public void beforeEachCreateTempDirs() throws IOException { tempDirPath = Files.createTempDirectory(managedTempDirPath, getClass().getSimpleName()); tempDirFile = tempDirPath.toFile(); } @SuppressWarnings("resource") // no FileSystem allocation protected final boolean isPosixFilePermissionsSupported() { return FileSystems.getDefault().supportedFileAttributeViews().contains("posix"); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/file/AccumulatorPathVisitorTest.java0100644 0000000 0000000 00000031125 14603604450 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.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.attribute.BasicFileAttributes; import java.time.Duration; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; 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.atomic.AtomicInteger; import java.util.function.Supplier; import java.util.stream.Stream; import org.apache.commons.io.ThreadUtils; 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.apache.commons.io.filefilter.TrueFileFilter; import org.junit.jupiter.api.Test; 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), Arguments.of((Supplier) () -> AccumulatorPathVisitor.withBigIntegerCounters(TrueFileFilter.INSTANCE, TrueFileFilter.INSTANCE))); // @formatter:on } static Stream testParametersIgnoreFailures() { // @formatter:off return Stream.of( Arguments.of((Supplier) () -> new AccumulatorPathVisitor( Counters.bigIntegerPathCounters(), CountingPathVisitor.defaultDirFilter(), CountingPathVisitor.defaultFileFilter()))); // @formatter:on } @TempDir Path tempDirPath; /** * Tests the 0-argument constructor. */ @Test public void test0ArgConstructor() throws IOException { final AccumulatorPathVisitor accPathVisitor = new AccumulatorPathVisitor(); final PathVisitorFileFilter countingFileFilter = new PathVisitorFileFilter(accPathVisitor); Files.walkFileTree(tempDirPath, new AndFileFilter(countingFileFilter, DirectoryFileFilter.INSTANCE, EmptyFileFilter.EMPTY)); assertCounts(0, 0, 0, accPathVisitor.getPathCounters()); assertEquals(1, accPathVisitor.getDirList().size()); assertTrue(accPathVisitor.getFileList().isEmpty()); assertEquals(accPathVisitor, accPathVisitor); assertEquals(accPathVisitor.hashCode(), accPathVisitor.hashCode()); } /** * Tests an empty folder. */ @ParameterizedTest @MethodSource("testParameters") public void testEmptyFolder(final Supplier supplier) throws IOException { final AccumulatorPathVisitor accPathVisitor = supplier.get(); final PathVisitorFileFilter countingFileFilter = new PathVisitorFileFilter(accPathVisitor); Files.walkFileTree(tempDirPath, new AndFileFilter(countingFileFilter, DirectoryFileFilter.INSTANCE, EmptyFileFilter.EMPTY)); assertCounts(1, 0, 0, accPathVisitor.getPathCounters()); assertEquals(1, accPathVisitor.getDirList().size()); assertTrue(accPathVisitor.getFileList().isEmpty()); assertEquals(accPathVisitor, accPathVisitor); assertEquals(accPathVisitor.hashCode(), accPathVisitor.hashCode()); } @Test public void testEqualsHashCode() { final AccumulatorPathVisitor visitor0 = AccumulatorPathVisitor.withLongCounters(); final AccumulatorPathVisitor visitor1 = AccumulatorPathVisitor.withLongCounters(); assertEquals(visitor0, visitor0); assertEquals(visitor0, visitor1); assertEquals(visitor1, visitor0); assertEquals(visitor0.hashCode(), visitor0.hashCode()); assertEquals(visitor0.hashCode(), visitor1.hashCode()); assertEquals(visitor1.hashCode(), visitor0.hashCode()); visitor0.getPathCounters().getByteCounter().increment(); assertEquals(visitor0, visitor0); assertNotEquals(visitor0, visitor1); assertNotEquals(visitor1, visitor0); assertEquals(visitor0.hashCode(), visitor0.hashCode()); assertNotEquals(visitor0.hashCode(), visitor1.hashCode()); assertNotEquals(visitor1.hashCode(), visitor0.hashCode()); } /** * 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()); assertEquals(accPathVisitor, accPathVisitor); assertEquals(accPathVisitor.hashCode(), accPathVisitor.hashCode()); } /** * 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()); assertEquals(accPathVisitor, accPathVisitor); assertEquals(accPathVisitor.hashCode(), accPathVisitor.hashCode()); } /** * 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()); assertEquals(accPathVisitor, accPathVisitor); assertEquals(accPathVisitor.hashCode(), accPathVisitor.hashCode()); } /** * Tests IO-755 with a directory with 100 files, and delete all of them midway through the visit. * * Random failure like: * *
     * ...?...
     * 
*/ @ParameterizedTest @MethodSource("testParametersIgnoreFailures") public void testFolderWhileDeletingAsync(final Supplier supplier) throws IOException, InterruptedException { final int count = 10_000; final List files = new ArrayList<>(count); // Create "count" file fixtures for (int i = 1; i <= count; i++) { final Path tempFile = Files.createTempFile(tempDirPath, "test", ".txt"); assertTrue(Files.exists(tempFile)); files.add(tempFile); } final AccumulatorPathVisitor accPathVisitor = supplier.get(); final PathVisitorFileFilter countingFileFilter = new PathVisitorFileFilter(accPathVisitor) { @Override public FileVisitResult visitFile(final Path path, final BasicFileAttributes attributes) throws IOException { // Slow down the walking a bit to try and cause conflicts with the deletion thread try { ThreadUtils.sleep(Duration.ofMillis(10)); } catch (final InterruptedException ignore) { // e.printStackTrace(); } return super.visitFile(path, attributes); } }; final ExecutorService executor = Executors.newSingleThreadExecutor(); final AtomicBoolean deleted = new AtomicBoolean(); try { executor.execute(() -> { for (final Path file : files) { try { // File deletion is slow compared to tree walking, so we go as fast as we can here Files.delete(file); } catch (final IOException ignored) { // e.printStackTrace(); } } deleted.set(true); }); Files.walkFileTree(tempDirPath, countingFileFilter); } finally { if (!deleted.get()) { ThreadUtils.sleep(Duration.ofMillis(1000)); } if (!deleted.get()) { executor.awaitTermination(5, TimeUnit.SECONDS); } executor.shutdownNow(); } assertEquals(accPathVisitor, accPathVisitor); assertEquals(accPathVisitor.hashCode(), accPathVisitor.hashCode()); } /** * Tests IO-755 with a directory with 100 files, and delete all of them midway through the visit. */ @ParameterizedTest @MethodSource("testParametersIgnoreFailures") public void testFolderWhileDeletingSync(final Supplier supplier) throws IOException { final int count = 100; final int marker = count / 2; final Set files = new LinkedHashSet<>(count); for (int i = 1; i <= count; i++) { final Path tempFile = Files.createTempFile(tempDirPath, "test", ".txt"); assertTrue(Files.exists(tempFile)); files.add(tempFile); } final AccumulatorPathVisitor accPathVisitor = supplier.get(); final AtomicInteger visitCount = new AtomicInteger(); final PathVisitorFileFilter countingFileFilter = new PathVisitorFileFilter(accPathVisitor) { @Override public FileVisitResult visitFile(final Path path, final BasicFileAttributes attributes) throws IOException { if (visitCount.incrementAndGet() == marker) { // Now that we've visited half the files, delete them all for (final Path file : files) { Files.delete(file); } } return super.visitFile(path, attributes); } }; Files.walkFileTree(tempDirPath, countingFileFilter); assertCounts(1, marker - 1, 0, accPathVisitor.getPathCounters()); assertEquals(1, accPathVisitor.getDirList().size()); assertEquals(marker - 1, accPathVisitor.getFileList().size()); assertEquals(accPathVisitor, accPathVisitor); assertEquals(accPathVisitor.hashCode(), accPathVisitor.hashCode()); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/file/CleaningPathVisitorTest.java0100644 0000000 0000000 00000015707 14603604450 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.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.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertSame; 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.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; /** * Tests {@link DeletingPathVisitor}. */ public class CleaningPathVisitorTest extends TestArguments { @TempDir private Path tempDir; private void applyCleanEmptyDirectory(final CleaningPathVisitor visitor) throws IOException { Files.walkFileTree(tempDir, visitor); assertCounts(1, 0, 0, visitor); } /** * 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); final CleaningPathVisitor visitFileTree = PathUtils.visitFileTree(visitor, tempDir); assertCounts(1, 1, 0, visitFileTree); assertSame(visitor, visitFileTree); // assertNotEquals(visitFileTree, CleaningPathVisitor.withLongCounters()); assertNotEquals(visitFileTree.hashCode(), CleaningPathVisitor.withLongCounters().hashCode()); assertEquals(visitFileTree, visitFileTree); assertEquals(visitFileTree.hashCode(), visitFileTree.hashCode()); } /** * 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); final CleaningPathVisitor visitFileTree = PathUtils.visitFileTree(visitor, tempDir); assertCounts(1, 1, 1, visitFileTree); assertSame(visitor, visitFileTree); // assertNotEquals(visitFileTree, CleaningPathVisitor.withLongCounters()); assertNotEquals(visitFileTree.hashCode(), CleaningPathVisitor.withLongCounters().hashCode()); assertEquals(visitFileTree, visitFileTree); assertEquals(visitFileTree.hashCode(), visitFileTree.hashCode()); } /** * 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); final CountingPathVisitor visitFileTree = PathUtils.visitFileTree(visitor, tempDir); assertCounts(1, 1, 1, visitFileTree); assertSame(visitor, visitFileTree); final Path skippedFile = tempDir.resolve(skipFileName); Assertions.assertTrue(Files.exists(skippedFile)); Files.delete(skippedFile); // assertNotEquals(visitFileTree, CleaningPathVisitor.withLongCounters()); assertNotEquals(visitFileTree.hashCode(), CleaningPathVisitor.withLongCounters().hashCode()); assertEquals(visitFileTree, visitFileTree); assertEquals(visitFileTree.hashCode(), visitFileTree.hashCode()); } /** * 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); final CleaningPathVisitor visitFileTree = PathUtils.visitFileTree(visitor, tempDir); assertCounts(3, 2, 2, visitFileTree); assertSame(visitor, visitFileTree); // assertNotEquals(visitFileTree, CleaningPathVisitor.withLongCounters()); assertNotEquals(visitFileTree.hashCode(), CleaningPathVisitor.withLongCounters().hashCode()); assertEquals(visitFileTree, visitFileTree); assertEquals(visitFileTree.hashCode(), visitFileTree.hashCode()); } @Test public void testEqualsHashCode() { final CountingPathVisitor visitor0 = CleaningPathVisitor.withLongCounters(); final CountingPathVisitor visitor1 = CleaningPathVisitor.withLongCounters(); assertEquals(visitor0, visitor0); assertEquals(visitor0, visitor1); assertEquals(visitor1, visitor0); assertEquals(visitor0.hashCode(), visitor0.hashCode()); assertEquals(visitor0.hashCode(), visitor1.hashCode()); assertEquals(visitor1.hashCode(), visitor0.hashCode()); visitor0.getPathCounters().getByteCounter().increment(); assertEquals(visitor0, visitor0); assertNotEquals(visitor0, visitor1); assertNotEquals(visitor1, visitor0); assertEquals(visitor0.hashCode(), visitor0.hashCode()); assertNotEquals(visitor0.hashCode(), visitor1.hashCode()); assertNotEquals(visitor1.hashCode(), visitor0.hashCode()); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/file/CopyDirectoryVisitorTest.java0100644 0000000 0000000 00000016071 14603604450 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.file; import static org.apache.commons.io.file.CounterAssertions.assertCounts; 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 java.io.IOException; import java.nio.file.CopyOption; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.util.function.Supplier; import org.apache.commons.io.file.Counters.PathCounters; import org.apache.commons.io.filefilter.TrueFileFilter; import org.junit.jupiter.api.io.TempDir; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; /** * Tests {@link CountingPathVisitor}. */ public class CopyDirectoryVisitorTest extends TestArguments { private static final CopyOption[] EXPECTED_COPY_OPTIONS = {StandardCopyOption.REPLACE_EXISTING}; @TempDir private Path targetDir; /** * Tests an empty folder. */ @ParameterizedTest @MethodSource("pathCounters") public void testCopyDirectoryEmptyFolder(final PathCounters pathCounters) throws IOException { try (TempDirectory sourceDir = TempDirectory.create(getClass().getSimpleName())) { final Supplier supplier = () -> new CopyDirectoryVisitor(pathCounters, sourceDir, targetDir, EXPECTED_COPY_OPTIONS); final CopyDirectoryVisitor visitFileTree = PathUtils.visitFileTree(supplier.get(), sourceDir.get()); assertCounts(1, 0, 0, visitFileTree); assertArrayEquals(EXPECTED_COPY_OPTIONS, visitFileTree.getCopyOptions()); assertEquals(sourceDir.get(), ((AbstractPathWrapper) visitFileTree.getSourceDirectory()).get()); assertEquals(sourceDir, visitFileTree.getSourceDirectory()); assertEquals(targetDir, visitFileTree.getTargetDirectory()); assertEquals(targetDir, visitFileTree.getTargetDirectory()); // assertEquals(visitFileTree, supplier.get()); assertEquals(visitFileTree.hashCode(), supplier.get().hashCode()); assertEquals(visitFileTree, visitFileTree); assertEquals(visitFileTree.hashCode(), visitFileTree.hashCode()); assertNotEquals(visitFileTree, "not"); assertNotEquals(visitFileTree, CountingPathVisitor.withLongCounters()); } } /** * Tests an empty folder. */ @ParameterizedTest @MethodSource("pathCounters") public void testCopyDirectoryEmptyFolderFilters(final PathCounters pathCounters) throws IOException { try (TempDirectory sourceDir = TempDirectory.create(getClass().getSimpleName())) { final Supplier supplier = () -> new CopyDirectoryVisitor(pathCounters, TrueFileFilter.INSTANCE, TrueFileFilter.INSTANCE, sourceDir, targetDir, EXPECTED_COPY_OPTIONS); final CopyDirectoryVisitor visitFileTree = PathUtils.visitFileTree(supplier.get(), sourceDir.get()); assertCounts(1, 0, 0, visitFileTree); assertArrayEquals(EXPECTED_COPY_OPTIONS, visitFileTree.getCopyOptions()); assertEquals(sourceDir, visitFileTree.getSourceDirectory()); assertEquals(targetDir, visitFileTree.getTargetDirectory()); // assertEquals(visitFileTree, supplier.get()); assertEquals(visitFileTree.hashCode(), supplier.get().hashCode()); assertEquals(visitFileTree, visitFileTree); assertEquals(visitFileTree.hashCode(), visitFileTree.hashCode()); } } /** * 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"); final Supplier supplier = () -> new CopyDirectoryVisitor(pathCounters, sourceDir, targetDir, EXPECTED_COPY_OPTIONS); final CopyDirectoryVisitor visitFileTree = PathUtils.visitFileTree(supplier.get(), sourceDir); assertCounts(1, 1, 0, visitFileTree); assertArrayEquals(EXPECTED_COPY_OPTIONS, visitFileTree.getCopyOptions()); assertEquals(sourceDir, visitFileTree.getSourceDirectory()); assertEquals(targetDir, visitFileTree.getTargetDirectory()); // assertEquals(visitFileTree, supplier.get()); assertEquals(visitFileTree.hashCode(), supplier.get().hashCode()); assertEquals(visitFileTree, visitFileTree); assertEquals(visitFileTree.hashCode(), visitFileTree.hashCode()); } /** * 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"); final CopyDirectoryVisitor visitFileTree = PathUtils.visitFileTree(new CopyDirectoryVisitor(pathCounters, sourceDir, targetDir, EXPECTED_COPY_OPTIONS), sourceDir); assertCounts(1, 1, 1, visitFileTree); assertArrayEquals(EXPECTED_COPY_OPTIONS, visitFileTree.getCopyOptions()); assertEquals(sourceDir, visitFileTree.getSourceDirectory()); assertEquals(targetDir, visitFileTree.getTargetDirectory()); } /** * 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"); final CopyDirectoryVisitor visitFileTree = PathUtils.visitFileTree(new CopyDirectoryVisitor(pathCounters, sourceDir, targetDir, EXPECTED_COPY_OPTIONS), sourceDir); assertCounts(3, 2, 2, visitFileTree); assertArrayEquals(EXPECTED_COPY_OPTIONS, visitFileTree.getCopyOptions()); assertEquals(sourceDir, visitFileTree.getSourceDirectory()); assertEquals(targetDir, visitFileTree.getTargetDirectory()); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/file/CounterAssertions.java0100644 0000000 0000000 00000004457 14603604450 031056 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.16.1-src/src/test/java/org/apache/commons/io/file/CountersEqualsAndHashCodeTest.java0100644 0000000 0000000 00000011407 14603604450 033214 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 testLongCounterHashCodes() { testHashCodes(Counters.longCounter(), Counters.longCounter()); } @Test public void testLongCounterMixEquals() { testEquals(Counters.longCounter(), Counters.bigIntegerCounter()); testEquals(Counters.bigIntegerCounter(), 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.16.1-src/src/test/java/org/apache/commons/io/file/CountersTest.java0100644 0000000 0000000 00000005512 14603604450 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; /** * Tests {@link Counter} and implementations. */ 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.16.1-src/src/test/java/org/apache/commons/io/file/CountingPathVisitorTest.java0100644 0000000 0000000 00000006440 14603604450 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 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 { private void checkZeroCounts(final CountingPathVisitor visitor) { Assertions.assertEquals(CountingPathVisitor.withLongCounters(), visitor); Assertions.assertEquals(CountingPathVisitor.withBigIntegerCounters(), visitor); } /** * Tests an empty folder. */ @ParameterizedTest @MethodSource("countingPathVisitors") public void testCountEmptyFolder(final CountingPathVisitor visitor) throws IOException { checkZeroCounts(visitor); try (TempDirectory tempDir = TempDirectory.create(getClass().getCanonicalName())) { assertCounts(1, 0, 0, PathUtils.visitFileTree(visitor, tempDir.get())); } } /** * 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")); } @ParameterizedTest @MethodSource("countingPathVisitors") void testToString(final CountingPathVisitor visitor) { // Make sure it does not blow up visitor.toString(); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/file/DeletablePath.java0100644 0000000 0000000 00000004160 14603604450 030051 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.Closeable; import java.io.IOException; import java.nio.file.Path; import org.apache.commons.io.file.Counters.PathCounters; /** * A Path that deletes its delegate on close. * * @since 2.12.0 */ public class DeletablePath extends AbstractPathWrapper implements Closeable { /** * Constructs a new instance wrapping the given delegate. * * @param path The delegate. */ public DeletablePath(final Path path) { super(path); } @Override public void close() throws IOException { delete(); } /** * Deletes the delegate path. * * @return The visitor used to delete the given directory. * @throws IOException if an I/O error is thrown by a visitor method or if an I/O error occurs. */ public PathCounters delete() throws IOException { return delete((DeleteOption[]) null); } /** * Deletes the delegate path. * @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 or if an I/O error occurs. */ public PathCounters delete(final DeleteOption... deleteOptions) throws IOException { return PathUtils.delete(get(), deleteOptions); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/file/DeletingPathVisitorTest.java0100644 0000000 0000000 00000017322 14603604450 032147 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; 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.file.Counters.PathCounters; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; /** * Tests {@link DeletingPathVisitor}. */ public class DeletingPathVisitorTest extends AbstractTempDirTest { private static final String ARGS = "org.apache.commons.io.file.TestArguments#"; private void applyDeleteEmptyDirectory(final DeletingPathVisitor visitor) throws IOException { Files.walkFileTree(tempDirPath, visitor); assertCounts(1, 0, 0, visitor); } /** * Tests an empty folder. */ @ParameterizedTest @MethodSource(ARGS + "deletingPathVisitors") public void testDeleteEmptyDirectory(final DeletingPathVisitor visitor) throws IOException { applyDeleteEmptyDirectory(visitor); // This will throw if not empty. Files.deleteIfExists(tempDirPath); } /** * Tests an empty folder. */ @ParameterizedTest @MethodSource(ARGS + "pathCounters") public void testDeleteEmptyDirectoryNullCtorArg(final PathCounters pathCounters) throws IOException { applyDeleteEmptyDirectory(new DeletingPathVisitor(pathCounters, (String[]) null)); // This will throw if not empty. Files.deleteIfExists(tempDirPath); } /** * Tests a directory with one file of size 0. */ @ParameterizedTest @MethodSource(ARGS + "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"), tempDirPath); assertCounts(1, 1, 0, PathUtils.visitFileTree(visitor, tempDirPath)); // This will throw if not empty. Files.deleteIfExists(tempDirPath); } /** * Tests a directory with one file of size 1. */ @ParameterizedTest @MethodSource(ARGS + "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"), tempDirPath); assertCounts(1, 1, 1, PathUtils.visitFileTree(visitor, tempDirPath)); // This will throw if not empty. Files.deleteIfExists(tempDirPath); } /** * Tests a directory with one file of size 1 but skip that file. */ @ParameterizedTest @MethodSource(ARGS + "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"), tempDirPath); final String skipFileName = "file-size-1.bin"; final CountingPathVisitor visitor = new DeletingPathVisitor(pathCounters, skipFileName); assertCounts(1, 1, 1, PathUtils.visitFileTree(visitor, tempDirPath)); final Path skippedFile = tempDirPath.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(ARGS + "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"), tempDirPath); assertCounts(3, 2, 2, PathUtils.visitFileTree(visitor, tempDirPath)); // This will throw if not empty. Files.deleteIfExists(tempDirPath); } @Test public void testEqualsHashCode() { final DeletingPathVisitor visitor0 = DeletingPathVisitor.withLongCounters(); final DeletingPathVisitor visitor1 = DeletingPathVisitor.withLongCounters(); assertEquals(visitor0, visitor0); assertEquals(visitor0, visitor1); assertEquals(visitor1, visitor0); assertEquals(visitor0.hashCode(), visitor0.hashCode()); assertEquals(visitor0.hashCode(), visitor1.hashCode()); assertEquals(visitor1.hashCode(), visitor0.hashCode()); visitor0.getPathCounters().getByteCounter().increment(); assertEquals(visitor0, visitor0); assertNotEquals(visitor0, visitor1); assertNotEquals(visitor1, visitor0); assertEquals(visitor0.hashCode(), visitor0.hashCode()); assertNotEquals(visitor0.hashCode(), visitor1.hashCode()); assertNotEquals(visitor1.hashCode(), visitor0.hashCode()); } /** * Tests https://issues.apache.org/jira/browse/IO-850 */ @Test public void testIO850DirectoriesAndFiles() throws IOException { final Path rootDir = Files.createDirectory(managedTempDirPath.resolve("IO850")); createTempSymlinkedRelativeDir(rootDir); final Path targetDir = rootDir.resolve(SUB_DIR); final Path symlinkDir = rootDir.resolve(SYMLINKED_DIR); Files.write(targetDir.resolve("file0.txt"), "Hello".getBytes(StandardCharsets.UTF_8)); final Path subDir0 = Files.createDirectory(targetDir.resolve("subDir0")); Files.write(subDir0.resolve("file1.txt"), "Hello".getBytes(StandardCharsets.UTF_8)); final DeletingPathVisitor visitor = DeletingPathVisitor.withLongCounters(); Files.walkFileTree(rootDir, visitor); assertFalse(Files.exists(targetDir)); assertFalse(Files.exists(symlinkDir)); assertFalse(Files.exists(rootDir)); assertTrue(visitor.getPathCounters().getDirectoryCounter().get() > 0); assertTrue(visitor.getPathCounters().getFileCounter().get() > 0); } /** * Tests https://issues.apache.org/jira/browse/IO-850 */ @Test public void testIO850DirectoriesOnly() throws IOException { final Path rootDir = Files.createDirectory(managedTempDirPath.resolve("IO850")); createTempSymlinkedRelativeDir(rootDir); final Path targetDir = rootDir.resolve(SUB_DIR); final Path symlinkDir = rootDir.resolve(SYMLINKED_DIR); final DeletingPathVisitor visitor = DeletingPathVisitor.withLongCounters(); Files.walkFileTree(rootDir, visitor); assertFalse(Files.exists(targetDir)); assertFalse(Files.exists(symlinkDir)); assertFalse(Files.exists(rootDir)); assertTrue(visitor.getPathCounters().getDirectoryCounter().get() > 0); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/file/DirectoryStreamFilterTest.java0100644 0000000 0000000 00000005006 14603604450 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.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 (DirectoryStream stream = Files.newDirectoryStream(PathUtils.current(), streamFilter)) { final Iterator iterator = stream.iterator(); final Path path = iterator.next(); assertEquals(PATH_FIXTURE, PathUtils.getFileNameString(path)); 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 (DirectoryStream stream = Files.newDirectoryStream(PathUtils.current(), streamFilter)) { stream.forEach(path -> assertNotEquals(PATH_FIXTURE, PathUtils.getFileNameString(path))); } } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/file/FilesUncheckTest.java0100644 0000000 0000000 00000042460 14603604450 030563 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.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.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assumptions.assumeTrue; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.UncheckedIOException; import java.nio.channels.SeekableByteChannel; import java.nio.charset.StandardCharsets; import java.nio.file.DirectoryStream; import java.nio.file.FileVisitOption; import java.nio.file.Files; import java.nio.file.LinkOption; import java.nio.file.OpenOption; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.nio.file.StandardOpenOption; import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.FileAttribute; import java.nio.file.attribute.FileTime; import java.nio.file.attribute.PosixFilePermission; import java.nio.file.attribute.UserPrincipal; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Set; import java.util.stream.Stream; import org.apache.commons.io.IOUtils; import org.apache.commons.io.function.Uncheck; import org.apache.commons.io.input.NullInputStream; import org.apache.commons.io.output.NullOutputStream; import org.apache.commons.lang3.ArrayUtils; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Tests {@link FilesUncheck}. * * These tests are simple and just makes sure we do can make the call without catching IOException. */ public class FilesUncheckTest { private static final FileAttribute[] EMPTY_FILE_ATTRIBUTES_ARRAY = {}; private static final Path FILE_PATH_A = Paths.get("src/test/resources/org/apache/commons/io/dirs-1-file-size-1/file-size-1.bin"); private static final Path FILE_PATH_EMPTY = Paths.get("src/test/resources/org/apache/commons/io/test-file-empty.bin"); private static final Path NEW_DIR_PATH = Paths.get("target/newdir"); private static final Path NEW_FILE_PATH = Paths.get("target/file.txt"); private static final Path NEW_FILE_PATH_LINK = Paths.get("target/to_another_file.txt"); private static final String PREFIX = "prefix"; private static final String SUFFIX = "suffix"; private static final Path TARGET_PATH = Paths.get("target"); @BeforeEach @AfterEach public void deleteFixtures() throws IOException { Files.deleteIfExists(NEW_FILE_PATH); Files.deleteIfExists(NEW_DIR_PATH); Files.deleteIfExists(NEW_FILE_PATH_LINK); } @Test public void testCopyInputStreamPathCopyOptionArray() { assertEquals(0, FilesUncheck.copy(NullInputStream.INSTANCE, NEW_FILE_PATH, PathUtils.EMPTY_COPY_OPTIONS)); } @Test public void testCopyPathOutputStream() { assertEquals(0, FilesUncheck.copy(FILE_PATH_EMPTY, NullOutputStream.INSTANCE)); } @Test public void testCopyPathPathCopyOptionArray() { assertEquals(NEW_FILE_PATH, FilesUncheck.copy(FILE_PATH_EMPTY, NEW_FILE_PATH, PathUtils.EMPTY_COPY_OPTIONS)); } @Test public void testCreateDirectories() { assertEquals(TARGET_PATH, FilesUncheck.createDirectories(TARGET_PATH, EMPTY_FILE_ATTRIBUTES_ARRAY)); } @Test public void testCreateDirectory() { assertEquals(NEW_DIR_PATH, FilesUncheck.createDirectory(NEW_DIR_PATH, EMPTY_FILE_ATTRIBUTES_ARRAY)); } @Test public void testCreateFile() { assertEquals(NEW_FILE_PATH, FilesUncheck.createFile(NEW_FILE_PATH, EMPTY_FILE_ATTRIBUTES_ARRAY)); } @Test public void testCreateLink() { assertEquals(NEW_FILE_PATH_LINK, FilesUncheck.createLink(NEW_FILE_PATH_LINK, FILE_PATH_EMPTY)); } @Test public void testCreateSymbolicLink() { // May cause: Caused by: java.nio.file.FileSystemException: A required privilege is not held by the client. assertEquals(NEW_FILE_PATH_LINK, FilesUncheck.createSymbolicLink(NEW_FILE_PATH_LINK, FILE_PATH_EMPTY)); } @Test public void testCreateTempDirectoryPathStringFileAttributeOfQArray() { assertEquals(TARGET_PATH, FilesUncheck.createTempDirectory(TARGET_PATH, PREFIX, EMPTY_FILE_ATTRIBUTES_ARRAY).getParent()); } @Test public void testCreateTempDirectoryStringFileAttributeOfQArray() { assertEquals(PathUtils.getTempDirectory(), FilesUncheck.createTempDirectory(PREFIX, EMPTY_FILE_ATTRIBUTES_ARRAY).getParent()); } @Test public void testCreateTempFilePathStringStringFileAttributeOfQArray() { assertEquals(TARGET_PATH, FilesUncheck.createTempFile(TARGET_PATH, PREFIX, SUFFIX, EMPTY_FILE_ATTRIBUTES_ARRAY).getParent()); } @Test public void testCreateTempFileStringStringFileAttributeOfQArray() { assertEquals(PathUtils.getTempDirectory(), FilesUncheck.createTempFile(PREFIX, SUFFIX, EMPTY_FILE_ATTRIBUTES_ARRAY).getParent()); } @Test public void testDelete() { assertThrows(UncheckedIOException.class, () -> FilesUncheck.delete(NEW_FILE_PATH)); } @Test public void testDeleteIfExists() { assertFalse(FilesUncheck.deleteIfExists(NEW_FILE_PATH)); } @Test public void testFind() { try (Stream find = FilesUncheck.find(FILE_PATH_EMPTY, 0, (t, u) -> false)) { assertNotNull(find); } } @Test public void testGetAttribute() { assertEquals(0L, FilesUncheck.getAttribute(FILE_PATH_EMPTY, "basic:size", LinkOption.NOFOLLOW_LINKS)); } @Test public void testGetFileStore() { assertNotNull(FilesUncheck.getFileStore(FILE_PATH_EMPTY)); } @Test public void testGetLastModifiedTime() { assertTrue(0 < FilesUncheck.getLastModifiedTime(FILE_PATH_EMPTY, LinkOption.NOFOLLOW_LINKS).toMillis()); } @Test public void testGetOwner() { assertNotNull(FilesUncheck.getOwner(FILE_PATH_EMPTY, LinkOption.NOFOLLOW_LINKS)); } @Test public void testGetPosixFilePermissions() { assumeTrue(PathUtils.isPosix(FILE_PATH_EMPTY, LinkOption.NOFOLLOW_LINKS)); assertNotNull(FilesUncheck.getPosixFilePermissions(FILE_PATH_EMPTY, LinkOption.NOFOLLOW_LINKS)); } @Test public void testIsHidden() { assertFalse(FilesUncheck.isHidden(FILE_PATH_EMPTY)); } @Test public void testIsSameFile() { assertTrue(FilesUncheck.isSameFile(FILE_PATH_EMPTY, FILE_PATH_EMPTY)); } @Test public void testLinesPath() { try (Stream stream = FilesUncheck.lines(FILE_PATH_EMPTY)) { assertEquals(0, stream.count()); } } @Test public void testLinesPathCharset() { try (Stream stream = FilesUncheck.lines(FILE_PATH_EMPTY, StandardCharsets.UTF_8)) { assertEquals(0, stream.count()); } } @Test public void testList() { try (Stream stream = FilesUncheck.list(Paths.get("src/test/resources/org/apache/commons/io/dirs-1-file-size-0"))) { assertEquals(1, stream.count()); } } @Test public void testMove() { final Path tempFile1 = FilesUncheck.createTempFile(PREFIX, SUFFIX); final Path tempFile2 = FilesUncheck.createTempFile(PREFIX, SUFFIX); assertEquals(tempFile2, FilesUncheck.move(tempFile1, tempFile2, StandardCopyOption.REPLACE_EXISTING)); FilesUncheck.delete(tempFile2); } @Test public void testNewBufferedReaderPath() { Uncheck.run(() -> { try (BufferedReader reader = FilesUncheck.newBufferedReader(FILE_PATH_EMPTY)) { IOUtils.consume(reader); } }); } @Test public void testNewBufferedReaderPathCharset() { Uncheck.run(() -> { try (BufferedReader reader = FilesUncheck.newBufferedReader(FILE_PATH_EMPTY, StandardCharsets.UTF_8)) { IOUtils.consume(reader); } }); } @Test public void testNewBufferedWriterPathCharsetOpenOptionArray() { final Path tempPath = FilesUncheck.createTempFile(PREFIX, SUFFIX); Uncheck.run(() -> { try (BufferedWriter writer = FilesUncheck.newBufferedWriter(tempPath, StandardCharsets.UTF_8, StandardOpenOption.TRUNCATE_EXISTING)) { writer.append("test"); } }); assertEquals("test", FilesUncheck.readAllLines(tempPath, StandardCharsets.UTF_8).get(0)); } @Test public void testNewBufferedWriterPathOpenOptionArray() { final Path tempPath = FilesUncheck.createTempFile(PREFIX, SUFFIX); Uncheck.run(() -> { try (BufferedWriter writer = FilesUncheck.newBufferedWriter(tempPath, StandardOpenOption.TRUNCATE_EXISTING)) { writer.append("test"); } }); assertEquals("test", FilesUncheck.readAllLines(tempPath).get(0)); } @Test public void testNewByteChannelPathOpenOptionArray() { assertEquals(0, Uncheck.get(() -> { try (SeekableByteChannel c = FilesUncheck.newByteChannel(FILE_PATH_EMPTY, StandardOpenOption.READ)) { return c.size(); } })); } @Test public void testNewByteChannelPathSetOfQextendsOpenOptionFileAttributeOfQArray() { final Set options = new HashSet<>(); options.add(StandardOpenOption.READ); assertEquals(0, Uncheck.get(() -> { try (SeekableByteChannel c = FilesUncheck.newByteChannel(FILE_PATH_EMPTY, options, EMPTY_FILE_ATTRIBUTES_ARRAY)) { return c.size(); } })); } @Test public void testNewDirectoryStreamPath() { Uncheck.run(() -> { try (final DirectoryStream directoryStream = FilesUncheck.newDirectoryStream(TARGET_PATH)) { directoryStream.forEach(e -> assertEquals(TARGET_PATH, e.getParent())); } }); } @Test public void testNewDirectoryStreamPathFilterOfQsuperPath() { Uncheck.run(() -> { try (final DirectoryStream directoryStream = FilesUncheck.newDirectoryStream(TARGET_PATH, e -> true)) { directoryStream.forEach(e -> assertEquals(TARGET_PATH, e.getParent())); } }); } @Test public void testNewDirectoryStreamPathString() { Uncheck.run(() -> { try (final DirectoryStream directoryStream = FilesUncheck.newDirectoryStream(TARGET_PATH, "*.xml")) { directoryStream.forEach(e -> assertEquals(TARGET_PATH, e.getParent())); } }); } @Test public void testNewInputStream() { assertEquals(0, Uncheck.get(() -> { try (InputStream in = FilesUncheck.newInputStream(FILE_PATH_EMPTY, StandardOpenOption.READ)) { return in.available(); } })); } @Test public void testNewOutputStream() { final Path tempPath = FilesUncheck.createTempFile(PREFIX, SUFFIX); Uncheck.run(() -> { try (OutputStream stream = FilesUncheck.newOutputStream(tempPath, StandardOpenOption.TRUNCATE_EXISTING)) { stream.write("test".getBytes()); } }); assertEquals("test", FilesUncheck.readAllLines(tempPath).get(0)); } @Test public void testProbeContentType() { // Empty file: String probeContentType = FilesUncheck.probeContentType(FILE_PATH_EMPTY); // Empirical: probeContentType is null on Windows // Empirical: probeContentType is "text/plain" on Ubuntu // Empirical: probeContentType is ? on macOS // // BOM file: probeContentType = FilesUncheck.probeContentType(Paths.get("src/test/resources/org/apache/commons/io/testfileBOM.xml")); // Empirical: probeContentType is "text/plain" on Windows // Empirical: probeContentType is "application/plain" on Ubuntu // Empirical: probeContentType is ? on macOS } @Test public void testReadAllBytes() { assertArrayEquals(ArrayUtils.EMPTY_BYTE_ARRAY, FilesUncheck.readAllBytes(FILE_PATH_EMPTY)); assertArrayEquals(new byte[] {'a'}, FilesUncheck.readAllBytes(FILE_PATH_A)); } @Test public void testReadAllLinesPath() { assertEquals(Collections.emptyList(), FilesUncheck.readAllLines(FILE_PATH_EMPTY)); assertEquals(Arrays.asList("a"), FilesUncheck.readAllLines(FILE_PATH_A)); } @Test public void testReadAllLinesPathCharset() { assertEquals(Collections.emptyList(), FilesUncheck.readAllLines(FILE_PATH_EMPTY, StandardCharsets.UTF_8)); assertEquals(Arrays.asList("a"), FilesUncheck.readAllLines(FILE_PATH_A, StandardCharsets.UTF_8)); } @Test public void testReadAttributesPathClassOfALinkOptionArray() { assertNotNull(FilesUncheck.readAttributes(FILE_PATH_EMPTY, BasicFileAttributes.class, LinkOption.NOFOLLOW_LINKS)); } @Test public void testReadAttributesPathStringLinkOptionArray() { assertNotNull(FilesUncheck.readAttributes(FILE_PATH_EMPTY, "basic:lastModifiedTime", LinkOption.NOFOLLOW_LINKS)); } @Test public void testReadSymbolicLink() { assertThrows(UncheckedIOException.class, () -> FilesUncheck.readSymbolicLink(NEW_FILE_PATH_LINK)); } @Test public void testSetAttribute() { final FileTime ft = FilesUncheck.getLastModifiedTime(FILE_PATH_EMPTY); assertEquals(FILE_PATH_EMPTY, FilesUncheck.setAttribute(FILE_PATH_EMPTY, "basic:lastModifiedTime", ft, LinkOption.NOFOLLOW_LINKS)); } @Test public void testSetLastModifiedTime() { final FileTime ft = FilesUncheck.getLastModifiedTime(FILE_PATH_EMPTY); assertEquals(FILE_PATH_EMPTY, FilesUncheck.setLastModifiedTime(FILE_PATH_EMPTY, ft)); } @Test public void testSetOwner() { final UserPrincipal owner = FilesUncheck.getOwner(FILE_PATH_EMPTY, LinkOption.NOFOLLOW_LINKS); assertEquals(FILE_PATH_EMPTY, FilesUncheck.setOwner(FILE_PATH_EMPTY, owner)); } @Test public void testSetPosixFilePermissions() { assumeTrue(PathUtils.isPosix(FILE_PATH_EMPTY, LinkOption.NOFOLLOW_LINKS)); final Set posixFilePermissions = FilesUncheck.getPosixFilePermissions(FILE_PATH_EMPTY, LinkOption.NOFOLLOW_LINKS); assertEquals(FILE_PATH_EMPTY, FilesUncheck.setPosixFilePermissions(FILE_PATH_EMPTY, posixFilePermissions)); } @Test public void testSize() { assertEquals(0, FilesUncheck.size(FILE_PATH_EMPTY)); assertEquals(1, FilesUncheck.size(FILE_PATH_A)); } @Test public void testWalkFileTreePathFileVisitorOfQsuperPath() { assertEquals(TARGET_PATH, FilesUncheck.walkFileTree(TARGET_PATH, NoopPathVisitor.INSTANCE)); } @Test public void testWalkFileTreePathSetOfFileVisitOptionIntFileVisitorOfQsuperPath() { assertEquals(TARGET_PATH, FilesUncheck.walkFileTree(TARGET_PATH, new HashSet<>(), 1, NoopPathVisitor.INSTANCE)); } @Test public void testWalkPathFileVisitOptionArray() { try (Stream stream = FilesUncheck.walk(TARGET_PATH, FileVisitOption.FOLLOW_LINKS)) { assertTrue(0 < stream.count()); } } @Test public void testWalkPathIntFileVisitOptionArray() { try (Stream stream = FilesUncheck.walk(TARGET_PATH, 0, FileVisitOption.FOLLOW_LINKS)) { assertEquals(1, stream.count()); } } @Test public void testWritePathByteArrayOpenOptionArray() { final Path tempFile = FilesUncheck.createTempFile(PREFIX, SUFFIX); assertEquals(tempFile, FilesUncheck.write(tempFile, "test".getBytes(), StandardOpenOption.TRUNCATE_EXISTING)); FilesUncheck.delete(tempFile); } @Test public void testWritePathIterableOfQextendsCharSequenceCharsetOpenOptionArray() { final Path tempFile = FilesUncheck.createTempFile(PREFIX, SUFFIX); assertEquals(tempFile, FilesUncheck.write(tempFile, Arrays.asList("test"), StandardCharsets.UTF_8, StandardOpenOption.TRUNCATE_EXISTING)); FilesUncheck.delete(tempFile); } @Test public void testWritePathIterableOfQextendsCharSequenceOpenOptionArray() { final Path tempFile = FilesUncheck.createTempFile(PREFIX, SUFFIX); assertEquals(tempFile, FilesUncheck.write(tempFile, Arrays.asList("test"), StandardOpenOption.TRUNCATE_EXISTING)); FilesUncheck.delete(tempFile); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/file/PathUtilsCleanDirectoryTest.java0100644 0000000 0000000 00000004602 14603604450 032761 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.Path; import java.nio.file.Paths; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; /** * Tests {@link DeletingPathVisitor}. */ public class PathUtilsCleanDirectoryTest { @TempDir private Path tempDir; /** * 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.16.1-src/src/test/java/org/apache/commons/io/file/PathUtilsContentEqualsTest.java0100644 0000000 0000000 00000027432 14603604450 032645 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.File; import java.io.IOException; 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 org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; /** * Tests {@link PathUtils}. */ public class PathUtilsContentEqualsTest { @TempDir public File temporaryFolder; private String getName() { return this.getClass().getSimpleName(); } @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)); } } @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 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 assertThrows(IOException.class, () -> PathUtils.fileContentEquals(temporaryFolder.toPath(), temporaryFolder.toPath())); // Different files final Path objFile1 = Paths.get(temporaryFolder.getAbsolutePath(), getName() + ".object"); PathUtils.copyFile(getClass().getResource("/java/lang/Object.class"), objFile1); final Path objFile1b = Paths.get(temporaryFolder.getAbsolutePath(), getName() + ".object2"); PathUtils.copyFile(getClass().getResource("/java/lang/Object.class"), objFile1b); final Path objFile2 = Paths.get(temporaryFolder.getAbsolutePath(), getName() + ".collection"); 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 testFileContentEqualsZip() throws Exception { final Path path1 = Paths.get("src/test/resources/org/apache/commons/io/bla.zip"); final Path path2 = Paths.get("src/test/resources/org/apache/commons/io/bla-copy.zip"); final Path path3 = Paths.get("src/test/resources/org/apache/commons/io/moby.zip"); assertTrue(PathUtils.fileContentEquals(path1, path2)); assertFalse(PathUtils.fileContentEquals(path1, path3)); } @Test public void testFileContentEqualsZipFileSystem() throws Exception { try (FileSystem fileSystem = FileSystems.newFileSystem(Paths.get("src/test/resources/org/apache/commons/io/test-same-size-diff-contents.zip"), ClassLoader.getSystemClassLoader())) { // Contains one char: A final Path path1 = fileSystem.getPath("/test-same-size-diff-contents/A.txt"); // Contains one char: B final Path path2 = fileSystem.getPath("/test-same-size-diff-contents/B.txt"); assertTrue(Files.exists(path1)); assertTrue(Files.exists(path2)); assertTrue(PathUtils.fileContentEquals(path1, path1)); assertTrue(PathUtils.fileContentEquals(path2, path2)); assertFalse(PathUtils.fileContentEquals(path1, path2)); } } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/file/PathUtilsCountingTest.java0100644 0000000 0000000 00000005617 14603604450 031647 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.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 { try (TempDirectory tempDir = TempDirectory.create(getClass().getCanonicalName())) { final PathCounters pathCounts = PathUtils.countDirectory(tempDir.get()); assertCounts(1, 0, 0, pathCounts); } } /** * 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); } /** * Tests a directory with two subdirectories, each containing one file of size 2. */ @Test public void testCountFolders2FileSize4() throws IOException { final PathCounters pathCounts = PathUtils .countDirectory(Paths.get("src/test/resources/org/apache/commons/io/dirs-2-file-size-4")); assertCounts(3, 4, 8, pathCounts); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/file/PathUtilsDeleteDirectoryTest.java0100644 0000000 0000000 00000010610 14603604450 033135 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 java.io.IOException; import java.nio.file.Files; import java.nio.file.NoSuchFileException; import java.nio.file.Path; import java.nio.file.Paths; import org.junit.jupiter.api.Test; /** * Tests {@link DeletingPathVisitor}. */ public class PathUtilsDeleteDirectoryTest extends AbstractTempDirTest { @Test public void testDeleteAbsentDirectory() throws IOException { final Path absent = tempDirPath.resolve("ThisDirectoryDoesNotExist"); assertFalse(Files.exists(absent)); final Class expectedType = NoSuchFileException.class; assertThrows(expectedType, () -> PathUtils.deleteDirectory(absent)); assertThrows(expectedType, () -> PathUtils.deleteDirectory(absent, StandardDeleteOption.OVERRIDE_READ_ONLY)); assertThrows(expectedType, () -> PathUtils.deleteDirectory(absent, PathUtils.EMPTY_DELETE_OPTION_ARRAY)); // This will throw if not empty. Files.deleteIfExists(tempDirPath); } /** * 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"), tempDirPath); assertCounts(1, 1, 0, PathUtils.deleteDirectory(tempDirPath)); // This will throw if not empty. Files.deleteIfExists(tempDirPath); } /** * 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"), tempDirPath); assertCounts(1, 1, 0, PathUtils.deleteDirectory(tempDirPath, options)); // This will throw if not empty. Files.deleteIfExists(tempDirPath); } @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"), tempDirPath); assertCounts(1, 1, 1, PathUtils.deleteDirectory(tempDirPath)); // This will throw if not empty. Files.deleteIfExists(tempDirPath); } /** * 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"), tempDirPath); assertCounts(3, 2, 2, PathUtils.deleteDirectory(tempDirPath)); // This will throw if not empty. Files.deleteIfExists(tempDirPath); } /** * Tests an empty folder. */ @Test public void testDeleteEmptyDirectory() throws IOException { assertCounts(1, 0, 0, PathUtils.deleteDirectory(tempDirPath)); // This will throw if not empty. Files.deleteIfExists(tempDirPath); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/file/PathUtilsDeleteFileTest.java0100644 0000000 0000000 00000013265 14603604450 032061 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.Assertions; import org.junit.jupiter.api.Test; /** * Tests {@link DeletingPathVisitor}. */ public class PathUtilsDeleteFileTest extends AbstractTempDirTest { @Test public void testDeleteBrokenLink() throws IOException { assumeFalse(SystemUtils.IS_OS_WINDOWS); final Path missingFile = tempDirPath.resolve("missing.txt"); final Path brokenLink = tempDirPath.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"); } /** * 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), tempDirPath); assertCounts(0, 1, 0, PathUtils.deleteFile(tempDirPath.resolve(fileName))); // This will throw if not empty. Files.deleteIfExists(tempDirPath); } /** * 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), tempDirPath); assertCounts(0, 1, 1, PathUtils.deleteFile(tempDirPath.resolve(fileName))); // This will throw if not empty. Files.deleteIfExists(tempDirPath); } /** * Tests a file that does not exist. */ @Test public void testDeleteFileDoesNotExist() throws IOException { testDeleteFileEmpty(PathUtils.deleteFile(tempDirPath.resolve("file-does-not-exist.bin"))); // This will throw if not empty. Files.deleteIfExists(tempDirPath); } 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(tempDirPath))); // This will throw if not empty. Files.deleteIfExists(tempDirPath); } /** * 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), tempDirPath); final Path resolved = tempDirPath.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(tempDirPath); } /** * 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), tempDirPath); final Path resolved = tempDirPath.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(tempDirPath); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/file/PathUtilsDeleteTest.java0100644 0000000 0000000 00000014532 14603604450 031257 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.Paths; import org.apache.commons.io.FileUtils; import org.apache.commons.io.file.Counters.PathCounters; import org.junit.jupiter.api.Test; /** * Tests {@link DeletingPathVisitor}. */ public class PathUtilsDeleteTest extends AbstractTempDirTest { @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(), tempDirPath.toFile()); assertCounts(0, 1, 0, PathUtils.delete(tempDirPath.resolve(fileName))); // This will throw if not empty. Files.deleteIfExists(tempDirPath); } 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(), tempDirPath.toFile()); assertCounts(0, 1, 0, PathUtils.delete(tempDirPath.resolve(fileName), options)); // This will throw if not empty. Files.deleteIfExists(tempDirPath); } /** * 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(), tempDirPath.toFile()); assertCounts(0, 1, 1, PathUtils.delete(tempDirPath.resolve(fileName))); // This will throw if not empty. Files.deleteIfExists(tempDirPath); } 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(), tempDirPath.toFile()); assertCounts(0, 1, 1, PathUtils.delete(tempDirPath.resolve(fileName), options)); // This will throw if not empty. Files.deleteIfExists(tempDirPath); } /** * 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(tempDirPath)); // This will throw if not empty. Files.deleteIfExists(tempDirPath); } /** * Tests an empty folder. */ private void testDeleteEmptyDirectory(final DeleteOption... options) throws IOException { testDeleteEmptyDirectory(PathUtils.delete(tempDirPath, options)); // This will throw if not empty. Files.deleteIfExists(tempDirPath); } 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(tempDirPath.resolve("file-does-not-exist.bin"))); // This will throw if not empty. Files.deleteIfExists(tempDirPath); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/file/PathUtilsIsEmptyTest.java0100644 0000000 0000000 00000004626 14603604450 031452 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.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)); try (TempDirectory tempDir = TempDirectory.create(getClass().getCanonicalName())) { Assertions.assertTrue(PathUtils.isEmpty(tempDir.get())); } Assertions.assertFalse(PathUtils.isEmpty(DIR_SIZE_1)); } @Test public void testIsEmptyDirectory() throws IOException { try (TempDirectory tempDir = TempDirectory.create(getClass().getCanonicalName())) { Assertions.assertTrue(PathUtils.isEmptyDirectory(tempDir.get())); } 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.16.1-src/src/test/java/org/apache/commons/io/file/PathUtilsTest.java0100644 0000000 0000000 00000056732 14603604450 030144 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.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.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assumptions.assumeFalse; import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.nio.charset.StandardCharsets; import java.nio.file.DirectoryStream; import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.LinkOption; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.attribute.DosFileAttributeView; import java.nio.file.attribute.FileTime; import java.nio.file.attribute.PosixFileAttributes; import java.util.GregorianCalendar; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.filefilter.NameFileFilter; import org.apache.commons.io.test.TestUtils; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.SystemUtils; import org.junit.jupiter.api.Test; /** * Tests {@link PathUtils}. */ public class PathUtilsTest extends AbstractTempDirTest { private static final String STRING_FIXTURE = "Hello World"; private static final byte[] BYTE_ARRAY_FIXTURE = STRING_FIXTURE.getBytes(StandardCharsets.UTF_8); 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"; private Path current() { return PathUtils.current(); } private Long getLastModifiedMillis(final Path file) throws IOException { return Files.getLastModifiedTime(file).toMillis(); } private Path getNonExistentPath() { return Paths.get("/does not exist/for/certain"); } private FileSystem openArchive(final Path p, final boolean createNew) throws IOException { 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()); return FileSystems.newFileSystem(uri, env, null); } return FileSystems.newFileSystem(p, (ClassLoader) null); } private void setLastModifiedMillis(final Path file, final long millis) throws IOException { Files.setLastModifiedTime(file, FileTime.fromMillis(millis)); } @Test public void testCopyDirectoryForDifferentFilesystemsWithAbsolutePath() throws IOException { final Path archivePath = Paths.get(TEST_JAR_PATH); try (FileSystem archive = openArchive(archivePath, false)) { // relative jar -> absolute dir Path sourceDir = archive.getPath("dir1"); PathUtils.copyDirectory(sourceDir, tempDirPath); assertTrue(Files.exists(tempDirPath.resolve("f1"))); // absolute jar -> absolute dir sourceDir = archive.getPath("/next"); PathUtils.copyDirectory(sourceDir, tempDirPath); assertTrue(Files.exists(tempDirPath.resolve("dir"))); } } @Test public void testCopyDirectoryForDifferentFilesystemsWithAbsolutePathReverse() throws IOException { try (FileSystem archive = openArchive(tempDirPath.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"))); } } @Test public void testCopyDirectoryForDifferentFilesystemsWithRelativePath() throws IOException { final Path archivePath = Paths.get(TEST_JAR_PATH); try (FileSystem archive = openArchive(archivePath, false); final FileSystem targetArchive = openArchive(tempDirPath.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"))); } } @Test public void testCopyDirectoryForDifferentFilesystemsWithRelativePathReverse() throws IOException { try (FileSystem archive = openArchive(tempDirPath.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"))); } } @Test public void testCopyFile() throws IOException { 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, tempDirPath); assertTrue(Files.exists(targetFile)); assertEquals(Files.size(sourceFile), Files.size(targetFile)); } @Test public void testCopyURL() throws IOException { final Path sourceFile = Paths.get("src/test/resources/org/apache/commons/io/dirs-1-file-size-1/file-size-1.bin"); final URL url = new URL("file:///" + FilenameUtils.getPath(sourceFile.toAbsolutePath().toString()) + sourceFile.getFileName()); final Path targetFile = PathUtils.copyFileToDirectory(url, tempDirPath); assertTrue(Files.exists(targetFile)); assertEquals(Files.size(sourceFile), Files.size(targetFile)); } @Test public void testCreateDirectoriesAlreadyExists() throws IOException { assertEquals(tempDirPath.getParent(), PathUtils.createParentDirectories(tempDirPath)); } @SuppressWarnings("resource") // FileSystems.getDefault() is a singleton @Test public void testCreateDirectoriesForRoots() throws IOException { for (final Path path : FileSystems.getDefault().getRootDirectories()) { final Path parent = path.getParent(); assertNull(parent); assertEquals(parent, PathUtils.createParentDirectories(path)); } } @Test public void testCreateDirectoriesForRootsLinkOptionNull() throws IOException { for (final File f : File.listRoots()) { final Path path = f.toPath(); assertEquals(path.getParent(), PathUtils.createParentDirectories(path, (LinkOption) null)); } } @Test public void testCreateDirectoriesNew() throws IOException { assertEquals(tempDirPath, PathUtils.createParentDirectories(tempDirPath.resolve("child"))); } @Test public void testCreateDirectoriesSymlink() throws IOException { final Path symlinkedDir = createTempSymlinkedRelativeDir(tempDirPath); final String leafDirName = "child"; final Path newDirFollowed = PathUtils.createParentDirectories(symlinkedDir.resolve(leafDirName), PathUtils.NULL_LINK_OPTION); assertEquals(Files.readSymbolicLink(symlinkedDir), newDirFollowed); } @Test public void testCreateDirectoriesSymlinkClashing() throws IOException { final Path symlinkedDir = createTempSymlinkedRelativeDir(tempDirPath); assertEquals(symlinkedDir, PathUtils.createParentDirectories(symlinkedDir.resolve("child"))); } @Test public void testGetBaseNamePathBaseCases() { assertEquals("bar", PathUtils.getBaseName(Paths.get("a/b/c/bar.foo"))); assertEquals("foo", PathUtils.getBaseName(Paths.get("foo"))); assertEquals("", PathUtils.getBaseName(Paths.get(""))); assertEquals("", PathUtils.getBaseName(Paths.get("."))); for (final File f : File.listRoots()) { assertNull(PathUtils.getBaseName(f.toPath())); } if (SystemUtils.IS_OS_WINDOWS) { assertNull(PathUtils.getBaseName(Paths.get("C:\\"))); } } @Test public void testGetBaseNamePathCornerCases() { assertNull(PathUtils.getBaseName((Path) null)); assertEquals("foo", PathUtils.getBaseName(Paths.get("foo."))); assertEquals("", PathUtils.getBaseName(Paths.get("bar/.foo"))); } @Test public void testGetExtension() { assertNull(PathUtils.getExtension(null)); assertEquals("ext", PathUtils.getExtension(Paths.get("file.ext"))); assertEquals("", PathUtils.getExtension(Paths.get("README"))); assertEquals("com", PathUtils.getExtension(Paths.get("domain.dot.com"))); assertEquals("jpeg", PathUtils.getExtension(Paths.get("image.jpeg"))); assertEquals("", PathUtils.getExtension(Paths.get("a.b/c"))); assertEquals("txt", PathUtils.getExtension(Paths.get("a.b/c.txt"))); assertEquals("", PathUtils.getExtension(Paths.get("a/b/c"))); assertEquals("", PathUtils.getExtension(Paths.get("a.b\\c"))); assertEquals("txt", PathUtils.getExtension(Paths.get("a.b\\c.txt"))); assertEquals("", PathUtils.getExtension(Paths.get("a\\b\\c"))); assertEquals("", PathUtils.getExtension(Paths.get("C:\\temp\\foo.bar\\README"))); assertEquals("ext", PathUtils.getExtension(Paths.get("../filename.ext"))); if (File.separatorChar != '\\') { // Upwards compatibility: assertEquals("txt", PathUtils.getExtension(Paths.get("foo.exe:bar.txt"))); } } @Test public void testGetFileName() { assertNull(PathUtils.getFileName(null, null)); assertNull(PathUtils.getFileName(null, Path::toString)); assertNull(PathUtils.getFileName(Paths.get("/"), Path::toString)); assertNull(PathUtils.getFileName(Paths.get("/"), Path::toString)); assertEquals("", PathUtils.getFileName(Paths.get(""), Path::toString)); assertEquals("a", PathUtils.getFileName(Paths.get("a"), Path::toString)); assertEquals("a", PathUtils.getFileName(Paths.get("p", "a"), Path::toString)); } @Test public void testGetFileNameString() { assertNull(PathUtils.getFileNameString(Paths.get("/"))); assertEquals("", PathUtils.getFileNameString(Paths.get(""))); assertEquals("a", PathUtils.getFileNameString(Paths.get("a"))); assertEquals("a", PathUtils.getFileNameString(Paths.get("p", "a"))); } @Test public void testGetLastModifiedFileTime_File_Present() throws IOException { assertNotNull(PathUtils.getLastModifiedFileTime(current().toFile())); } @Test public void testGetLastModifiedFileTime_Path_Absent() throws IOException { assertNull(PathUtils.getLastModifiedFileTime(getNonExistentPath())); } @Test public void testGetLastModifiedFileTime_Path_FileTime_Absent() throws IOException { final FileTime fromMillis = FileTime.fromMillis(0); assertEquals(fromMillis, PathUtils.getLastModifiedFileTime(getNonExistentPath(), fromMillis)); } @Test public void testGetLastModifiedFileTime_Path_Present() throws IOException { assertNotNull(PathUtils.getLastModifiedFileTime(current())); } @Test public void testGetLastModifiedFileTime_URI_Present() throws IOException { assertNotNull(PathUtils.getLastModifiedFileTime(current().toUri())); } @Test public void testGetLastModifiedFileTime_URL_Present() throws IOException, URISyntaxException { assertNotNull(PathUtils.getLastModifiedFileTime(current().toUri().toURL())); } @Test public void testGetTempDirectory() { final Path tempDirectory = Paths.get(System.getProperty("java.io.tmpdir")); assertEquals(tempDirectory, PathUtils.getTempDirectory()); } @Test public void testIsDirectory() throws IOException { assertFalse(PathUtils.isDirectory(null)); assertTrue(PathUtils.isDirectory(tempDirPath)); try (TempFile testFile1 = TempFile.create(tempDirPath, "prefix", null)) { assertFalse(PathUtils.isDirectory(testFile1.get())); Path ref = null; try (TempDirectory tempDir = TempDirectory.create(getClass().getCanonicalName())) { ref = tempDir.get(); assertTrue(PathUtils.isDirectory(tempDir.get())); } assertFalse(PathUtils.isDirectory(ref)); } } @Test public void testIsPosix() throws IOException { boolean isPosix; try { Files.getPosixFilePermissions(current()); isPosix = true; } catch (final UnsupportedOperationException e) { isPosix = false; } assertEquals(isPosix, PathUtils.isPosix(current())); } @Test public void testIsRegularFile() throws IOException { assertFalse(PathUtils.isRegularFile(null)); assertFalse(PathUtils.isRegularFile(tempDirPath)); try (TempFile testFile1 = TempFile.create(tempDirPath, "prefix", null)) { assertTrue(PathUtils.isRegularFile(testFile1.get())); Files.delete(testFile1.get()); assertFalse(PathUtils.isRegularFile(testFile1.get())); } } @Test public void testNewDirectoryStream() throws Exception { final PathFilter pathFilter = new NameFileFilter(PATH_FIXTURE); try (DirectoryStream stream = PathUtils.newDirectoryStream(current(), pathFilter)) { final Iterator iterator = stream.iterator(); final Path path = iterator.next(); assertEquals(PATH_FIXTURE, PathUtils.getFileNameString(path)); assertFalse(iterator.hasNext()); } } @Test public void testNewOutputStreamExistingFileAppendFalse() throws IOException { testNewOutputStreamNewFile(false); testNewOutputStreamNewFile(false); } @Test public void testNewOutputStreamExistingFileAppendTrue() throws IOException { testNewOutputStreamNewFile(true); final Path file = writeToNewOutputStream(true); assertArrayEquals(ArrayUtils.addAll(BYTE_ARRAY_FIXTURE, BYTE_ARRAY_FIXTURE), Files.readAllBytes(file)); } public void testNewOutputStreamNewFile(final boolean append) throws IOException { final Path file = writeToNewOutputStream(append); assertArrayEquals(BYTE_ARRAY_FIXTURE, Files.readAllBytes(file)); } @Test public void testNewOutputStreamNewFileAppendFalse() throws IOException { testNewOutputStreamNewFile(false); } @Test public void testNewOutputStreamNewFileAppendTrue() throws IOException { testNewOutputStreamNewFile(true); } @Test public void testNewOutputStreamNewFileInsideExistingSymlinkedDir() throws IOException { final Path symlinkDir = createTempSymlinkedRelativeDir(tempDirPath); final Path file = symlinkDir.resolve("test.txt"); try (OutputStream outputStream = PathUtils.newOutputStream(file, new LinkOption[] {})) { // empty } try (OutputStream outputStream = PathUtils.newOutputStream(file, null)) { // empty } try (OutputStream outputStream = PathUtils.newOutputStream(file, true)) { // empty } try (OutputStream outputStream = PathUtils.newOutputStream(file, false)) { // empty } } @Test public void testReadAttributesPosix() throws IOException { boolean isPosix; try { Files.getPosixFilePermissions(current()); isPosix = true; } catch (final UnsupportedOperationException e) { isPosix = false; } assertEquals(isPosix, PathUtils.readAttributes(current(), PosixFileAttributes.class) != null); } @Test public void testReadStringEmptyFile() throws IOException { final Path path = Paths.get("src/test/resources/org/apache/commons/io/test-file-empty.bin"); assertEquals(StringUtils.EMPTY, PathUtils.readString(path, StandardCharsets.UTF_8)); assertEquals(StringUtils.EMPTY, PathUtils.readString(path, null)); } @Test public void testReadStringSimpleUtf8() throws IOException { final Path path = Paths.get("src/test/resources/org/apache/commons/io/test-file-simple-utf8.bin"); final String expected = "ABC\r\n"; assertEquals(expected, PathUtils.readString(path, StandardCharsets.UTF_8)); assertEquals(expected, PathUtils.readString(path, null)); } @Test public void testSetReadOnlyFile() throws IOException { final Path resolved = tempDirPath.resolve("testSetReadOnlyFile.txt"); // Ask now, as we are allowed before editing parent permissions. final boolean isPosix = PathUtils.isPosix(tempDirPath); // TEMP HACK assumeFalse(SystemUtils.IS_OS_LINUX); PathUtils.writeString(resolved, "test", StandardCharsets.UTF_8); final boolean readable = Files.isReadable(resolved); final boolean writable = Files.isWritable(resolved); final boolean regularFile = Files.isRegularFile(resolved); final boolean executable = Files.isExecutable(resolved); final boolean hidden = Files.isHidden(resolved); final boolean directory = Files.isDirectory(resolved); final boolean symbolicLink = Files.isSymbolicLink(resolved); // Sanity checks assertTrue(readable); assertTrue(writable); // Test A PathUtils.setReadOnly(resolved, false); assertTrue(Files.isReadable(resolved), "isReadable"); assertTrue(Files.isWritable(resolved), "isWritable"); // Again, shouldn't blow up. PathUtils.setReadOnly(resolved, false); assertTrue(Files.isReadable(resolved), "isReadable"); assertTrue(Files.isWritable(resolved), "isWritable"); // assertEquals(regularFile, Files.isReadable(resolved)); assertEquals(executable, Files.isExecutable(resolved)); assertEquals(hidden, Files.isHidden(resolved)); assertEquals(directory, Files.isDirectory(resolved)); assertEquals(symbolicLink, Files.isSymbolicLink(resolved)); // Test B PathUtils.setReadOnly(resolved, true); if (isPosix) { // On POSIX, now that the parent is not WX, the file is not readable. assertFalse(Files.isReadable(resolved), "isReadable"); } else { assertTrue(Files.isReadable(resolved), "isReadable"); } assertFalse(Files.isWritable(resolved), "isWritable"); final DosFileAttributeView dosFileAttributeView = PathUtils.getDosFileAttributeView(resolved); if (dosFileAttributeView != null) { assertTrue(dosFileAttributeView.readAttributes().isReadOnly()); } if (isPosix) { assertFalse(Files.isReadable(resolved)); } else { assertEquals(regularFile, Files.isReadable(resolved)); } assertEquals(executable, Files.isExecutable(resolved)); assertEquals(hidden, Files.isHidden(resolved)); assertEquals(directory, Files.isDirectory(resolved)); assertEquals(symbolicLink, Files.isSymbolicLink(resolved)); // PathUtils.setReadOnly(resolved, false); PathUtils.deleteFile(resolved); } @Test public void testTouch() throws IOException { assertThrows(NullPointerException.class, () -> FileUtils.touch(null)); final Path file = managedTempDirPath.resolve("touch.txt"); Files.deleteIfExists(file); assertFalse(Files.exists(file), "Bad test: test file still exists"); PathUtils.touch(file); assertTrue(Files.exists(file), "touch() created file"); try (OutputStream out = Files.newOutputStream(file)) { assertEquals(0, Files.size(file), "Created empty file."); out.write(0); } assertEquals(1, Files.size(file), "Wrote one byte to file"); final long y2k = new GregorianCalendar(2000, 0, 1).getTime().getTime(); setLastModifiedMillis(file, y2k); // 0L fails on Win98 assertEquals(y2k, getLastModifiedMillis(file), "Bad test: set lastModified set incorrect value"); final long nowMillis = System.currentTimeMillis(); PathUtils.touch(file); assertEquals(1, Files.size(file), "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 testWriteStringToFile1() throws Exception { final Path file = tempDirPath.resolve("write.txt"); PathUtils.writeString(file, "Hello /u1234", StandardCharsets.UTF_8); final byte[] text = "Hello /u1234".getBytes(StandardCharsets.UTF_8); TestUtils.assertEqualContent(text, file); } /** * Tests newOutputStream() here and don't use Files.write obviously. */ private Path writeToNewOutputStream(final boolean append) throws IOException { final Path file = tempDirPath.resolve("test1.txt"); try (OutputStream os = PathUtils.newOutputStream(file, append)) { os.write(BYTE_ARRAY_FIXTURE); } return file; } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/file/PathUtilsVisitorTest.java0100644 0000000 0000000 00000010535 14603604450 031513 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.16.1-src/src/test/java/org/apache/commons/io/file/TempDirectory.java0100644 0000000 0000000 00000005334 14603604450 030151 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.attribute.FileAttribute; /** * A temporary directory path that deletes its delegate on close. * * @since 2.12.0 */ public class TempDirectory extends DeletablePath { /** * Creates a new instance for a new temporary directory in the specified directory, using the given prefix to generate * its name. * * @param dir See {@link Files#createTempDirectory(String, FileAttribute...)}. * @param prefix See {@link Files#createTempDirectory(String, FileAttribute...)}. * @param attrs See {@link Files#createTempDirectory(String, FileAttribute...)}. * @return a new instance for a new temporary directory * @throws IOException See {@link Files#createTempDirectory(String, FileAttribute...)}. */ public static TempDirectory create(final Path dir, final String prefix, final FileAttribute... attrs) throws IOException { return new TempDirectory(Files.createTempDirectory(dir, prefix, attrs)); } /** * Creates a new instance for a new temporary directory in the specified directory, using the given prefix to generate * its name. * * @param prefix See {@link Files#createTempDirectory(String, FileAttribute...)}. * @param attrs See {@link Files#createTempDirectory(String, FileAttribute...)}. * @return a new instance for a new temporary directory * @throws IOException See {@link Files#createTempDirectory(String, FileAttribute...)}. */ public static TempDirectory create(final String prefix, final FileAttribute... attrs) throws IOException { return new TempDirectory(Files.createTempDirectory(prefix, attrs)); } /** * Constructs a new instance wrapping the given delegate. * * @param path The delegate. */ private TempDirectory(final Path path) { super(path); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/file/TempDirectoryTest.java0100644 0000000 0000000 00000004244 14603604450 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.file; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import org.apache.commons.io.FileUtils; import org.junit.jupiter.api.Test; /** * Tests {@link TempDirectory}. */ public class TempDirectoryTest { @SuppressWarnings("resource") @Test public void testCreatePath() throws IOException { final TempDirectory ref; try (TempDirectory tempDir = TempDirectory.create(getClass().getCanonicalName())) { ref = tempDir; assertTrue(FileUtils.isEmptyDirectory(tempDir.toFile())); } assertFalse(Files.exists(ref.get())); // Fails with a ProviderMismatchException because the Windows FS uses "instanceof sun.nio.fs.WindowsPath". // WindowsPath is a class, not an interface we can proxy. // assertFalse(Files.exists(ref)); } @SuppressWarnings("resource") @Test public void testCreateString() throws IOException { final TempDirectory ref; try (TempDirectory tempDir = TempDirectory.create(Paths.get("target"), getClass().getCanonicalName())) { ref = tempDir; assertTrue(FileUtils.isEmptyDirectory(tempDir.toFile())); } assertFalse(Files.exists(ref.get())); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/file/TempFile.java0100644 0000000 0000000 00000005734 14603604450 027070 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.attribute.FileAttribute; /** * A temporary file path that deletes its delegate on close. * * @since 2.12.0 */ public class TempFile extends DeletablePath { /** * Creates a new instance for a new temporary file in the specified directory, using the given prefix to generate its * name. * * @param dir See {@link Files#createTempFile(Path, String, String, FileAttribute...)}. * @param prefix See {@link Files#createTempFile(Path, String, String, FileAttribute...)}. * @param suffix See {@link Files#createTempFile(Path, String, String, FileAttribute...)}. * @param attrs See {@link Files#createTempFile(Path, String, String, FileAttribute...)}. * @return a new instance for a new temporary directory * @throws IOException See {@link Files#createTempFile(Path, String, String, FileAttribute...)}. */ public static TempFile create(final Path dir, final String prefix, final String suffix, final FileAttribute... attrs) throws IOException { return new TempFile(Files.createTempFile(dir, prefix, suffix, attrs)); } /** * Creates a new instance for a new temporary file in the specified directory, using the given prefix to generate its * name. * * @param prefix See {@link Files#createTempFile(Path, String, String, FileAttribute...)}. * @param suffix See {@link Files#createTempFile(Path, String, String, FileAttribute...)}. * @param attrs See {@link Files#createTempFile(Path, String, String, FileAttribute...)}. * @return a new instance for a new temporary directory * @throws IOException See {@link Files#createTempFile(Path, String, String, FileAttribute...)}. */ public static TempFile create(final String prefix, final String suffix, final FileAttribute... attrs) throws IOException { return new TempFile(Files.createTempFile(prefix, suffix, attrs)); } /** * Constructs a new instance wrapping the given delegate. * * @param path The delegate. */ private TempFile(final Path path) { super(path); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/file/TempFileTest.java0100644 0000000 0000000 00000004053 14603604450 027721 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import org.junit.jupiter.api.Test; /** * Tests {@link TempFile}. */ public class TempFileTest { @SuppressWarnings("resource") @Test public void testCreatePath() throws IOException { final TempFile ref; try (TempFile tempDir = TempFile.create(Paths.get("target"), "prefix", ".suffix")) { ref = tempDir; assertTrue(Files.exists(ref.get())); } assertFalse(Files.exists(ref.get())); // Fails with a ProviderMismatchException because the Windows FS uses "instanceof sun.nio.fs.WindowsPath". // WindowsPath is a class, not an interface we can proxy. // assertFalse(Files.exists(ref)); } @SuppressWarnings("resource") @Test public void testCreateString() throws IOException { final TempFile ref; try (TempFile tempDir = TempFile.create(getClass().getCanonicalName(), ".suffix")) { ref = tempDir; assertTrue(Files.exists(ref.get())); } assertFalse(Files.exists(ref.get())); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/file/TestArguments.java0100644 0000000 0000000 00000004310 14603604450 030155 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.16.1-src/src/test/java/org/apache/commons/io/file/attribute/FileTimesTest.java0100644 0000000 0000000 00000024045 14603604450 032103 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.attribute; 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.nio.file.attribute.FileTime; import java.time.Instant; import java.util.Date; import java.util.concurrent.TimeUnit; import java.util.stream.Stream; 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; /** * Tests {@link FileTimes}. */ public class FileTimesTest { public static Stream dateToNtfsProvider() { // @formatter:off return Stream.of( Arguments.of("1601-01-01T00:00:00.000Z", 0), Arguments.of("1601-01-01T00:00:00.000Z", 1), Arguments.of("1600-12-31T23:59:59.999Z", -1), Arguments.of("1601-01-01T00:00:00.001Z", FileTimes.HUNDRED_NANOS_PER_MILLISECOND), Arguments.of("1601-01-01T00:00:00.001Z", FileTimes.HUNDRED_NANOS_PER_MILLISECOND + 1), Arguments.of("1601-01-01T00:00:00.000Z", FileTimes.HUNDRED_NANOS_PER_MILLISECOND - 1), Arguments.of("1600-12-31T23:59:59.999Z", -FileTimes.HUNDRED_NANOS_PER_MILLISECOND), Arguments.of("1600-12-31T23:59:59.999Z", -FileTimes.HUNDRED_NANOS_PER_MILLISECOND + 1), Arguments.of("1600-12-31T23:59:59.998Z", -FileTimes.HUNDRED_NANOS_PER_MILLISECOND - 1), Arguments.of("1970-01-01T00:00:00.000Z", -FileTimes.WINDOWS_EPOCH_OFFSET), Arguments.of("1970-01-01T00:00:00.000Z", -FileTimes.WINDOWS_EPOCH_OFFSET + 1), Arguments.of("1970-01-01T00:00:00.001Z", -FileTimes.WINDOWS_EPOCH_OFFSET + FileTimes.HUNDRED_NANOS_PER_MILLISECOND), Arguments.of("1969-12-31T23:59:59.999Z", -FileTimes.WINDOWS_EPOCH_OFFSET - 1), Arguments.of("1969-12-31T23:59:59.999Z", -FileTimes.WINDOWS_EPOCH_OFFSET - FileTimes.HUNDRED_NANOS_PER_MILLISECOND)); // @formatter:on } public static Stream fileTimeToNtfsProvider() { // @formatter:off return Stream.of( Arguments.of("1601-01-01T00:00:00.0000000Z", 0), Arguments.of("1601-01-01T00:00:00.0000001Z", 1), Arguments.of("1600-12-31T23:59:59.9999999Z", -1), Arguments.of("1601-01-01T00:00:00.0010000Z", FileTimes.HUNDRED_NANOS_PER_MILLISECOND), Arguments.of("1601-01-01T00:00:00.0010001Z", FileTimes.HUNDRED_NANOS_PER_MILLISECOND + 1), Arguments.of("1601-01-01T00:00:00.0009999Z", FileTimes.HUNDRED_NANOS_PER_MILLISECOND - 1), Arguments.of("1600-12-31T23:59:59.9990000Z", -FileTimes.HUNDRED_NANOS_PER_MILLISECOND), Arguments.of("1600-12-31T23:59:59.9990001Z", -FileTimes.HUNDRED_NANOS_PER_MILLISECOND + 1), Arguments.of("1600-12-31T23:59:59.9989999Z", -FileTimes.HUNDRED_NANOS_PER_MILLISECOND - 1), Arguments.of("1970-01-01T00:00:00.0000000Z", -FileTimes.WINDOWS_EPOCH_OFFSET), Arguments.of("1970-01-01T00:00:00.0000001Z", -FileTimes.WINDOWS_EPOCH_OFFSET + 1), Arguments.of("1970-01-01T00:00:00.0010000Z", -FileTimes.WINDOWS_EPOCH_OFFSET + FileTimes.HUNDRED_NANOS_PER_MILLISECOND), Arguments.of("1969-12-31T23:59:59.9999999Z", -FileTimes.WINDOWS_EPOCH_OFFSET - 1), Arguments.of("1969-12-31T23:59:59.9990000Z", -FileTimes.WINDOWS_EPOCH_OFFSET - FileTimes.HUNDRED_NANOS_PER_MILLISECOND)); // @formatter:on } public static Stream isUnixFileTimeProvider() { // @formatter:off return Stream.of( Arguments.of("2022-12-27T12:45:22Z", true), Arguments.of("2038-01-19T03:14:07Z", true), Arguments.of("1901-12-13T23:14:08Z", true), Arguments.of("1901-12-13T03:14:08Z", false), Arguments.of("2038-01-19T03:14:08Z", false), Arguments.of("2099-06-30T12:31:42Z", false)); // @formatter:on } @ParameterizedTest @MethodSource("dateToNtfsProvider") public void testDateToFileTime(final String instant, final long ignored) { final Instant parsedInstant = Instant.parse(instant); final FileTime parsedFileTime = FileTime.from(parsedInstant); final Date parsedDate = Date.from(parsedInstant); assertEquals(parsedFileTime, FileTimes.toFileTime(parsedDate)); } @ParameterizedTest @MethodSource("dateToNtfsProvider") public void testDateToNtfsTime(final String instant, final long ntfsTime) { final long ntfsMillis = Math.floorDiv(ntfsTime, FileTimes.HUNDRED_NANOS_PER_MILLISECOND) * FileTimes.HUNDRED_NANOS_PER_MILLISECOND; final Date parsed = Date.from(Instant.parse(instant)); assertEquals(ntfsMillis, FileTimes.toNtfsTime(parsed)); assertEquals(ntfsMillis, FileTimes.toNtfsTime(parsed.getTime())); } @Test public void testEpoch() { assertEquals(0, FileTimes.EPOCH.toMillis()); } @ParameterizedTest @MethodSource("fileTimeToNtfsProvider") public void testFileTimeToDate(final String instant, final long ignored) { final Instant parsedInstant = Instant.parse(instant); final FileTime parsedFileTime = FileTime.from(parsedInstant); final Date parsedDate = Date.from(parsedInstant); assertEquals(parsedDate, FileTimes.toDate(parsedFileTime)); } @ParameterizedTest @MethodSource("fileTimeToNtfsProvider") public void testFileTimeToNtfsTime(final String instant, final long ntfsTime) { final FileTime parsed = FileTime.from(Instant.parse(instant)); assertEquals(ntfsTime, FileTimes.toNtfsTime(parsed)); } @ParameterizedTest @MethodSource("dateToNtfsProvider") public void testFromUnixTime(final String instant, final long ntfsTime) { final long epochSecond = Instant.parse(instant).getEpochSecond(); assertEquals(epochSecond, FileTimes.fromUnixTime(epochSecond).to(TimeUnit.SECONDS)); } @ParameterizedTest @MethodSource("isUnixFileTimeProvider") public void testIsUnixTime(final String instant, final boolean isUnixTime) { assertEquals(isUnixTime, FileTimes.isUnixTime(FileTime.from(Instant.parse(instant)))); } public void testIsUnixTimeFileTimeNull() { assertTrue(FileTimes.isUnixTime(null)); } @ParameterizedTest @MethodSource("isUnixFileTimeProvider") public void testIsUnixTimeLong(final String instant, final boolean isUnixTime) { assertEquals(isUnixTime, FileTimes.isUnixTime(Instant.parse(instant).getEpochSecond())); } @Test public void testMinusMillis() { final int millis = 2; assertEquals(Instant.EPOCH.minusMillis(millis), FileTimes.minusMillis(FileTimes.EPOCH, millis).toInstant()); assertEquals(Instant.EPOCH, FileTimes.minusMillis(FileTimes.EPOCH, 0).toInstant()); } @Test public void testMinusNanos() { final int millis = 2; assertEquals(Instant.EPOCH.minusNanos(millis), FileTimes.minusNanos(FileTimes.EPOCH, millis).toInstant()); assertEquals(Instant.EPOCH, FileTimes.minusNanos(FileTimes.EPOCH, 0).toInstant()); } @Test public void testMinusSeconds() { final int seconds = 2; assertEquals(Instant.EPOCH.minusSeconds(seconds), FileTimes.minusSeconds(FileTimes.EPOCH, seconds).toInstant()); assertEquals(Instant.EPOCH, FileTimes.minusSeconds(FileTimes.EPOCH, 0).toInstant()); } @ParameterizedTest @MethodSource("dateToNtfsProvider") public void testNtfsTimeToDate(final String instant, final long ntfsTime) { assertEquals(Instant.parse(instant), FileTimes.ntfsTimeToDate(ntfsTime).toInstant()); } @ParameterizedTest @MethodSource("fileTimeToNtfsProvider") public void testNtfsTimeToFileTime(final String instant, final long ntfsTime) { final FileTime parsed = FileTime.from(Instant.parse(instant)); assertEquals(parsed, FileTimes.ntfsTimeToFileTime(ntfsTime)); } @Test public void testNullDateToNullFileTime() { assertNull(FileTimes.toFileTime(null)); } @Test public void testNullFileTimeToNullDate() { assertNull(FileTimes.toDate(null)); } @Test public void testPlusMinusMillis() { final int millis = 2; assertEquals(Instant.EPOCH.plusMillis(millis), FileTimes.plusMillis(FileTimes.EPOCH, millis).toInstant()); assertEquals(Instant.EPOCH, FileTimes.plusMillis(FileTimes.EPOCH, 0).toInstant()); } @Test public void testPlusNanos() { final int millis = 2; assertEquals(Instant.EPOCH.plusNanos(millis), FileTimes.plusNanos(FileTimes.EPOCH, millis).toInstant()); assertEquals(Instant.EPOCH, FileTimes.plusNanos(FileTimes.EPOCH, 0).toInstant()); } @Test public void testPlusSeconds() { final int seconds = 2; assertEquals(Instant.EPOCH.plusSeconds(seconds), FileTimes.plusSeconds(FileTimes.EPOCH, seconds).toInstant()); assertEquals(Instant.EPOCH, FileTimes.plusSeconds(FileTimes.EPOCH, 0).toInstant()); } @ParameterizedTest @MethodSource("isUnixFileTimeProvider") public void testToUnixTime(final String instant, final boolean isUnixTime) { assertEquals(isUnixTime, FileTimes.isUnixTime(FileTimes.toUnixTime(FileTime.from(Instant.parse(instant))))); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/file/spi/FileSystemProvidersTest.java0100644 0000000 0000000 00000004615 14603604450 032775 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 org.junit.jupiter.api.Test; public class FileSystemProvidersTest { private static final String FILE_PATH = "file:///foo.txt"; @Test public void testGetFileSystemProvider_all() throws URISyntaxException { for (final FileSystemProvider 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))); } } ././@LongLink0100644 0000000 0000000 00000000154 14603604450 011635 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/filefilter/AbstractConditionalFileFilterTest.javacommons-io-2.16.1-src/src/test/java/org/apache/commons/io/filefilter/AbstractConditionalFileFilterTe0100644 0000000 0000000 00000020214 14603604450 034025 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 AbstractConditionalFileFilterTest extends AbstractIOFileFilterTest { 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; protected abstract IOFileFilter buildFilterUsingAdd(List filters); protected abstract IOFileFilter buildFilterUsingConstructor(List filters); protected abstract ConditionalFileFilter getConditionalFileFilter(); protected abstract String getDefaultWorkingPath(); protected abstract List getFalseResults(); protected abstract List getFilenameResults(); protected abstract List getFileResults(); protected abstract List> getTestFilters(); protected abstract List getTrueResults(); protected abstract String getWorkingPathNamePropertyKey(); @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: "); } fileFilter.getFileFilters().forEach(filter -> { assertTrue(filters.contains(filter), "found file filter"); }); assertEquals(filters.size(), fileFilter.getFileFilters().size(), "file filters count"); } @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 file name filter resetTrueFilters(this.trueFilters); resetFalseFilters(this.falseFilters); assertFilenameFiltering(i, filter, this.file, fileNameResults); assertTrueFiltersInvoked(i, trueFilters, trueResults); assertFalseFiltersInvoked(i, falseFilters, falseResults); } } @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 file name filter resetTrueFilters(this.trueFilters); resetFalseFilters(this.falseFilters); assertFilenameFiltering(i, filter, this.file, fileNameResults); assertTrueFiltersInvoked(i, trueFilters, trueResults); assertFalseFiltersInvoked(i, falseFilters, falseResults); } } @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 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()); filters.forEach(filter -> { fileFilter.removeFileFilter(filter); assertFalse(fileFilter.getFileFilters().contains(filter), "file filter removed"); }); assertEquals(0, fileFilter.getFileFilters().size(), "file filters count"); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/filefilter/AbstractFilterTest.java0100644 0000000 0000000 00000022764 14603604450 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.filefilter; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; 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.IOCase; import org.junit.jupiter.api.io.TempDir; /** * Tests {@link FileFilterUtils} and friends. */ public class AbstractFilterTest { /** * The subversion directory name. */ static final String SVN_DIR_NAME = ".svn"; static final boolean WINDOWS = File.separatorChar == '\\'; @TempDir public File temporaryFolder; void assertFiltering(final IOFileFilter filter, final File file, final boolean expected) throws IOException { // 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); final Path path = file.toPath(); assertEquals(expected, filter.accept(path, null) != FileVisitResult.TERMINATE, filter::toString); if (Files.isRegularFile(path)) { assertEquals(expected, filter.accept(path, Files.readAttributes(path, BasicFileAttributes.class)) != FileVisitResult.TERMINATE, filter::toString); } assertEquals(expected, filter.matches(path), filter::toString); } else if (file == null) { assertEquals(expected, filter.accept(null), "Filter(File, String) " + filter.getClass().getName() + " not " + expected + " for null"); assertEquals(expected, filter.matches(null), "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.toDefaultFileVisitResult(expected); 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); assertEquals(expectedFileVisitResult != FileVisitResult.TERMINATE, filter.matches(path), "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"); assertEquals(expectedFileVisitResult != FileVisitResult.TERMINATE, filter.matches(path), "Filter(Path, Path) " + filter.getClass().getName() + " not " + expectedFileVisitResult + " for null"); } assertNotNull(filter.toString()); } void assertFooBarFileFiltering(IOFileFilter filter) throws IOException { 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); } boolean equalsLastModified(final File left, final File right) throws IOException { return Files.getLastModifiedTime(left.toPath()).equals(Files.getLastModifiedTime(right.toPath())); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/filefilter/AbstractIOFileFilterTest.java0100644 0000000 0000000 00000013373 14603604450 033370 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; import java.util.Objects; import java.util.stream.Stream; public abstract class AbstractIOFileFilterTest { final 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 reset() { setInvoked(false); } public void setInvoked(final boolean invoked) { this.invoked = invoked; } } final 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 reset() { setInvoked(false); } public void setInvoked(final boolean invoked) { this.invoked = 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 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); assertEquals(expected, filter.matches(file.toPath()), "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 a 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.getParentFile() != null) { assertEquals(expected, filter.accept(file.getParentFile(), file.getName()), "test " + testNumber + " Filter(File, String) " + filter.getClass().getName() + " not " + expected + " for " + file); assertEquals(expected, filter.matches(file.toPath()), "test " + testNumber + " Filter(File) " + filter.getClass().getName() + " not " + expected + " for " + file); } } 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 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) { Stream.of(filters).filter(Objects::nonNull).forEach(TesterFalseFileFilter::reset); } public static void resetTrueFilters(final TesterTrueFileFilter[] filters) { Stream.of(filters).filter(Objects::nonNull).forEach(TesterTrueFileFilter::reset); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/filefilter/AgeFileFilterTest.java0100644 0000000 0000000 00000010324 14603604450 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.FileUtils; 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 = FileUtils.current(); // We are interested in files older than one day final long cutoffMillis = System.currentTimeMillis(); final String[] files = dir.list(new AgeFileFilter(cutoffMillis)); // 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.16.1-src/src/test/java/org/apache/commons/io/filefilter/AndFileFilterTest.java0100644 0000000 0000000 00000024705 14603604450 032100 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.util.ArrayList; import java.util.Collections; import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Tests {@link AndFileFilter}. */ public class AndFileFilterTest extends AbstractConditionalFileFilterTest { private static final String DEFAULT_WORKING_PATH = "./AndFileFilterTestCase/"; private static final String WORKING_PATH_NAME_PROPERTY_KEY = AndFileFilterTest.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(); filters.forEach(filter::addFileFilter); 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 getFilenameResults() { return this.testFilenameResults; } @Override protected List getFileResults() { return this.testFileResults; } @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 testSetTestFiltersClearsOld() { // 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()); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/filefilter/DirectoryFileFilterTest.java0100644 0000000 0000000 00000006627 14603604450 033345 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.FileUtils; 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 = FileUtils.current(); final String[] files = dir.list(DirectoryFileFilter.INSTANCE); // 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.16.1-src/src/test/java/org/apache/commons/io/filefilter/FileFilterTest.java0100644 0000000 0000000 00000207424 14603604450 031456 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.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 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.file.TempFile; import org.apache.commons.io.test.TestUtils; import org.apache.commons.lang3.SystemUtils; import org.junit.jupiter.api.Test; /** * Tests {@link FileFilterUtils}. */ public class FileFilterTest extends AbstractFilterTest { @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 (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 (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 (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() throws IOException { 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(falseFilter), new File("foo.test"), false); } @Test public void testAnd2() throws IOException { 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, null)); assertThrows(NullPointerException.class, () -> new AndFileFilter(null, falseFilter)); assertThrows(NullPointerException.class, () -> new AndFileFilter((List) null)); } @Test public void testAndArray() throws IOException { 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); try (TempFile executablePath = TempFile.create(getClass().getSimpleName(), null)) { final File executableFile = executablePath.toFile(); try (BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(executablePath.get()))) { TestUtils.generateTestData(output, 32); } assertTrue(executableFile.setExecutable(true)); assertFiltering(CanExecuteFileFilter.CAN_EXECUTE, executablePath.get(), true); assertFiltering(CanExecuteFileFilter.CAN_EXECUTE, (Path) null, false); assertFiltering(CanExecuteFileFilter.CAN_EXECUTE, executableFile, true); assertFiltering(CanExecuteFileFilter.CAN_EXECUTE, (File) null, false); executableFile.setExecutable(false); assertFiltering(CanExecuteFileFilter.CANNOT_EXECUTE, executablePath.get(), false); assertFiltering(CanExecuteFileFilter.CANNOT_EXECUTE, (Path) null, true); assertFiltering(CanExecuteFileFilter.CANNOT_EXECUTE, executableFile, false); assertFiltering(CanExecuteFileFilter.CANNOT_EXECUTE, (File) null, true); } } @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 (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, (File) null, false); assertFiltering(CanReadFileFilter.CAN_READ, readOnlyPath, true); assertFiltering(CanReadFileFilter.CAN_READ, (Path) null, false); assertFiltering(CanReadFileFilter.CANNOT_READ, readOnlyFile, false); assertFiltering(CanReadFileFilter.CANNOT_READ, (File) null, true); assertFiltering(CanReadFileFilter.CANNOT_READ, readOnlyPath, false); assertFiltering(CanReadFileFilter.CANNOT_READ, (Path) null, true); assertFiltering(CanReadFileFilter.READ_ONLY, readOnlyFile, true); assertFiltering(CanReadFileFilter.READ_ONLY, (File) null, false); assertFiltering(CanReadFileFilter.READ_ONLY, readOnlyPath, true); assertFiltering(CanReadFileFilter.READ_ONLY, (Path) null, false); 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 (BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(readOnlyFile.toPath()))) { TestUtils.generateTestData(output, 32); } assertTrue(readOnlyFile.setReadOnly()); assertFiltering(CanWriteFileFilter.CAN_WRITE, temporaryFolder, true); assertFiltering(CanWriteFileFilter.CAN_WRITE, readOnlyFile, false); assertFiltering(CanWriteFileFilter.CAN_WRITE, (File) null, false); assertFiltering(CanWriteFileFilter.CAN_WRITE, readOnlyPath, false); assertFiltering(CanWriteFileFilter.CAN_WRITE, (Path) null, false); assertFiltering(CanWriteFileFilter.CANNOT_WRITE, temporaryFolder, false); assertFiltering(CanWriteFileFilter.CANNOT_WRITE, readOnlyFile, true); assertFiltering(CanWriteFileFilter.CANNOT_WRITE, readOnlyPath, true); assertFiltering(CanWriteFileFilter.CANNOT_WRITE, (File) null, true); assertFiltering(CanWriteFileFilter.CANNOT_WRITE, (Path) null, true); readOnlyFile.delete(); } @Test public void testDelegateFileFilter() throws IOException { 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 assertThrows(NullPointerException.class, () -> new DelegateFileFilter((FileFilter) null)); assertThrows(NullPointerException.class, () -> new DelegateFileFilter((FilenameFilter) null)); } @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() throws IOException { 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); // File assertTrue(listFilter.accept(txtFile)); assertFalse(listFilter.accept(bmpFile)); assertFalse(listFilter.accept(dirFile)); // Path assertTrue(listFilter.matches(txtPath)); assertFalse(listFilter.matches(bmpPath)); assertFalse(listFilter.matches(dirPath)); // 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)); assertThrows(NullPointerException.class, () -> new WildcardFilter((String) null)); assertThrows(NullPointerException.class, () -> new WildcardFilter((String[]) null)); assertThrows(NullPointerException.class, () -> new WildcardFilter((List) null)); } @Test public void testDirectory() throws IOException { // 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); assertFiltering(filter, (File) null, false); assertFiltering(filter, (Path) null, 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.EMPTY, (File) null, true); assertFiltering(EmptyFileFilter.EMPTY, (Path) null, true); assertFiltering(EmptyFileFilter.NOT_EMPTY, emptyDirFile, false); assertFiltering(EmptyFileFilter.NOT_EMPTY, emptyDirPath, false); assertFiltering(EmptyFileFilter.NOT_EMPTY, (File) null, false); assertFiltering(EmptyFileFilter.NOT_EMPTY, (Path) null, 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 (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 (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() throws IOException { 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() throws IOException { assertFooBarFileFiltering( new FileEqualsFileFilter(new File("foo")).or(new FileEqualsFileFilter(new File("bar")))); } @Test public void testFileFilterUtils_and() throws IOException { 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() throws IOException { 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() throws IOException { // XXX: This test presumes the current working dir is the base dir of the source checkout. final IOFileFilter filter = FileFileFilter.INSTANCE; assertFiltering(filter, (File) null, false); 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"); assertThrows(NullPointerException.class, () -> FileFilterUtils.filter(null, fileA, fileB)); 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() { assertThrows(NullPointerException.class, () -> FileFilterUtils.filterList(null, Collections.emptyList())); final IOFileFilter filter = FileFilterUtils.trueFileFilter(); List filteredList = FileFilterUtils.filterList(filter, Collections.singletonList(null)); assertEquals(1, filteredList.size()); assertNull(filteredList.get(0)); 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(); assertThrows(NullPointerException.class, () -> PathUtils.filter(null, fileA, fileB)); 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() { assertThrows(NullPointerException.class, () -> FileFilterUtils.filterSet(null, Collections.emptySet())); final IOFileFilter filter = FileFilterUtils.trueFileFilter(); FileFilterUtils.filterSet(filter, new HashSet<>(Collections.singletonList(null))); final Set filteredSet = FileFilterUtils.filterSet(filter, (Set) null); assertEquals(0, filteredSet.size()); } @Test public void testHidden() throws IOException { 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.HIDDEN, (Path) null, true); assertFiltering(HiddenFileFilter.VISIBLE, temporaryFolder, true); assertFiltering(HiddenFileFilter.VISIBLE, path, true); assertFiltering(HiddenFileFilter.VISIBLE, (Path) null, false); } @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 (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 (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 (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 MagicNumberFileFilter((String) null, 0)); assertThrows(IllegalArgumentException.class, () -> new MagicNumberFileFilter("0", -1)); assertThrows(IllegalArgumentException.class, () -> new MagicNumberFileFilter("", 0)); assertThrows(NullPointerException.class, () -> new MagicNumberFileFilter((byte[]) null, 0)); assertThrows(IllegalArgumentException.class, () -> new MagicNumberFileFilter(new byte[] {0}, -1)); assertThrows(IllegalArgumentException.class, () -> new MagicNumberFileFilter(new byte[] {}, 0)); } @Test public void testMakeCVSAware() throws Exception { final IOFileFilter filter1 = FileFilterUtils.makeCVSAware(null); final IOFileFilter filter2 = FileFilterUtils.makeCVSAware(FileFilterUtils.nameFileFilter("test-file1.txt")); File file = new File(temporaryFolder, "CVS"); file.mkdirs(); assertFiltering(filter1, file, false); assertFiltering(filter2, file, false); FileUtils.deleteDirectory(file); file = new File(temporaryFolder, "test-file1.txt"); if (!file.getParentFile().exists()) { fail("Cannot create file " + file + " as the parent directory does not exist"); } try (BufferedOutputStream output2 = new BufferedOutputStream(Files.newOutputStream(file.toPath()))) { TestUtils.generateTestData(output2, 0); } assertFiltering(filter1, file, true); assertFiltering(filter2, file, true); file = new File(temporaryFolder, "test-file2.log"); if (!file.getParentFile().exists()) { fail("Cannot create file " + file + " as the parent directory does not exist"); } try (BufferedOutputStream output1 = new BufferedOutputStream(Files.newOutputStream(file.toPath()))) { TestUtils.generateTestData(output1, 0); } assertFiltering(filter1, file, true); assertFiltering(filter2, file, false); file = new File(temporaryFolder, "CVS"); if (!file.getParentFile().exists()) { fail("Cannot create file " + file + " as the parent directory does not exist"); } try (BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(file.toPath()))) { TestUtils.generateTestData(output, 0); } assertFiltering(filter1, file, true); assertFiltering(filter2, file, false); } @Test public void testMakeDirectoryOnly() throws Exception { assertSame(DirectoryFileFilter.DIRECTORY, FileFilterUtils.makeDirectoryOnly(null)); final IOFileFilter filter = FileFilterUtils.makeDirectoryOnly(FileFilterUtils.nameFileFilter("B")); final File fileA = new File(temporaryFolder, "A"); final File fileB = new File(temporaryFolder, "B"); fileA.mkdirs(); fileB.mkdirs(); assertFiltering(filter, fileA, false); assertFiltering(filter, fileB, true); FileUtils.deleteDirectory(fileA); FileUtils.deleteDirectory(fileB); if (!fileA.getParentFile().exists()) { fail("Cannot create file " + fileA + " as the parent directory does not exist"); } try (BufferedOutputStream output1 = new BufferedOutputStream(Files.newOutputStream(fileA.toPath()))) { TestUtils.generateTestData(output1, 32); } if (!fileB.getParentFile().exists()) { fail("Cannot create file " + fileB + " as the parent directory does not exist"); } try (BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(fileB.toPath()))) { TestUtils.generateTestData(output, 32); } assertFiltering(filter, fileA, false); assertFiltering(filter, fileB, false); fileA.delete(); fileB.delete(); } @Test public void testMakeFileOnly() throws Exception { assertSame(FileFileFilter.INSTANCE, FileFilterUtils.makeFileOnly(null)); final IOFileFilter filter = FileFilterUtils.makeFileOnly(FileFilterUtils.nameFileFilter("B")); final File fileA = new File(temporaryFolder, "A"); final File fileB = new File(temporaryFolder, "B"); fileA.mkdirs(); fileB.mkdirs(); assertFiltering(filter, fileA, false); assertFiltering(filter, fileB, false); FileUtils.deleteDirectory(fileA); FileUtils.deleteDirectory(fileB); if (!fileA.getParentFile().exists()) { fail("Cannot create file " + fileA + " as the parent directory does not exist"); } try (BufferedOutputStream output1 = new BufferedOutputStream(Files.newOutputStream(fileA.toPath()))) { TestUtils.generateTestData(output1, 32); } if (!fileB.getParentFile().exists()) { fail("Cannot create file " + fileB + " as the parent directory does not exist"); } try (BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(fileB.toPath()))) { TestUtils.generateTestData(output, 32); } assertFiltering(filter, fileA, false); assertFiltering(filter, fileB, true); fileA.delete(); fileB.delete(); } @Test public void testMakeSVNAware() throws Exception { final IOFileFilter filter1 = FileFilterUtils.makeSVNAware(null); final IOFileFilter filter2 = FileFilterUtils.makeSVNAware(FileFilterUtils.nameFileFilter("test-file1.txt")); File file = new File(temporaryFolder, SVN_DIR_NAME); file.mkdirs(); assertFiltering(filter1, file, false); assertFiltering(filter2, file, false); FileUtils.deleteDirectory(file); file = new File(temporaryFolder, "test-file1.txt"); if (!file.getParentFile().exists()) { fail("Cannot create file " + file + " as the parent directory does not exist"); } try (BufferedOutputStream output2 = new BufferedOutputStream(Files.newOutputStream(file.toPath()))) { TestUtils.generateTestData(output2, 0); } assertFiltering(filter1, file, true); assertFiltering(filter2, file, true); file = new File(temporaryFolder, "test-file2.log"); if (!file.getParentFile().exists()) { fail("Cannot create file " + file + " as the parent directory does not exist"); } try (BufferedOutputStream output1 = new BufferedOutputStream(Files.newOutputStream(file.toPath()))) { TestUtils.generateTestData(output1, 0); } assertFiltering(filter1, file, true); assertFiltering(filter2, file, false); file = new File(temporaryFolder, SVN_DIR_NAME); if (!file.getParentFile().exists()) { fail("Cannot create file " + file + " as the parent directory does not exist"); } try (BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(file.toPath()))) { TestUtils.generateTestData(output, 0); } assertFiltering(filter1, file, true); assertFiltering(filter2, file, false); } @Test public void testNameFilter() throws IOException { final NameFileFilter filter = new NameFileFilter("foo", "bar"); assertFooBarFileFiltering(filter); assertFiltering(filter, (File) null, false); assertFiltering(filter, (Path) null, false); } @Test public void testNameFilterNullArgument() { final String test = null; final String failMessage = "constructing a NameFileFilter with a null String argument should fail."; assertThrows(NullPointerException.class, () -> new NameFileFilter(test), failMessage); assertThrows(NullPointerException.class, () -> FileFilterUtils.nameFileFilter(test, IOCase.INSENSITIVE), failMessage); } @Test public void testNameFilterNullArrayArgument() { assertThrows(NullPointerException.class, () -> new NameFileFilter((String[]) null)); } @Test public void testNameFilterNullListArgument() { final List test = null; assertThrows(NullPointerException.class, () -> new NameFileFilter(test)); } @Test public void testNegate() throws IOException { 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(NullPointerException.class, () -> new NotFileFilter(null)); } @Test public void testNullFilters() { assertThrows(NullPointerException.class, () -> FileFilterUtils.toList((IOFileFilter) null)); assertThrows(NullPointerException.class, () -> FileFilterUtils.toList(new IOFileFilter[] {null})); } @Test public void testOr() throws IOException { 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)); assertTrue(orFilter.matches(testPath)); orFilter.removeFileFilter(trueFilter); assertFalse(orFilter.accept(testFile.getParentFile(), testFile.getName())); assertEquals(FileVisitResult.TERMINATE, orFilter.accept(testPath, null)); assertFalse(orFilter.matches(testPath)); assertThrows(NullPointerException.class, () -> new OrFileFilter(falseFilter, null)); } @Test public void testPathEqualsFilter() throws IOException { assertFooBarFileFiltering( new PathEqualsFileFilter(Paths.get("foo")).or(new PathEqualsFileFilter(Paths.get("bar")))); } @Test public void testPrefix() throws IOException { 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)); // assertTrue(filter.matches(testPath)); assertFalse(filter.matches(fredPath)); 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)); // assertFalse(listFilter.matches(testPath)); assertTrue(listFilter.matches(fredPath)); assertThrows(NullPointerException.class, () -> new PrefixFileFilter((String) null)); assertThrows(NullPointerException.class, () -> new PrefixFileFilter((String[]) null)); assertThrows(NullPointerException.class, () -> new PrefixFileFilter((List) null)); } @Test public void testPrefixCaseInsensitive() throws IOException { 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-insensitive assertFiltering(filter, new File("BAR.test1"), true); // case-insensitive 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-insensitive assertFiltering(filter, new File("BAR.test2"), true); // case-insensitive 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-insensitive assertFiltering(filter, new File("BAR.test3"), true); // case-insensitive assertThrows(NullPointerException.class, () -> new PrefixFileFilter((String) null, IOCase.INSENSITIVE)); assertThrows(NullPointerException.class, () -> new PrefixFileFilter((String[]) null, IOCase.INSENSITIVE)); assertThrows(NullPointerException.class, () -> new PrefixFileFilter((List) null, IOCase.INSENSITIVE)); // 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-insensitive assertFiltering(filter, new File("BAR.test2"), true); // case-insensitive assertThrows(NullPointerException.class, () -> FileFilterUtils.prefixFileFilter(null, IOCase.INSENSITIVE)); } @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 (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 (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); assertThrows(IllegalArgumentException.class, () -> FileFilterUtils.sizeFileFilter(-1)); } @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); assertThrows(IllegalArgumentException.class, () -> FileFilterUtils.sizeFileFilter(-1)); } @Test public void testSuffix() throws IOException { 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)); // assertTrue(filter.matches(testPath)); assertFalse(filter.matches(fredPath)); 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)); assertThrows(NullPointerException.class, () -> new SuffixFileFilter((String) null)); assertThrows(NullPointerException.class, () -> new SuffixFileFilter((String[]) null)); assertThrows(NullPointerException.class, () -> new SuffixFileFilter((List) null)); } @Test public void testSuffixCaseInsensitive() throws IOException { 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); assertThrows(NullPointerException.class, () -> new SuffixFileFilter((String) null, IOCase.INSENSITIVE)); assertThrows(NullPointerException.class, () -> new SuffixFileFilter((String[]) null, IOCase.INSENSITIVE)); assertThrows(NullPointerException.class, () -> new SuffixFileFilter((List) null, IOCase.INSENSITIVE)); // FileFilterUtils.suffixFileFilter(String, IOCase) tests filter = FileFilterUtils.suffixFileFilter("est", IOCase.INSENSITIVE); assertFiltering(filter, new File("test"), true); assertFiltering(filter, new File("TEST"), true); assertThrows(NullPointerException.class, () -> FileFilterUtils.suffixFileFilter(null, IOCase.INSENSITIVE)); } @Test public void testTrue() throws IOException { 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()); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/filefilter/NameFileFilterTest.java0100644 0000000 0000000 00000010740 14603604450 032250 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.FileUtils; 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 = FileUtils.current(); final String[] files = dir.list(new NameFileFilter("NOTICE.txt")); // 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.16.1-src/src/test/java/org/apache/commons/io/filefilter/OrFileFilterTest.java0100644 0000000 0000000 00000023105 14603604450 031747 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 OrFileFilterTest extends AbstractConditionalFileFilterTest { private static final String DEFAULT_WORKING_PATH = "./OrFileFilterTestCase/"; private static final String WORKING_PATH_NAME_PROPERTY_KEY = OrFileFilterTest.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(); filters.forEach(filter::addFileFilter); 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 getFilenameResults() { return this.testFilenameResults; } @Override protected List getFileResults() { return this.testFileResults; } @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.16.1-src/src/test/java/org/apache/commons/io/filefilter/PathMatcherFileFilterTest.java0100644 0000000 0000000 00000003723 14603604450 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.filefilter; 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.FileSystems; import org.apache.commons.io.FileSystem; import org.junit.jupiter.api.Test; /** * Tests {@link PathMatcherFileFilter}. */ public class PathMatcherFileFilterTest extends AbstractFilterTest { @Test public void testGlob() throws IOException { @SuppressWarnings("resource") final IOFileFilter filter = new PathMatcherFileFilter(FileSystems.getDefault().getPathMatcher("glob:*.txt")); final File file1 = new File("log.txt"); final File file2 = new File("log.TXT"); // assertTrue(filter.accept(file1)); assertEquals(!FileSystem.getCurrent().isCaseSensitive(), filter.accept(file2)); assertTrue(filter.accept(file1.getParentFile(), file1.getName())); assertEquals(!FileSystem.getCurrent().isCaseSensitive(), filter.accept(file2.getParentFile(), file2.getName())); assertFiltering(filter, file1, true); assertFiltering(filter, file1.toPath(), true); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/filefilter/RegexFileFilterTest.java0100644 0000000 0000000 00000021434 14603604450 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 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.assertTrue; import java.io.File; import java.io.IOException; import java.io.ObjectOutputStream; import java.io.Serializable; import java.nio.file.FileVisitResult; import java.nio.file.Path; import java.nio.file.Paths; import java.util.function.Function; import java.util.regex.Pattern; import org.apache.commons.io.IOCase; import org.apache.commons.io.output.ByteArrayOutputStream; import org.junit.jupiter.api.Test; /** * Tests {@link RegexFileFilter}. */ public class RegexFileFilterTest { 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); assertEquals(expected, filter.matches(file.toPath()), "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"); assertEquals(expected, filter.matches(null), "Filter(File, String) " + filter.getClass().getName() + " not " + expected + " for null"); } // Just don't blow up assertNotNull(filter.toString()); } 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.toDefaultFileVisitResult(expected); assertEquals(expectedFileVisitResult, filter.accept(path, null), "Filter(Path) " + filter.getClass().getName() + " not " + expectedFileVisitResult + " for " + path); assertEquals(expectedFileVisitResult != FileVisitResult.TERMINATE, filter.matches(path), "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"); } // Just don't blow up assertNotNull(filter.toString()); } private RegexFileFilter assertSerializable(final RegexFileFilter serializable) throws IOException { try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) { try (ObjectOutputStream oos = new ObjectOutputStream(baos)) { oos.writeObject(serializable); } baos.flush(); assertTrue(baos.toByteArray().length > 0); } return serializable; } @Test public void testRegex() throws IOException { RegexFileFilter filter = new RegexFileFilter("^.*[tT]est(-\\d+)?\\.java$"); assertSerializable(filter); 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$"); assertSerializable(filter); 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)); assertSerializable(filter); 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); assertSerializable(filter); 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); assertSerializable(filter); 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() { assertThrows(NullPointerException.class, () -> assertSerializable(new RegexFileFilter((String) null))); assertThrows(NullPointerException.class, () -> assertSerializable(new RegexFileFilter(null, Pattern.CASE_INSENSITIVE))); assertThrows(NullPointerException.class, () -> assertSerializable(new RegexFileFilter(null, IOCase.INSENSITIVE))); assertThrows(NullPointerException.class, () -> assertSerializable(new RegexFileFilter((java.util.regex.Pattern) null))); } /** * Tests https://issues.apache.org/jira/browse/IO-733. * * @throws IOException */ @SuppressWarnings("unchecked") @Test public void testRegexFileNameOnly() throws IOException { final Path path = Paths.get("folder", "Foo.java"); final String patternStr = "Foo.*"; assertFiltering(assertSerializable(new RegexFileFilter(patternStr)), path, true); assertFiltering(assertSerializable(new RegexFileFilter(Pattern.compile(patternStr), (Function & Serializable) Path::toString)), path, false); // assertFiltering(new RegexFileFilter(Pattern.compile(patternStr), (Function & Serializable) null), path, false); assertFiltering(new RegexFileFilter(Pattern.compile(patternStr), (Function & Serializable) p -> null), path, false); // assertFiltering(assertSerializable(new RegexFileFilter(Pattern.compile(patternStr), (Function & Serializable) null)), path, false); assertFiltering(assertSerializable(new RegexFileFilter(Pattern.compile(patternStr), (Function & Serializable) p -> null)), path, false); } } ././@LongLink0100644 0000000 0000000 00000000145 14603604450 011635 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/filefilter/SymbolicLinkFileFilterTest.javacommons-io-2.16.1-src/src/test/java/org/apache/commons/io/filefilter/SymbolicLinkFileFilterTest.java0100644 0000000 0000000 00000017714 14603604450 033777 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.io.IOException; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; import org.apache.commons.io.file.PathUtils; import org.apache.commons.io.function.IOBiFunction; import org.apache.commons.lang3.SystemUtils; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; /** * Tests {@link SymbolicLinkFileFilter}. */ public class SymbolicLinkFileFilterTest { public static final String TARGET_SHORT_NAME = "SLFF_Target"; public static final String TARGET_EXT = ".txt"; public static final String TARGET_NAME = TARGET_SHORT_NAME + TARGET_EXT; public static final String DIRECTORY_NAME = "SLFF_TargetDirectory"; public static final String DIRECTORY_LINK_NAME = "SLFF_LinkDirectory"; public static final String MISSING = "Missing"; private static File testTargetFile; // hard file private static Path testTargetPath; // hard file Path private static File parentDirectoryFile; // System Temp directory private static File testLinkFile; // symbolic link to hard file private static String linkName; // Name of link file private static Path testLinkPath; // symbolic link to hard file Path private static File targetDirFile; // private static Path targetDirPath; // hard directory Path private static Path testLinkDirPath; // symbolic link to hardDirectory private static File testLinkDirFile; private static File missingFileFile; // non-existent file private static Path missingFilePath; // non-existent file private static SymbolicLinkFileFilter filter; // Mock filter for testing on Windows. private static SymbolicLinkFileFilter createMockFilter() { return new SymbolicLinkFileFilter() { private static final long serialVersionUID = 1L; @Override boolean isSymbolicLink(final Path filePath) { return filePath.toFile().exists() && filePath.toString().contains("Link"); // Mock test } }; } private static Path createMockSymbolicLink(final Path link, final Path target) throws IOException { return Files.createFile(link); } private static Path createRealSymbolicLink(final Path link, final Path target) throws IOException { Files.deleteIfExists(link); return Files.createSymbolicLink(link, target); } @AfterAll static void tearDown() { // Fortunately, delete() doesn't throw an exception if the file doesn't exist. testLinkDirFile.delete(); targetDirFile.delete(); testLinkFile.delete(); testTargetFile.delete(); } /** *

* Unit test setup creates a hard file, a symbolic link to the hard file, a hard directory, and a symbolic link to that directory. All are created in the * temp directory *

*

* Unit test teardown deletes all four of these files. *

* * @throws IOException If it fails to create the temporary files */ @BeforeAll static void testSetup() throws IOException { final IOBiFunction symbolicLinkCreator; // We can't create symbolic links on Windows without admin privileges, // so iff that's our OS, we mock them. if (SystemUtils.IS_OS_WINDOWS) { symbolicLinkCreator = SymbolicLinkFileFilterTest::createMockSymbolicLink; filter = createMockFilter(); } else { symbolicLinkCreator = SymbolicLinkFileFilterTest::createRealSymbolicLink; filter = SymbolicLinkFileFilter.INSTANCE; } testTargetFile = File.createTempFile(TARGET_SHORT_NAME, TARGET_EXT); testTargetPath = testTargetFile.toPath(); parentDirectoryFile = testTargetFile.getParentFile(); // parent directory final Path parentDirectoryPath = parentDirectoryFile.toPath(); linkName = "SLFF_LinkTo" + testTargetFile.getName(); testLinkPath = symbolicLinkCreator.apply(parentDirectoryPath.resolve(linkName), testTargetPath); testLinkFile = testLinkPath.toFile(); targetDirPath = Files.createDirectories(parentDirectoryPath.resolve(DIRECTORY_NAME)); targetDirFile = targetDirPath.toFile(); testLinkDirPath = symbolicLinkCreator.apply(parentDirectoryPath.resolve(DIRECTORY_LINK_NAME), targetDirPath); testLinkDirFile = testLinkDirPath.toFile(); missingFileFile = new File(parentDirectoryPath.toFile(), MISSING); missingFilePath = missingFileFile.toPath(); } @Test public void testFileFilter_HardDirectory() { assertFalse(filter.accept(targetDirFile)); } @Test public void testFileFilter_HardFile() { assertFalse(filter.accept(testTargetFile)); } @Test public void testFileFilter_Link() { assertTrue(filter.accept(testLinkFile)); } @Test public void testFileFilter_missingFile() { assertFalse(filter.accept(missingFileFile)); } @Test public void testFileFilter_PathLink() { assertTrue(filter.accept(testLinkDirFile)); } @Test public void testFileNameFilter_HardDirectory() { assertFalse(filter.accept(parentDirectoryFile, DIRECTORY_NAME)); } @Test public void testFileNameFilter_HardFile() { assertFalse(filter.accept(parentDirectoryFile, TARGET_NAME)); } @Test public void testFileNameFilter_Link() { assertTrue(filter.accept(parentDirectoryFile, linkName)); } @Test public void testFileNameFilter_missingFile() { assertFalse(filter.accept(parentDirectoryFile, MISSING)); } @Test public void testFileNameFilter_PathLink() { assertTrue(filter.accept(parentDirectoryFile, DIRECTORY_LINK_NAME)); } @Test public void testPathFilter_HardDirectory() { assertEquals(FileVisitResult.TERMINATE, filter.accept(targetDirPath, null)); assertFalse(filter.matches(targetDirPath)); } @Test public void testPathFilter_HardFile() { assertEquals(FileVisitResult.TERMINATE, filter.accept(testTargetPath, null)); assertFalse(filter.matches(testTargetPath)); } @Test public void testPathFilter_Link() { assertEquals(FileVisitResult.CONTINUE, filter.accept(testLinkPath, null)); assertTrue(filter.matches(testLinkPath)); } @Test public void testPathFilter_missingFile() { assertEquals(FileVisitResult.TERMINATE, filter.accept(missingFilePath, null)); assertFalse(filter.matches(missingFilePath)); } @Test public void testPathFilter_PathLink() { assertEquals(FileVisitResult.CONTINUE, filter.accept(testLinkDirPath, null)); assertTrue(filter.matches(testLinkDirPath)); } @Test public void testSymbolicLinkFileFilter() { assertEquals(FileVisitResult.TERMINATE, SymbolicLinkFileFilter.INSTANCE.accept(PathUtils.current(), null)); assertFalse(filter.matches(PathUtils.current())); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/filefilter/WildcardFileFilterTest.java0100644 0000000 0000000 00000020437 14603604450 033125 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.File; import java.io.IOException; import java.nio.file.FileVisitResult; import java.nio.file.Path; import java.util.Arrays; import java.util.List; import org.apache.commons.io.IOCase; import org.junit.jupiter.api.Test; public class WildcardFileFilterTest extends AbstractFilterTest { @Test public void testWildcard() throws IOException { 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); // filter = WildcardFileFilter.builder().setWildcards("*.txt").setIoCase(IOCase.SENSITIVE).get(); 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 = WildcardFileFilter.builder().setWildcards("*.txt").setIoCase(IOCase.INSENSITIVE).get(); 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 = WildcardFileFilter.builder().setWildcards("*.txt").setIoCase(IOCase.SYSTEM).get(); 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 = WildcardFileFilter.builder().setWildcards("*.txt").setIoCase(null).get(); 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 = WildcardFileFilter.builder().setWildcards("*.java", "*.class").get(); 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 = WildcardFileFilter.builder().setWildcards("*.java", "*.class").setIoCase(IOCase.SENSITIVE).get(); 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 = WildcardFileFilter.builder().setWildcards("*.java", "*.class").setIoCase(IOCase.INSENSITIVE).get(); 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 = WildcardFileFilter.builder().setWildcards("*.java", "*.class").setIoCase(IOCase.SYSTEM).get(); 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 = WildcardFileFilter.builder().setWildcards("*.java", "*.class").setIoCase(null).get(); 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 = WildcardFileFilter.builder().setWildcards(patternList).get(); 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(); // File assertTrue(listFilter.accept(txtFile)); assertFalse(listFilter.accept(bmpFile)); assertFalse(listFilter.accept(dirFile)); // Path assertTrue(listFilter.matches(txtPath)); assertFalse(listFilter.matches(bmpPath)); assertFalse(listFilter.matches(dirPath)); // 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)); assertThrows(NullPointerException.class, () -> new WildcardFileFilter((String) null)); assertThrows(NullPointerException.class, () -> new WildcardFileFilter((String[]) null)); assertThrows(NullPointerException.class, () -> new WildcardFileFilter((List) null)); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/function/EraseTest.java0100644 0000000 0000000 00000007037 14603604450 030166 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import org.junit.jupiter.api.Test; /** * Tests {@code Erase}. */ final class EraseTest { private final AtomicInteger intRef = new AtomicInteger(); private final AtomicBoolean boolRef = new AtomicBoolean(); @Test void testAcceptIOBiConsumerOfTUTU() { Erase.accept((e, f) -> boolRef.set(intRef.compareAndSet(0, e)), 1, true); assertEquals(1, intRef.get()); assertTrue(boolRef.get()); assertThrows(IOException.class, () -> Erase.accept(TestUtils.throwingIOBiConsumer(), null, 1)); } @Test void testAcceptIOConsumerOfTT() { Erase.accept(e -> intRef.compareAndSet(0, e), 1); assertEquals(1, intRef.get()); assertThrows(IOException.class, () -> Erase.accept(TestUtils.throwingIOConsumer(), 1)); } @Test void testApplyIOBiFunctionOfQsuperTQsuperUQextendsRTU() { assertTrue(Erase.apply((i, b) -> boolRef.compareAndSet(false, intRef.compareAndSet(0, i.intValue())), 1, Boolean.TRUE)); assertThrows(IOException.class, () -> Erase.apply(TestUtils.throwingIOBiFunction(), 1, Boolean.TRUE)); } @Test void testApplyIOFunctionOfQsuperTQextendsRT() { assertTrue(Erase.apply(e -> intRef.compareAndSet(0, e), 1)); assertThrows(IOException.class, () -> Erase.apply(TestUtils.throwingIOFunction(), 1)); } @Test void testCompare() { assertEquals(0, Erase.compare(String::compareTo, "A", "A")); assertEquals(-1, Erase.compare(String::compareTo, "A", "B")); assertEquals(1, Erase.compare(String::compareTo, "B", "A")); assertThrows(IOException.class, () -> Erase.compare(TestUtils.throwingIOComparator(), null, null)); } @Test void testGet() { assertEquals(0, Erase.get(() -> intRef.get())); assertThrows(IOException.class, () -> Erase.get(TestUtils.throwingIOSupplier())); } @Test void testRethrow() { assertThrows(IOException.class, () -> Erase.rethrow(new IOException())); } @Test void testRun() { Erase.run(() -> intRef.set(1)); assertEquals(1, intRef.get()); assertThrows(IOException.class, () -> Erase.run(TestUtils.throwingIORunnable())); } @Test void testTest() { assertTrue(Erase.test(e -> intRef.compareAndSet(0, e), 1)); assertThrows(IOException.class, () -> Erase.test(TestUtils.throwingIOPredicate(), 1)); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/function/IOBaseStreamTest.java0100644 0000000 0000000 00000031537 14603604450 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.function; 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 java.io.IOException; import java.nio.file.Path; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import java.util.stream.BaseStream; import java.util.stream.Stream; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Tests {@link IOBaseStream}. */ public class IOBaseStreamTest { /** * Implements IOBaseStream with generics. */ private static class IOBaseStreamFixture, B extends BaseStream> implements IOBaseStream { private final B baseStream; private IOBaseStreamFixture(final B baseStream) { this.baseStream = baseStream; } @Override public B unwrap() { return baseStream; } @SuppressWarnings("unchecked") // We are this here @Override public S wrap(final B delegate) { return delegate == baseStream ? (S) this : (S) new IOBaseStreamFixture(delegate); } } /** * Implements IOBaseStream with a concrete type. */ private static final class IOBaseStreamPathFixture> extends IOBaseStreamFixture, B> { private IOBaseStreamPathFixture(final B baseStream) { super(baseStream); } @Override public IOBaseStreamPathFixture wrap(final B delegate) { return delegate == unwrap() ? this : new IOBaseStreamPathFixture<>(delegate); } } private static final class MyRuntimeException extends RuntimeException { private static final long serialVersionUID = 1L; public MyRuntimeException(final String message) { super(message); } } /** Sanity check */ private BaseStream> baseStream; /** Generic version */ private IOBaseStreamFixture, ?> ioBaseStream; /** Concrete version */ private IOBaseStreamPathFixture> ioBaseStreamPath; /** Adapter version */ private IOStream ioBaseStreamAdapter; @BeforeEach public void beforeEach() { baseStream = createStreamOfPaths(); ioBaseStream = createIOBaseStream(); ioBaseStreamPath = createIOBaseStreamPath(); ioBaseStreamAdapter = createIOBaseStreamAdapter(); } private IOBaseStreamFixture> createIOBaseStream() { return new IOBaseStreamFixture<>(createStreamOfPaths()); } private IOStream createIOBaseStreamAdapter() { return IOStreamAdapter.adapt(createStreamOfPaths()); } private IOBaseStreamPathFixture> createIOBaseStreamPath() { return new IOBaseStreamPathFixture<>(createStreamOfPaths()); } private Stream createStreamOfPaths() { return Stream.of(TestConstants.ABS_PATH_A, TestConstants.ABS_PATH_B); } @Test @AfterEach public void testClose() { baseStream.close(); ioBaseStream.close(); ioBaseStreamPath.close(); ioBaseStream.asBaseStream().close(); ioBaseStreamPath.asBaseStream().close(); } @SuppressWarnings("resource") // @AfterEach @Test public void testIsParallel() { assertFalse(baseStream.isParallel()); assertFalse(ioBaseStream.isParallel()); assertFalse(ioBaseStream.asBaseStream().isParallel()); assertFalse(ioBaseStreamPath.asBaseStream().isParallel()); assertFalse(ioBaseStreamPath.isParallel()); } @SuppressWarnings("resource") // @AfterEach @Test public void testIteratorPathIO() throws IOException { final AtomicReference ref = new AtomicReference<>(); ioBaseStream.iterator().forEachRemaining(e -> ref.set(e.toRealPath())); assertEquals(TestConstants.ABS_PATH_B.toRealPath(), ref.get()); // ioBaseStreamPath.asBaseStream().iterator().forEachRemaining(e -> ref.set(e.getFileName())); assertEquals(TestConstants.ABS_PATH_B.getFileName(), ref.get()); } @SuppressWarnings("resource") // @AfterEach @Test public void testIteratorSimple() throws IOException { final AtomicInteger ref = new AtomicInteger(); baseStream.iterator().forEachRemaining(e -> ref.incrementAndGet()); assertEquals(2, ref.get()); ioBaseStream.iterator().forEachRemaining(e -> ref.incrementAndGet()); assertEquals(4, ref.get()); ioBaseStreamPath.asBaseStream().iterator().forEachRemaining(e -> ref.incrementAndGet()); assertEquals(6, ref.get()); } @SuppressWarnings("resource") @Test public void testOnClose() { // Stream testOnClose(baseStream); testOnClose(ioBaseStream.asBaseStream()); testOnClose(ioBaseStreamPath.asBaseStream()); } @SuppressWarnings("resource") private > void testOnClose(final BaseStream stream) { final AtomicReference refA = new AtomicReference<>(); final AtomicReference refB = new AtomicReference<>(); stream.onClose(() -> refA.set("A")); stream.onClose(() -> { throw new MyRuntimeException("B"); }); stream.onClose(() -> { throw new MyRuntimeException("C"); }); stream.onClose(() -> refB.set("D")); final MyRuntimeException e = assertThrows(MyRuntimeException.class, stream::close); assertEquals("A", refA.get()); assertEquals("D", refB.get()); assertEquals("B", e.getMessage()); final Throwable[] suppressed = e.getSuppressed(); assertNotNull(suppressed); assertEquals(1, suppressed.length); assertEquals("C", suppressed[0].getMessage()); } @SuppressWarnings("resource") @Test public void testParallel() throws IOException { final AtomicInteger ref = new AtomicInteger(); baseStream.parallel().iterator().forEachRemaining(e -> ref.incrementAndGet()); assertEquals(2, ref.get()); ioBaseStream.parallel().iterator().forEachRemaining(e -> ref.incrementAndGet()); assertEquals(4, ref.get()); final BaseStream parallel = ioBaseStreamPath.asBaseStream().parallel(); parallel.iterator().forEachRemaining(e -> ref.incrementAndGet()); assertEquals(6, ref.get()); assertTrue(parallel.isParallel()); } @SuppressWarnings("resource") // @AfterEach @Test public void testParallelParallel() { try (final IOBaseStream stream = createIOBaseStream()) { testParallelParallel(stream); } try (final IOBaseStream stream = createIOBaseStreamPath()) { testParallelParallel(stream); } try (final IOBaseStream stream = createIOBaseStream()) { testParallelParallel(stream); } try (final IOBaseStreamFixture> stream = createIOBaseStream()) { testParallelParallel(stream.asBaseStream()); } } @SuppressWarnings("resource") private void testParallelParallel(final BaseStream stream) { final BaseStream seq = stream.sequential(); assertFalse(seq.isParallel()); final BaseStream p1 = seq.parallel(); assertTrue(p1.isParallel()); final BaseStream p2 = p1.parallel(); assertTrue(p1.isParallel()); assertSame(p1, p2); } @SuppressWarnings("resource") private void testParallelParallel(final IOBaseStream stream) { final IOBaseStream seq = stream.sequential(); assertFalse(seq.isParallel()); final IOBaseStream p1 = seq.parallel(); assertTrue(p1.isParallel()); final IOBaseStream p2 = p1.parallel(); assertTrue(p1.isParallel()); assertSame(p1, p2); } @SuppressWarnings("resource") @Test public void testSequential() throws IOException { final AtomicInteger ref = new AtomicInteger(); baseStream.sequential().iterator().forEachRemaining(e -> ref.incrementAndGet()); assertEquals(2, ref.get()); ioBaseStream.sequential().iterator().forEachRemaining(e -> ref.incrementAndGet()); assertEquals(4, ref.get()); ioBaseStreamPath.asBaseStream().sequential().iterator().forEachRemaining(e -> ref.incrementAndGet()); assertEquals(6, ref.get()); } @SuppressWarnings("resource") // @AfterEach @Test public void testSequentialSequential() { try (final IOBaseStream stream = createIOBaseStream()) { testSequentialSequential(stream); } try (final IOBaseStream stream = createIOBaseStreamPath()) { testSequentialSequential(stream); } try (final IOBaseStream stream = createIOBaseStream()) { testSequentialSequential(stream.asBaseStream()); } } @SuppressWarnings("resource") private void testSequentialSequential(final BaseStream stream) { final BaseStream p = stream.parallel(); assertTrue(p.isParallel()); final BaseStream seq1 = p.sequential(); assertFalse(seq1.isParallel()); final BaseStream seq2 = seq1.sequential(); assertFalse(seq1.isParallel()); assertSame(seq1, seq2); } @SuppressWarnings("resource") private void testSequentialSequential(final IOBaseStream stream) { final IOBaseStream p = stream.parallel(); assertTrue(p.isParallel()); final IOBaseStream seq1 = p.sequential(); assertFalse(seq1.isParallel()); final IOBaseStream seq2 = seq1.sequential(); assertFalse(seq1.isParallel()); assertSame(seq1, seq2); } @SuppressWarnings("resource") // @AfterEach @Test public void testSpliterator() { final AtomicInteger ref = new AtomicInteger(); baseStream.spliterator().forEachRemaining(e -> ref.incrementAndGet()); assertEquals(2, ref.get()); ioBaseStream.spliterator().forEachRemaining(e -> ref.incrementAndGet()); assertEquals(4, ref.get()); ioBaseStreamPath.asBaseStream().spliterator().forEachRemaining(e -> ref.incrementAndGet()); assertEquals(6, ref.get()); } @SuppressWarnings("resource") @Test public void testUnordered() throws IOException { final AtomicInteger ref = new AtomicInteger(); baseStream.unordered().iterator().forEachRemaining(e -> ref.incrementAndGet()); assertEquals(2, ref.get()); ioBaseStream.unordered().iterator().forEachRemaining(e -> ref.incrementAndGet()); assertEquals(4, ref.get()); ioBaseStreamPath.asBaseStream().unordered().iterator().forEachRemaining(e -> ref.incrementAndGet()); assertEquals(6, ref.get()); } @SuppressWarnings("resource") @Test public void testUnwrap() { final AtomicInteger ref = new AtomicInteger(); baseStream.iterator().forEachRemaining(e -> ref.incrementAndGet()); assertEquals(2, ref.get()); ioBaseStream.unwrap().iterator().forEachRemaining(e -> ref.incrementAndGet()); assertEquals(4, ref.get()); ioBaseStreamPath.asBaseStream().iterator().forEachRemaining(e -> ref.incrementAndGet()); assertEquals(6, ref.get()); } @Test public void testWrap() { final Stream stream = createStreamOfPaths(); @SuppressWarnings("resource") final IOStream wrap = ioBaseStreamAdapter.wrap(stream); assertNotNull(wrap); assertEquals(stream, wrap.unwrap()); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/function/IOBiConsumerTest.java0100644 0000000 0000000 00000005014 14603604450 031416 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.IOException; import java.io.UncheckedIOException; import java.util.HashMap; import java.util.Map; import java.util.concurrent.atomic.AtomicReference; import org.junit.jupiter.api.Test; /** * Tests {@link IOBiConsumer}. */ public class IOBiConsumerTest { @Test public void testAccept() throws IOException { final AtomicReference ref = new AtomicReference<>(); final IOBiConsumer biConsumer = (s, i) -> ref.set(s + i); biConsumer.accept("A", 1); assertEquals("A1", ref.get()); } @Test public void testAndThen() throws IOException { final AtomicReference ref = new AtomicReference<>(); final IOBiConsumer biConsumer1 = (s, i) -> ref.set(s + i); final IOBiConsumer biConsumer2 = (s, i) -> ref.set(ref.get() + i + s); biConsumer1.andThen(biConsumer2).accept("B", 2); assertEquals("B22B", ref.get()); } @Test public void testAsBiConsumer() { final Map map = new HashMap<>(); map.put("a", 1); assertThrows(UncheckedIOException.class, () -> map.forEach(TestConstants.THROWING_IO_BI_CONSUMER.asBiConsumer())); final AtomicReference ref = new AtomicReference<>(); final IOBiConsumer consumer1 = (t, u) -> ref.set(t + u); map.forEach(consumer1.asBiConsumer()); assertEquals("a1", ref.get()); } @Test public void testNoopIOConsumer() throws IOException { IOBiConsumer.noop().accept(null, null); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/function/IOBiFunctionTest.java0100644 0000000 0000000 00000006313 14603604450 031413 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import java.nio.file.Files; import java.nio.file.LinkOption; import java.nio.file.Path; import java.util.HashMap; import java.util.Map; import org.apache.commons.io.file.PathUtils; import org.junit.jupiter.api.Test; /** * Tests {@link IOBiFunction}. */ public class IOBiFunctionTest { @SuppressWarnings("unused") private boolean not(final boolean value) throws IOException { return !value; } /** * Tests {@link IOBiFunction#andThen(IOFunction)}. * * @throws IOException thrown on test failure */ @Test public void testAndThenIOFunction() throws IOException { final IOBiFunction isDirectory = Files::isDirectory; final IOFunction not = this::not; assertTrue( isDirectory.apply(PathUtils.current(), PathUtils.EMPTY_LINK_OPTION_ARRAY)); final IOBiFunction andThen = isDirectory.andThen(not); assertFalse(andThen.apply(PathUtils.current(), PathUtils.EMPTY_LINK_OPTION_ARRAY)); } /** * Tests {@link IOBiFunction#apply(Object, Object)}. * * @throws IOException thrown on test failure */ @Test public void testApply() throws IOException { final IOBiFunction isDirectory = Files::isDirectory; assertTrue( isDirectory.apply(PathUtils.current(), PathUtils.EMPTY_LINK_OPTION_ARRAY)); } /** * Tests {@link IOBiFunction#apply(Object, Object)}. */ @Test public void testApplyThrowsException() { final IOBiFunction isDirectory = (t, u) -> { throw new IOException("Boom!"); }; assertThrows(IOException.class, () -> isDirectory.apply(PathUtils.current(), PathUtils.EMPTY_LINK_OPTION_ARRAY)); } @Test public void testAsBiFunction() { final Map map = new HashMap<>(); map.put("1", 0L); final IOBiFunction f = (t, u) -> Files.size(PathUtils.current()); map.computeIfPresent("1", f.asBiFunction()); assertNotEquals(0L, map.get("1")); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/function/IOBinaryOperatorStreamTest.java0100644 0000000 0000000 00000012701 14603604450 033465 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 static org.junit.jupiter.api.Assertions.fail; import java.io.IOException; import java.io.UncheckedIOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.function.BiFunction; import java.util.function.BinaryOperator; import java.util.stream.Stream; import org.apache.commons.io.file.PathUtils; import org.junit.jupiter.api.Test; /** * Tests {@link IOBinaryOperator}. */ public class IOBinaryOperatorStreamTest { private static final IOBinaryOperator MIN_BY_IO_BO = IOBinaryOperator.minBy(IOComparatorTest.REAL_PATH_COMP); private static final BinaryOperator MIN_BY_BO = MIN_BY_IO_BO.asBinaryOperator(); private static final IOBinaryOperator MAX_BY_IO_BO = IOBinaryOperator.maxBy(IOComparatorTest.REAL_PATH_COMP); private static final BinaryOperator MAX_BY_BO = MAX_BY_IO_BO.asBinaryOperator(); private static final IOBinaryOperator REAL_PATH_IO_BO = (t, u) -> t.toRealPath(); private static final BinaryOperator REAL_PATH_BO = REAL_PATH_IO_BO.asBinaryOperator(); @Test public void testAsBinaryOperator() { assertThrows(UncheckedIOException.class, () -> Stream.of(TestConstants.ABS_PATH_A, TestConstants.ABS_PATH_A).reduce(TestUtils.throwingIOBinaryOperator().asBinaryOperator()).get()); assertEquals(TestConstants.ABS_PATH_A, Stream.of(TestConstants.ABS_PATH_A, TestConstants.ABS_PATH_A).reduce(MAX_BY_BO).get()); assertEquals(TestConstants.ABS_PATH_A, Stream.of(TestConstants.ABS_PATH_A, TestConstants.ABS_PATH_A).reduce(MIN_BY_BO).get()); } /** */ @Test public void testMaxBy() { assertEquals(TestConstants.ABS_PATH_A, Stream.of(TestConstants.ABS_PATH_A, TestConstants.ABS_PATH_A).reduce(MAX_BY_BO).get()); // in-line lambda ok: final IOBinaryOperator binIoOp = IOBinaryOperator.maxBy((t, u) -> t.toRealPath().compareTo(u)); final BiFunction asBiFunction = binIoOp.asBiFunction(); final BinaryOperator asBinaryOperator = binIoOp.asBinaryOperator(); assertEquals(TestConstants.ABS_PATH_B, asBiFunction.apply(TestConstants.ABS_PATH_A, TestConstants.ABS_PATH_B)); assertEquals(TestConstants.ABS_PATH_B, asBinaryOperator.apply(TestConstants.ABS_PATH_A, TestConstants.ABS_PATH_B)); // assertEquals(TestConstants.ABS_PATH_A, Stream.of(TestConstants.ABS_PATH_A, TestConstants.ABS_PATH_A).reduce(asBinaryOperator).get()); assertEquals(TestConstants.ABS_PATH_B, Stream.of(TestConstants.ABS_PATH_A, TestConstants.ABS_PATH_B).reduce(asBinaryOperator).get()); assertEquals(TestConstants.ABS_PATH_B, Stream.of(TestConstants.ABS_PATH_B, TestConstants.ABS_PATH_A).reduce(asBinaryOperator).get()); } @Test public void testMinBy() { assertEquals(TestConstants.ABS_PATH_A, Stream.of(TestConstants.ABS_PATH_A, TestConstants.ABS_PATH_A).reduce(MIN_BY_BO).get()); // in-line lambda ok: final IOBinaryOperator binIoOp = IOBinaryOperator.minBy((t, u) -> t.toRealPath().compareTo(u)); final BiFunction asBiFunction = binIoOp.asBiFunction(); final BinaryOperator asBinaryOperator = binIoOp.asBinaryOperator(); assertEquals(TestConstants.ABS_PATH_A, asBiFunction.apply(TestConstants.ABS_PATH_A, TestConstants.ABS_PATH_B)); assertEquals(TestConstants.ABS_PATH_A, asBinaryOperator.apply(TestConstants.ABS_PATH_A, TestConstants.ABS_PATH_B)); // assertEquals(TestConstants.ABS_PATH_A, Stream.of(TestConstants.ABS_PATH_A, TestConstants.ABS_PATH_A).reduce(asBinaryOperator).get()); assertEquals(TestConstants.ABS_PATH_A, Stream.of(TestConstants.ABS_PATH_A, TestConstants.ABS_PATH_B).reduce(asBinaryOperator).get()); assertEquals(TestConstants.ABS_PATH_A, Stream.of(TestConstants.ABS_PATH_B, TestConstants.ABS_PATH_A).reduce(asBinaryOperator).get()); } @Test public void testReduce() throws IOException { // A silly example to pass in a IOBinaryOperator. final Path current = PathUtils.current(); final Path expected; try (Stream stream = Files.list(current)) { expected = stream.reduce((t, u) -> { try { return t.toRealPath(); } catch (final IOException e) { return fail(e); } }).get(); } try (Stream stream = Files.list(current)) { assertEquals(expected, stream.reduce(REAL_PATH_BO).get()); } } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/function/IOComparatorTest.java0100644 0000000 0000000 00000004652 14603604450 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.function; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.IOException; import java.io.UncheckedIOException; import java.nio.file.Files; import java.nio.file.Path; import org.junit.jupiter.api.Test; /** * Tests {@link IOComparator}. */ public class IOComparatorTest { /** {@link Files#size(Path)} throws IOException */ static final IOComparator PATH_SIZE_COMP = (final Path t, final Path u) -> Long.compare(Files.size(t), Files.size(u)); /** {@link Path#toRealPath(java.nio.file.LinkOption...)} throws IOException */ static final IOComparator REAL_PATH_COMP = (final Path t, final Path u) -> t.toRealPath().compareTo(u); @Test public void testAsComparator() { assertEquals(0, REAL_PATH_COMP.asComparator().compare(TestConstants.ABS_PATH_A, TestConstants.ABS_PATH_A)); assertThrows(UncheckedIOException.class, () -> TestConstants.THROWING_IO_COMPARATOR.asComparator().compare(TestConstants.ABS_PATH_A, TestConstants.ABS_PATH_B)); } @Test public void testCompareLong() throws IOException { assertEquals(0, REAL_PATH_COMP.compare(TestConstants.ABS_PATH_A, TestConstants.ABS_PATH_A)); } @Test public void testComparePath() throws IOException { assertEquals(0, PATH_SIZE_COMP.compare(TestConstants.ABS_PATH_A, TestConstants.ABS_PATH_A)); } @Test public void testThrowing() { assertThrows(IOException.class, () -> TestConstants.THROWING_IO_COMPARATOR.compare(TestConstants.ABS_PATH_A, TestConstants.ABS_PATH_B)); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/function/IOConsumerTest.java0100644 0000000 0000000 00000015164 14603604450 031152 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.Closeable; import java.io.IOException; import java.io.StringReader; import java.io.UncheckedIOException; import java.nio.file.Files; import java.util.Arrays; import java.util.Optional; import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Stream; import org.apache.commons.io.IOExceptionList; import org.apache.commons.io.IOUtils; import org.apache.commons.io.file.PathUtils; import org.apache.commons.io.test.ThrowOnCloseReader; import org.junit.jupiter.api.Test; /** * Tests {@link IOConsumer}. */ public class IOConsumerTest { @Test void testAccept() throws IOException { IOConsumer.noop().accept(null); IOConsumer.noop().accept("."); Uncheck.accept(Files::size, PathUtils.current()); // final AtomicReference ref = new AtomicReference<>(); final IOConsumer consumer = s -> ref.set(s + "1"); consumer.accept("A"); assertEquals("A1", ref.get()); } @Test void testAndThen() throws IOException { final AtomicReference ref = new AtomicReference<>(); final IOConsumer consumer1 = s -> ref.set(s + "1"); final IOConsumer consumer2 = s -> ref.set(ref.get() + "2" + s); consumer1.andThen(consumer2).accept("B"); assertEquals("B12B", ref.get()); } @Test public void testAsConsumer() { assertThrows(UncheckedIOException.class, () -> Optional.of("a").ifPresent(TestUtils.throwingIOConsumer().asConsumer())); final AtomicReference ref = new AtomicReference<>(); final IOConsumer consumer1 = s -> ref.set(s + "1"); Optional.of("a").ifPresent(consumer1.asConsumer()); assertEquals("a1", ref.get()); } @Test public void testForAllArrayOf1() throws IOException { IOConsumer.forAll(TestUtils.throwingIOConsumer(), (String[]) null); IOConsumer.forAll(null, (String[]) null); assertThrows(IOExceptionList.class, () -> IOConsumer.forAll(TestUtils.throwingIOConsumer(), "1")); // final AtomicReference ref = new AtomicReference<>("0"); final IOConsumer consumer1 = s -> ref.set(ref.get() + s); IOConsumer.forAll(consumer1, "1"); assertEquals("01", ref.get()); } @Test public void testForAllArrayOf2() throws IOException { IOConsumer.forAll(TestUtils.throwingIOConsumer(), (String[]) null); IOConsumer.forAll(null, (String[]) null); assertThrows(IOExceptionList.class, () -> IOConsumer.forAll(TestUtils.throwingIOConsumer(), "1", "2")); // final AtomicReference ref = new AtomicReference<>("0"); final IOConsumer consumer1 = s -> ref.set(ref.get() + s); IOConsumer.forAll(consumer1, "1", "2"); assertEquals("012", ref.get()); } @Test public void testForAllIterableOf1() throws IOException { IOConsumer.forAll(TestUtils.throwingIOConsumer(), (Iterable) null); IOConsumer.forAll(null, (Iterable) null); assertThrows(IOExceptionList.class, () -> IOConsumer.forAll(TestUtils.throwingIOConsumer(), Arrays.asList("1"))); final AtomicReference ref = new AtomicReference<>("0"); final IOConsumer consumer1 = s -> ref.set(ref.get() + s); IOConsumer.forAll(consumer1, Arrays.asList("1")); assertEquals("01", ref.get()); } @Test public void testForAllIterableOf2() throws IOException { IOConsumer.forAll(TestUtils.throwingIOConsumer(), (Iterable) null); IOConsumer.forAll(null, (Iterable) null); assertThrows(IOExceptionList.class, () -> IOConsumer.forAll(TestUtils.throwingIOConsumer(), Arrays.asList("1", "2"))); final AtomicReference ref = new AtomicReference<>("0"); final IOConsumer consumer1 = s -> ref.set(ref.get() + s); IOConsumer.forAll(consumer1, Arrays.asList("1", "2")); assertEquals("012", ref.get()); } @Test public void testForAllStreamOf1() throws IOException { IOConsumer.forAll(TestUtils.throwingIOConsumer(), (Stream) null); IOConsumer.forAll(null, (Stream) null); assertThrows(IOExceptionList.class, () -> IOConsumer.forAll(TestUtils.throwingIOConsumer(), Arrays.asList("1").stream())); final AtomicReference ref = new AtomicReference<>("0"); final IOConsumer consumer1 = s -> ref.set(ref.get() + s); IOConsumer.forAll(consumer1, Arrays.asList("1").stream()); assertEquals("01", ref.get()); } @Test public void testForAllStreamOf2() throws IOException { IOConsumer.forAll(TestUtils.throwingIOConsumer(), (Stream) null); IOConsumer.forAll(null, (Stream) null); assertThrows(IOExceptionList.class, () -> IOConsumer.forAll(TestUtils.throwingIOConsumer(), Arrays.asList("1", "2").stream())); final AtomicReference ref = new AtomicReference<>("0"); final IOConsumer consumer1 = s -> ref.set(ref.get() + s); IOConsumer.forAll(consumer1, Arrays.asList("1", "2").stream()); assertEquals("012", ref.get()); } @Test public void testNoop() { 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.16.1-src/src/test/java/org/apache/commons/io/function/IOFunctionTest.java0100644 0000000 0000000 00000015615 14603604450 031145 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.assertArrayEquals; 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.io.UncheckedIOException; import java.util.Optional; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; import org.apache.commons.lang3.ArrayUtils; import org.junit.jupiter.api.Test; /** * Tests {@link IOFunction}. */ public class IOFunctionTest { private static final 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 testApplyThrowsException() { final IOFunction throwException = function -> { throw new IOException("Boom!"); }; assertThrows(IOException.class, () -> throwException.apply(new ByteArrayInputStream(ArrayUtils.EMPTY_BYTE_ARRAY))); } @Test public void testAsFunction() { assertThrows(UncheckedIOException.class, () -> Optional.of("a").map(TestConstants.THROWING_IO_FUNCTION.asFunction()).get()); assertEquals("a", Optional.of("a").map(IOFunction.identity().asFunction()).get()); } @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 { assertEquals(IOFunction.identity(), IOFunction.identity()); final IOFunction identityFunction = IOFunction.identity(); final byte[] buf = {(byte) 0xa, (byte) 0xb, (byte) 0xc}; assertEquals(buf, identityFunction.apply(buf)); assertArrayEquals(buf, identityFunction.apply(buf)); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/function/IOIntStream.java0100644 0000000 0000000 00000002164 14603604450 030421 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.util.stream.IntStream; /** * Placeholder for future possible development and makes sure we can extend IOBaseStream cleanly with proper generics. */ interface IOIntStream extends IOBaseStream { // Placeholder for future possible development. } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/function/IOIntStreamAdapter.java0100644 0000000 0000000 00000002724 14603604450 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.function; import java.util.stream.IntStream; /** * Placeholder for future possible development and makes sure we can extend IOBaseStreamAdapter cleanly with proper * generics. */ final class IOIntStreamAdapter extends IOBaseStreamAdapter implements IOIntStream { static IOIntStream adapt(final IntStream stream) { return new IOIntStreamAdapter(stream); } private IOIntStreamAdapter(final IntStream stream) { super(stream); } @Override public IOIntStream wrap(final IntStream delegate) { return unwrap() == delegate ? this : IOIntStreamAdapter.adapt(delegate); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/function/IOIntSupplierTest.java0100644 0000000 0000000 00000004721 14603604450 031632 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.IOException; import java.io.UncheckedIOException; import java.util.concurrent.atomic.AtomicInteger; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Tests {@link IOIntSupplier}. */ public class IOIntSupplierTest { private AtomicInteger atomicInt; private int getThrowsIO(final IOIntSupplier supplier) throws IOException { return supplier.getAsInt(); } private int getThrowsNone(final IOIntSupplier supplier) { return supplier.asIntSupplier().getAsInt(); } @BeforeEach public void initEach() { atomicInt = new AtomicInteger(); } @Test public void testAsSupplier() { assertThrows(UncheckedIOException.class, () -> TestConstants.THROWING_IO_INT_SUPPLIER.asIntSupplier().getAsInt()); assertEquals(1, getThrowsNone(() -> TestUtils.compareAndSetThrowsIO(atomicInt, 1))); assertEquals(1, atomicInt.get()); assertNotEquals(TestConstants.THROWING_IO_INT_SUPPLIER.asIntSupplier(), TestConstants.THROWING_IO_INT_SUPPLIER.asIntSupplier()); } @Test public void testGet() throws IOException { assertThrows(IOException.class, () -> TestConstants.THROWING_IO_INT_SUPPLIER.getAsInt()); assertThrows(IOException.class, () -> { throw new IOException(); }); assertEquals(1, getThrowsIO(() -> TestUtils.compareAndSetThrowsIO(atomicInt, 1))); assertEquals(1, atomicInt.get()); } }commons-io-2.16.1-src/src/test/java/org/apache/commons/io/function/IOIteratorAdapterTest.java0100644 0000000 0000000 00000006143 14603604450 032446 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.apache.commons.lang3.JavaVersion; import org.apache.commons.lang3.SystemUtils; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Tests {@code IOIteratorAdapter}. */ public class IOIteratorAdapterTest { private IOIteratorAdapter iterator; @BeforeEach public void beforeEach() { iterator = IOIteratorAdapter.adapt(newPathList().iterator()); } private List newPathList() { return Arrays.asList(TestConstants.ABS_PATH_A, TestConstants.ABS_PATH_B); } @Test public void testAdapt() throws IOException { assertEquals(TestConstants.ABS_PATH_A, iterator.next()); } @Test public void testAsIterator() { assertEquals(TestConstants.ABS_PATH_A, iterator.asIterator().next()); } @Test public void testForEachRemaining() throws IOException { final List list = new ArrayList<>(); iterator.forEachRemaining(p -> list.add(p.toRealPath())); assertFalse(iterator.hasNext()); assertEquals(newPathList(), list); } @Test public void testHasNext() throws IOException { assertTrue(iterator.hasNext()); iterator.forEachRemaining(Path::toRealPath); assertFalse(iterator.hasNext()); } @Test public void testNext() throws IOException { assertEquals(TestConstants.ABS_PATH_A, iterator.next()); } @Test public void testRemove() throws IOException { final Class exClass = SystemUtils.isJavaVersionAtMost(JavaVersion.JAVA_1_8) ? IllegalStateException.class : UnsupportedOperationException.class; assertThrows(exClass, iterator::remove); assertThrows(exClass, iterator::remove); iterator.next(); assertThrows(UnsupportedOperationException.class, iterator::remove); assertThrows(UnsupportedOperationException.class, iterator::remove); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/function/IOIteratorTest.java0100644 0000000 0000000 00000006420 14603604450 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.function; 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.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import org.apache.commons.lang3.JavaVersion; import org.apache.commons.lang3.SystemUtils; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Tests {@link IOIterator}. */ public class IOIteratorTest { private IOIterator iterator; @BeforeEach public void beforeEach() { iterator = IOIterator.adapt(newPathList().iterator()); } private List newPathList() { return Arrays.asList(TestConstants.ABS_PATH_A, TestConstants.ABS_PATH_B); } @Test public void testAdapt() throws IOException { assertEquals(TestConstants.ABS_PATH_A, iterator.next()); } @Test public void testAsIterator() { final Iterator asIterator = iterator.asIterator(); assertTrue(asIterator.hasNext()); assertEquals(TestConstants.ABS_PATH_A, asIterator.next()); assertThrows(UnsupportedOperationException.class, asIterator::remove); } @Test public void testForEachRemaining() throws IOException { final List list = new ArrayList<>(); iterator.forEachRemaining(p -> list.add(p.toRealPath())); assertFalse(iterator.hasNext()); assertEquals(newPathList(), list); } @Test public void testHasNext() throws IOException { assertTrue(iterator.hasNext()); iterator.forEachRemaining(Path::toRealPath); assertFalse(iterator.hasNext()); } @Test public void testNext() throws IOException { assertEquals(TestConstants.ABS_PATH_A, iterator.next()); } @Test public void testRemove() throws IOException { final Class exClass = SystemUtils.isJavaVersionAtMost(JavaVersion.JAVA_1_8) ? IllegalStateException.class : UnsupportedOperationException.class; assertThrows(exClass, iterator::remove); assertThrows(exClass, iterator::remove); iterator.next(); assertThrows(UnsupportedOperationException.class, iterator::remove); assertThrows(UnsupportedOperationException.class, iterator::remove); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/function/IOLongSupplierTest.java0100644 0000000 0000000 00000004726 14603604450 032004 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.IOException; import java.io.UncheckedIOException; import java.util.concurrent.atomic.AtomicLong; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Tests {@link IOLongSupplier}. */ public class IOLongSupplierTest { private AtomicLong atomicLong; private long getThrowsIO(final IOLongSupplier supplier) throws IOException { return supplier.getAsLong(); } private long getThrowsNone(final IOLongSupplier supplier) { return supplier.asSupplier().getAsLong(); } @BeforeEach public void initEach() { atomicLong = new AtomicLong(); } @Test public void testAsSupplier() { assertThrows(UncheckedIOException.class, () -> TestConstants.THROWING_IO_LONG_SUPPLIER.asSupplier().getAsLong()); assertEquals(1L, getThrowsNone(() -> TestUtils.compareAndSetThrowsIO(atomicLong, 1L))); assertEquals(1L, atomicLong.get()); assertNotEquals(TestConstants.THROWING_IO_LONG_SUPPLIER.asSupplier(), TestConstants.THROWING_IO_LONG_SUPPLIER.asSupplier()); } @Test public void testGet() throws IOException { assertThrows(IOException.class, () -> TestConstants.THROWING_IO_LONG_SUPPLIER.getAsLong()); assertThrows(IOException.class, () -> { throw new IOException(); }); assertEquals(1L, getThrowsIO(() -> TestUtils.compareAndSetThrowsIO(atomicLong, 1L))); assertEquals(1L, atomicLong.get()); } }commons-io-2.16.1-src/src/test/java/org/apache/commons/io/function/IOPredicateTest.java0100644 0000000 0000000 00000015163 14603604450 031256 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.assertFalse; 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 java.io.IOException; import java.io.UncheckedIOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import java.util.function.Predicate; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.function.Executable; /** * Tests {@link IOPredicate}. */ public class IOPredicateTest { /** Files::isHidden throws IOException. */ private static final IOPredicate IS_HIDDEN = Files::isHidden; private static final Path PATH_FIXTURE = Paths.get("src/test/resources/org/apache/commons/io/abitmorethan16k.txt"); private static final Object THROWING_EQUALS = new Object() { @Override public boolean equals(final Object obj) { throw Erase.rethrow(new IOException("Expected")); } }; private static final Predicate THROWING_UNCHECKED_PREDICATE = TestConstants.THROWING_IO_PREDICATE.asPredicate(); private void assertThrowsChecked(final Executable executable) { assertThrows(IOException.class, executable); } private void assertThrowsUnchecked(final Executable executable) { assertThrows(UncheckedIOException.class, executable); } @Test public void testAndChecked() throws IOException { assertFalse(IS_HIDDEN.and(IS_HIDDEN).test(PATH_FIXTURE)); assertTrue(IOPredicate.alwaysTrue().and(IOPredicate.alwaysTrue()).test(PATH_FIXTURE)); assertFalse(IOPredicate.alwaysFalse().and(IOPredicate.alwaysTrue()).test(PATH_FIXTURE)); assertFalse(IOPredicate.alwaysTrue().and(IOPredicate.alwaysFalse()).test(PATH_FIXTURE)); assertFalse(IOPredicate.alwaysFalse().and(IOPredicate.alwaysFalse()).test(PATH_FIXTURE)); } @Test public void testAndUnchecked() { assertThrowsUnchecked(() -> THROWING_UNCHECKED_PREDICATE.and(THROWING_UNCHECKED_PREDICATE).test(PATH_FIXTURE)); } @Test public void testAsPredicate() throws IOException { new ArrayList<>().removeIf(THROWING_UNCHECKED_PREDICATE); final List list = new ArrayList<>(); list.add("A"); list.add("B"); list.removeIf(Predicate.isEqual("A")); assertFalse(list.contains("A")); list.removeIf(IOPredicate.isEqual("B").asPredicate()); assertFalse(list.contains("B")); assertFalse(IS_HIDDEN.test(PATH_FIXTURE)); } @Test public void testFalse() throws IOException { assertFalse(Constants.IO_PREDICATE_FALSE.test("A")); // Make sure we keep the argument type final IOPredicate alwaysFalse = IOPredicate.alwaysFalse(); assertFalse(alwaysFalse.test("A")); assertEquals(IOPredicate.alwaysFalse(), IOPredicate.alwaysFalse()); assertSame(IOPredicate.alwaysFalse(), IOPredicate.alwaysFalse()); } @Test public void testIsEqualChecked() throws IOException { assertThrowsChecked(() -> IOPredicate.isEqual(THROWING_EQUALS).test("B")); assertFalse(IOPredicate.isEqual(null).test("A")); assertTrue(IOPredicate.isEqual("B").test("B")); assertFalse(IOPredicate.isEqual("A").test("B")); assertFalse(IOPredicate.isEqual("B").test("A")); } @Test public void testIsEqualUnchecked() { assertThrowsUnchecked(() -> IOPredicate.isEqual(THROWING_EQUALS).asPredicate().test("B")); assertFalse(IOPredicate.isEqual(null).asPredicate().test("A")); assertTrue(IOPredicate.isEqual("B").asPredicate().test("B")); assertFalse(IOPredicate.isEqual("A").asPredicate().test("B")); assertFalse(IOPredicate.isEqual("B").asPredicate().test("A")); } @Test public void testNegateChecked() throws IOException { assertTrue(IS_HIDDEN.negate().test(PATH_FIXTURE)); assertFalse(IOPredicate.alwaysTrue().negate().test(PATH_FIXTURE)); } @Test public void testNegateUnchecked() { assertTrue(IS_HIDDEN.negate().asPredicate().test(PATH_FIXTURE)); assertTrue(IS_HIDDEN.asPredicate().negate().test(PATH_FIXTURE)); assertThrowsUnchecked(() -> THROWING_UNCHECKED_PREDICATE.negate().test(PATH_FIXTURE)); } @Test public void testOrChecked() throws IOException { assertFalse(IS_HIDDEN.or(IS_HIDDEN).test(PATH_FIXTURE)); assertTrue(IOPredicate.alwaysTrue().or(IOPredicate.alwaysFalse()).test(PATH_FIXTURE)); assertTrue(IOPredicate.alwaysFalse().or(IOPredicate.alwaysTrue()).test(PATH_FIXTURE)); } @Test public void testOrUnchecked() { assertFalse(IS_HIDDEN.asPredicate().or(e -> false).test(PATH_FIXTURE)); assertThrowsUnchecked(() -> THROWING_UNCHECKED_PREDICATE.or(THROWING_UNCHECKED_PREDICATE).test(PATH_FIXTURE)); } @Test public void testTestChecked() throws IOException { assertThrowsChecked(() -> TestConstants.THROWING_IO_PREDICATE.test(null)); assertTrue(Constants.IO_PREDICATE_TRUE.test("A")); } @Test public void testTestUnchecked() { assertThrowsUnchecked(() -> THROWING_UNCHECKED_PREDICATE.test(null)); assertTrue(Constants.IO_PREDICATE_TRUE.asPredicate().test("A")); } @Test public void testTrue() throws IOException { assertTrue(Constants.IO_PREDICATE_TRUE.test("A")); // Make sure we keep the argument type final IOPredicate alwaysTrue = IOPredicate.alwaysTrue(); assertTrue(alwaysTrue.test("A")); assertEquals(IOPredicate.alwaysTrue(), IOPredicate.alwaysTrue()); assertSame(IOPredicate.alwaysTrue(), IOPredicate.alwaysTrue()); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/function/IOQuadFunctionTest.java0100644 0000000 0000000 00000007123 14603604450 031753 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 java.io.IOException; import java.math.BigInteger; import java.util.concurrent.atomic.AtomicReference; import org.junit.jupiter.api.Test; /** * Tests {@link IOQuadFunction}. */ public class IOQuadFunctionTest { /** * Tests {@link IOQuadFunction#apply(Object, Object, Object, Object)}. * * @throws IOException thrown on test failure */ @Test public void testAccept() throws IOException { final AtomicReference ref1 = new AtomicReference<>(); final AtomicReference ref2 = new AtomicReference<>(); final AtomicReference ref3 = new AtomicReference<>(); final AtomicReference ref4 = new AtomicReference<>(); final IOQuadFunction, AtomicReference, AtomicReference, AtomicReference, String> quad = (t, u, v, w) -> { ref1.set(Byte.valueOf("1")); ref2.set(Short.valueOf((short) 1)); ref3.set("z"); ref4.set(Long.valueOf(2)); return "ABCD"; }; assertEquals("ABCD", quad.apply(ref1, ref2, ref3, ref4)); assertEquals(Byte.valueOf("1"), ref1.get()); assertEquals(Short.valueOf((short) 1), ref2.get()); assertEquals("z", ref3.get()); assertEquals(Long.valueOf(2), ref4.get()); } /** * Tests {@link IOTriFunction#andThen(IOFunction)}. * * @throws IOException thrown on test failure */ @Test public void testAndThenIOFunction() throws IOException { final AtomicReference ref1 = new AtomicReference<>(); final AtomicReference ref2 = new AtomicReference<>(); final AtomicReference ref3 = new AtomicReference<>(); final AtomicReference ref4 = new AtomicReference<>(); final IOQuadFunction, AtomicReference, AtomicReference, AtomicReference, String> quad = (t, u, v, w) -> { ref1.set(Byte.valueOf("1")); ref2.set(Short.valueOf((short) 1)); ref3.set("z"); ref4.set(Long.valueOf(2)); return "9"; }; final IOFunction after = t -> { ref1.set(Byte.valueOf("2")); ref2.set(Short.valueOf((short) 2)); ref3.set("zz"); ref4.set(Long.valueOf(3)); return BigInteger.valueOf(Long.parseLong(t)).add(BigInteger.ONE); }; assertEquals(BigInteger.TEN, quad.andThen(after).apply(ref1, ref2, ref3, ref4)); assertEquals(Byte.valueOf("2"), ref1.get()); assertEquals(Short.valueOf((short) 2), ref2.get()); assertEquals("zz", ref3.get()); assertEquals(Long.valueOf(3), ref4.get()); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/function/IORunnableTest.java0100644 0000000 0000000 00000004425 14603604450 031123 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import java.io.UncheckedIOException; import java.nio.file.Files; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicReference; import org.apache.commons.io.file.PathUtils; import org.junit.jupiter.api.Test; /** * Tests {@link IORunnable}. */ public class IORunnableTest { /** * Tests {@link IORunnable#run()}. * * @throws IOException thrown on test failure */ @Test public void testAccept() throws IOException { final AtomicReference ref = new AtomicReference<>(); final IORunnable runnable = () -> ref.set("A1"); runnable.run(); assertEquals("A1", ref.get()); } @Test public void testAsRunnable() throws Exception { assertThrows(UncheckedIOException.class, () -> Executors.callable(TestConstants.THROWING_IO_RUNNABLE.asRunnable()).call()); final IORunnable runnable = () -> Files.size(PathUtils.current()); assertNull(Executors.callable(runnable.asRunnable()).call()); } @SuppressWarnings("cast") @Test public void testNoop() throws IOException { assertTrue(IORunnable.noop() instanceof IORunnable); IORunnable.noop().run(); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/function/IOSpliteratorTest.java0100644 0000000 0000000 00000012461 14603604450 031664 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.assertNotNull; 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 java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Spliterator; import java.util.TreeSet; import java.util.concurrent.atomic.AtomicReference; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Tests {@link IOSpliterator}. */ public class IOSpliteratorTest { private IOSpliterator spliterator; @BeforeEach public void beforeEach() { spliterator = IOSpliterator.adapt(newPathList().spliterator()); } private List newPathList() { return Arrays.asList(TestConstants.ABS_PATH_A, TestConstants.ABS_PATH_B); } @Test public void testAdapt() { spliterator = IOSpliterator.adapt(newPathList().spliterator()); assertEquals(2, spliterator.estimateSize()); } @Test public void testAsSpliterator() { assertEquals(2, spliterator.estimateSize()); assertEquals(2, spliterator.asSpliterator().estimateSize()); } @Test public void testCharacteristics() { assertEquals(spliterator.unwrap().characteristics(), spliterator.characteristics()); assertEquals(spliterator.unwrap().characteristics(), spliterator.asSpliterator().characteristics()); } @Test public void testEstimateSize() { assertEquals(2, spliterator.estimateSize()); assertEquals(spliterator.unwrap().estimateSize(), spliterator.estimateSize()); assertEquals(spliterator.unwrap().estimateSize(), spliterator.asSpliterator().estimateSize()); } @Test public void testForEachRemaining() { final List list = new ArrayList<>(); spliterator.forEachRemaining(list::add); assertEquals(2, list.size()); assertEquals(newPathList(), list); } @Test public void testForEachRemainingAsSpliterator() { final List list = new ArrayList<>(); spliterator.asSpliterator().forEachRemaining(list::add); assertEquals(2, list.size()); assertEquals(newPathList(), list); } @Test public void testGetComparator() { if (spliterator.hasCharacteristics(Spliterator.SORTED)) { assertEquals(spliterator.unwrap().getComparator(), spliterator.getComparator()); assertEquals(spliterator.unwrap().getComparator(), spliterator.asSpliterator().getComparator()); } else { assertThrows(IllegalStateException.class, () -> spliterator.unwrap().getComparator()); assertThrows(IllegalStateException.class, () -> spliterator.asSpliterator().getComparator()); } final IOSpliterator adapted = IOSpliterator.adapt(new TreeSet<>(newPathList()).stream().sorted().spliterator()); final IOComparator comparator = adapted.getComparator(); assertNull(comparator); } @Test public void testGetExactSizeIfKnown() { assertEquals(2, spliterator.getExactSizeIfKnown()); assertEquals(spliterator.unwrap().getExactSizeIfKnown(), spliterator.getExactSizeIfKnown()); assertEquals(spliterator.unwrap().getExactSizeIfKnown(), spliterator.asSpliterator().getExactSizeIfKnown()); } @Test public void testHasCharacteristics() { assertTrue( spliterator.hasCharacteristics(spliterator.characteristics())); assertEquals(spliterator.unwrap().hasCharacteristics(spliterator.unwrap().characteristics()), spliterator.hasCharacteristics(spliterator.characteristics())); assertEquals(spliterator.unwrap().hasCharacteristics(spliterator.unwrap().characteristics()), spliterator.asSpliterator().hasCharacteristics(spliterator.asSpliterator().characteristics())); } @Test public void testTryAdvance() { final AtomicReference ref = new AtomicReference<>(); assertTrue(spliterator.tryAdvance(ref::set)); assertEquals(TestConstants.ABS_PATH_A, ref.get()); } @Test public void testTrySplit() { final IOSpliterator trySplit = spliterator.trySplit(); assertNotNull(trySplit); assertTrue(spliterator.getExactSizeIfKnown() > 0); } @Test public void testUnwrap() { assertNotNull(spliterator.unwrap()); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/function/IOStreamTest.java0100644 0000000 0000000 00000065074 14603604450 030617 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.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.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import java.util.Arrays; import java.util.Collections; import java.util.NoSuchElementException; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Collectors; import java.util.stream.DoubleStream; import java.util.stream.IntStream; import java.util.stream.LongStream; import java.util.stream.Stream; import org.apache.commons.lang3.JavaVersion; import org.apache.commons.lang3.SystemUtils; import org.junit.jupiter.api.Test; /** * Tests {@link IOStream}. */ public class IOStreamTest { private static final boolean AT_LEAST_JAVA_11 = SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_11); private static final boolean AT_LEAST_JAVA_17 = SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_17); private void compareAndSetIO(final AtomicReference ref, final String expected, final String update) throws IOException { TestUtils.compareAndSetThrowsIO(ref, expected, update); } private void compareAndSetRE(final AtomicReference ref, final String expected, final String update) { TestUtils.compareAndSetThrowsRE(ref, expected, update); } private void ioExceptionOnNull(final Object test) throws IOException { if (test == null) { throw new IOException("Unexpected"); } } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testAdapt() { assertEquals(0, IOStream.adapt((Stream) null).count()); assertEquals(0, IOStream.adapt(Stream.empty()).count()); assertEquals(1, IOStream.adapt(Stream.of("A")).count()); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testAllMatch() throws IOException { assertThrows(IOException.class, () -> IOStream.of("A", "B").allMatch(TestConstants.THROWING_IO_PREDICATE)); assertTrue(IOStream.of("A", "B").allMatch(IOPredicate.alwaysTrue())); assertFalse(IOStream.of("A", "B").allMatch(IOPredicate.alwaysFalse())); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testAnyMatch() throws IOException { assertThrows(IOException.class, () -> IOStream.of("A", "B").anyMatch(TestConstants.THROWING_IO_PREDICATE)); assertTrue(IOStream.of("A", "B").anyMatch(IOPredicate.alwaysTrue())); assertFalse(IOStream.of("A", "B").anyMatch(IOPredicate.alwaysFalse())); } @Test public void testClose() { IOStream.of("A", "B").close(); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testCollectCollectorOfQsuperTAR() { // TODO IOCollector? IOStream.of("A", "B").collect(Collectors.toList()); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testCollectSupplierOfRBiConsumerOfRQsuperTBiConsumerOfRR() throws IOException { // TODO Need an IOCollector? IOStream.of("A", "B").collect(() -> "A", (t, u) -> { }, (t, u) -> { }); assertEquals("AB", Stream.of("A", "B").collect(StringBuilder::new, StringBuilder::append, StringBuilder::append).toString()); assertEquals("AB", IOStream.of("A", "B").collect(StringBuilder::new, StringBuilder::append, StringBuilder::append).toString()); // Exceptions assertThrows(IOException.class, () -> IOStream.of("A", "B").collect(TestUtils.throwingIOSupplier(), (t, u) -> { }, (t, u) -> { })); assertThrows(IOException.class, () -> IOStream.of("A", "B").collect(() -> "A", TestUtils.throwingIOBiConsumer(), (t, u) -> { })); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testCount() { assertEquals(0, IOStream.of().count()); assertEquals(1, IOStream.of("A").count()); assertEquals(2, IOStream.of("A", "B").count()); assertEquals(3, IOStream.of("A", "B", "C").count()); assertEquals(3, IOStream.of("A", "A", "A").count()); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testDistinct() { assertEquals(0, IOStream.of().distinct().count()); assertEquals(1, IOStream.of("A").distinct().count()); assertEquals(2, IOStream.of("A", "B").distinct().count()); assertEquals(3, IOStream.of("A", "B", "C").distinct().count()); assertEquals(1, IOStream.of("A", "A", "A").distinct().count()); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testEmpty() throws IOException { assertEquals(0, Stream.empty().count()); assertEquals(0, IOStream.empty().count()); IOStream.empty().forEach(TestUtils.throwingIOConsumer()); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testFilter() throws IOException { IOStream.of("A").filter(TestConstants.THROWING_IO_PREDICATE); // compile vs type assertThrows(IOException.class, () -> IOStream.of("A").filter(TestConstants.THROWING_IO_PREDICATE).count()); // compile vs inline lambda assertThrows(IOException.class, () -> IOStream.of("A").filter(e -> { throw new IOException("Failure"); }).count()); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testFindAny() throws IOException { // compile vs type assertThrows(IOException.class, () -> IOStream.of("A").filter(TestConstants.THROWING_IO_PREDICATE).findAny()); // compile vs inline lambda assertThrows(IOException.class, () -> IOStream.of("A").filter(e -> { throw new IOException("Failure"); }).findAny()); assertTrue(IOStream.of("A", "B").filter(IOPredicate.alwaysTrue()).findAny().isPresent()); assertFalse(IOStream.of("A", "B").filter(IOPredicate.alwaysFalse()).findAny().isPresent()); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testFindFirst() throws IOException { // compile vs type assertThrows(IOException.class, () -> IOStream.of("A").filter(TestConstants.THROWING_IO_PREDICATE).findFirst()); // compile vs inline lambda assertThrows(IOException.class, () -> IOStream.of("A").filter(e -> { throw new IOException("Failure"); }).findAny()); assertTrue(IOStream.of("A", "B").filter(IOPredicate.alwaysTrue()).findFirst().isPresent()); assertFalse(IOStream.of("A", "B").filter(IOPredicate.alwaysFalse()).findFirst().isPresent()); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testFlatMap() throws IOException { assertEquals(Arrays.asList("A", "B", "C", "D"), IOStream.of(IOStream.of("A", "B"), IOStream.of("C", "D")).flatMap(IOFunction.identity()).collect(Collectors.toList())); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testFlatMapToDouble() throws IOException { assertEquals('A' + 'B', IOStream.of("A", "B").flatMapToDouble(e -> DoubleStream.of(e.charAt(0))).sum()); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testFlatMapToInt() throws IOException { assertEquals('A' + 'B', IOStream.of("A", "B").flatMapToInt(e -> IntStream.of(e.charAt(0))).sum()); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testFlatMapToLong() throws IOException { assertEquals('A' + 'B', IOStream.of("A", "B").flatMapToLong(e -> LongStream.of(e.charAt(0))).sum()); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testForaAllIOConsumer() throws IOException { // compile vs type assertThrows(IOException.class, () -> IOStream.of("A").forAll(TestUtils.throwingIOConsumer())); // compile vs inline assertThrows(IOException.class, () -> IOStream.of("A").forAll(e -> { throw new IOException("Failure"); })); assertThrows(IOException.class, () -> IOStream.of("A", "B").forAll(TestUtils.throwingIOConsumer())); final StringBuilder sb = new StringBuilder(); IOStream.of("A", "B").forAll(sb::append); assertEquals("AB", sb.toString()); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testForaAllIOConsumerBiFunction() throws IOException { // compile vs type assertThrows(IOException.class, () -> IOStream.of("A").forAll(TestUtils.throwingIOConsumer(), (i, e) -> e)); // compile vs inline assertThrows(IOException.class, () -> IOStream.of("A").forAll(e -> { throw new IOException("Failure"); }, (i, e) -> e)); assertThrows(IOException.class, () -> IOStream.of("A", "B").forAll(TestUtils.throwingIOConsumer(), (i, e) -> e)); final StringBuilder sb = new StringBuilder(); IOStream.of("A", "B").forAll(sb::append, (i, e) -> e); assertEquals("AB", sb.toString()); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testForaAllIOConsumerBiFunctionNull() throws IOException { // compile vs type assertDoesNotThrow(() -> IOStream.of("A").forAll(TestUtils.throwingIOConsumer(), null)); // compile vs inline assertDoesNotThrow(() -> IOStream.of("A").forAll(e -> { throw new IOException("Failure"); }, null)); assertDoesNotThrow(() -> IOStream.of("A", "B").forAll(TestUtils.throwingIOConsumer(), null)); final StringBuilder sb = new StringBuilder(); IOStream.of("A", "B").forAll(sb::append, null); assertEquals("AB", sb.toString()); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testForEachIOConsumerOfQsuperT() throws IOException { // compile vs type assertThrows(IOException.class, () -> IOStream.of("A").forEach(TestUtils.throwingIOConsumer())); // compile vs inline assertThrows(IOException.class, () -> IOStream.of("A").forEach(e -> { throw new IOException("Failure"); })); assertThrows(IOException.class, () -> IOStream.of("A", "B").forEach(TestUtils.throwingIOConsumer())); final StringBuilder sb = new StringBuilder(); IOStream.of("A", "B").forEachOrdered(sb::append); assertEquals("AB", sb.toString()); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testForEachOrdered() throws IOException { // compile vs type assertThrows(IOException.class, () -> IOStream.of("A").forEach(TestUtils.throwingIOConsumer())); // compile vs inline assertThrows(IOException.class, () -> IOStream.of("A").forEach(e -> { throw new IOException("Failure"); })); assertThrows(IOException.class, () -> IOStream.of("A", "B").forEach(TestUtils.throwingIOConsumer())); final StringBuilder sb = new StringBuilder(); IOStream.of("A", "B").forEachOrdered(sb::append); assertEquals("AB", sb.toString()); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testIsParallel() { assertFalse(IOStream.of("A", "B").isParallel()); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testIterateException() throws IOException { final IOStream stream = IOStream.iterate(1L, TestUtils.throwingIOUnaryOperator()); final IOIterator iterator = stream.iterator(); assertEquals(1L, iterator.next()); assertThrows(NoSuchElementException.class, () -> iterator.next()); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testIterateLong() throws IOException { final IOStream stream = IOStream.iterate(1L, i -> i + 1); final IOIterator iterator = stream.iterator(); assertEquals(1L, iterator.next()); assertEquals(2L, iterator.next()); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testIterator() throws IOException { final AtomicInteger ref = new AtomicInteger(); IOStream.of("A", "B").iterator().forEachRemaining(e -> ref.incrementAndGet()); assertEquals(2, ref.get()); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testLimit() { assertEquals(1, IOStream.of("A", "B").limit(1).count()); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testMap() throws IOException { assertEquals(Arrays.asList("AC", "BC"), IOStream.of("A", "B").map(e -> e + "C").collect(Collectors.toList())); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testMapToDouble() { assertArrayEquals(new double[] { Double.parseDouble("1"), Double.parseDouble("2") }, IOStream.of("1", "2").mapToDouble(Double::parseDouble).toArray()); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testMapToInt() { assertArrayEquals(new int[] { 1, 2 }, IOStream.of("1", "2").mapToInt(Integer::parseInt).toArray()); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testMapToLong() { assertArrayEquals(new long[] { 1L, 2L }, IOStream.of("1", "2").mapToLong(Long::parseLong).toArray()); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testMax() throws IOException { assertEquals("B", IOStream.of("A", "B").max(String::compareTo).get()); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testMin() throws IOException { assertEquals("A", IOStream.of("A", "B").min(String::compareTo).get()); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testNoneMatch() throws IOException { assertThrows(IOException.class, () -> IOStream.of("A", "B").noneMatch(TestConstants.THROWING_IO_PREDICATE)); assertFalse(IOStream.of("A", "B").noneMatch(IOPredicate.alwaysTrue())); assertTrue(IOStream.of("A", "B").noneMatch(IOPredicate.alwaysFalse())); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testOfArray() { assertEquals(0, IOStream.of((String[]) null).count()); assertEquals(0, IOStream.of().count()); assertEquals(2, IOStream.of("A", "B").count()); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testOfIterable() { assertEquals(0, IOStream.of((Iterable) null).count()); assertEquals(0, IOStream.of(Collections.emptyList()).count()); assertEquals(0, IOStream.of(Collections.emptySet()).count()); assertEquals(0, IOStream.of(Collections.emptySortedSet()).count()); assertEquals(1, IOStream.of(Arrays.asList("a")).count()); assertEquals(2, IOStream.of(Arrays.asList("a", "b")).count()); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testOfOne() { assertEquals(1, IOStream.of("A").count()); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testOnClose() throws IOException { assertThrows(IOException.class, () -> IOStream.of("A").onClose(TestConstants.THROWING_IO_RUNNABLE).close()); final AtomicReference ref = new AtomicReference<>(); IOStream.of("A").onClose(() -> compareAndSetIO(ref, null, "new1")).close(); assertEquals("new1", ref.get()); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testOnCloseMultipleHandlers() { // final AtomicReference ref = new AtomicReference<>(); // Sanity check ref.set(null); final RuntimeException thrownRE = assertThrows(RuntimeException.class, () -> { // @formatter:off final Stream stream = Stream.of("A") .onClose(() -> compareAndSetRE(ref, null, "new1")) .onClose(() -> TestConstants.throwRuntimeException("Failure 2")); // @formatter:on stream.close(); }); assertEquals("new1", ref.get()); assertEquals("Failure 2", thrownRE.getMessage()); assertEquals(0, thrownRE.getSuppressed().length); // Test ref.set(null); final IOException thrownIO = assertThrows(IOException.class, () -> { // @formatter:off final IOStream stream = IOStream.of("A") .onClose(() -> compareAndSetIO(ref, null, "new1")) .onClose(() -> TestConstants.throwIOException("Failure 2")); // @formatter:on stream.close(); }); assertEquals("new1", ref.get()); assertEquals("Failure 2", thrownIO.getMessage()); assertEquals(0, thrownIO.getSuppressed().length); // final IOException thrownB = assertThrows(IOException.class, () -> { // @formatter:off final IOStream stream = IOStream.of("A") .onClose(TestConstants.throwIOException("Failure 1")) .onClose(TestConstants.throwIOException("Failure 2")); // @formatter:on stream.close(); }); assertEquals("Failure 1", thrownB.getMessage()); assertEquals(0, thrownB.getSuppressed().length); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testParallel() { assertEquals(2, IOStream.of("A", "B").parallel().count()); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testPeek() throws IOException { final AtomicReference ref = new AtomicReference<>(); // Stream sanity check assertEquals(1, Stream.of("A").peek(e -> compareAndSetRE(ref, null, e)).count()); // TODO Resolve, abstract or document these differences? assertEquals(AT_LEAST_JAVA_11 ? null : "A", ref.get()); if (AT_LEAST_JAVA_11) { assertEquals(1, IOStream.of("B").peek(e -> compareAndSetRE(ref, null, e)).count()); assertEquals(1, IOStream.of("B").peek(e -> compareAndSetIO(ref, null, e)).count()); assertNull(ref.get()); } else { // Java 8 assertThrows(RuntimeException.class, () -> IOStream.of("B").peek(e -> compareAndSetRE(ref, null, e)).count()); assertThrows(IOException.class, () -> IOStream.of("B").peek(e -> compareAndSetIO(ref, null, e)).count()); assertEquals("A", ref.get()); } } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testReduceBinaryOperatorOfT() throws IOException { assertEquals("AB", IOStream.of("A", "B").reduce((t, u) -> t + u).get()); assertEquals(TestConstants.ABS_PATH_A.toRealPath(), IOStream.of(TestConstants.ABS_PATH_A, TestConstants.ABS_PATH_B).reduce((t, u) -> t.toRealPath()).get()); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testReduceTBinaryOperatorOfT() throws IOException { assertEquals("_AB", IOStream.of("A", "B").reduce("_", (t, u) -> t + u)); assertEquals(TestConstants.ABS_PATH_A.toRealPath(), IOStream.of(TestConstants.ABS_PATH_A, TestConstants.ABS_PATH_B).reduce(TestConstants.ABS_PATH_A, (t, u) -> t.toRealPath())); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testReduceUBiFunctionOfUQsuperTUBinaryOperatorOfU() throws IOException { assertEquals("_AB", IOStream.of("A", "B").reduce("_", (t, u) -> t + u, (t, u) -> t + u)); assertEquals(TestConstants.ABS_PATH_A.toRealPath(), IOStream.of(TestConstants.ABS_PATH_A, TestConstants.ABS_PATH_B).reduce(TestConstants.ABS_PATH_A, (t, u) -> t.toRealPath(), (t, u) -> u.toRealPath())); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testSequential() { assertEquals(2, IOStream.of("A", "B").sequential().count()); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testSkip() throws IOException { final AtomicReference ref = new AtomicReference<>(); assertEquals(1, Stream.of("A", "B").skip(1).peek(e -> compareAndSetRE(ref, null, e)).count()); // TODO Resolve, abstract or document these differences? assertEquals(AT_LEAST_JAVA_17 ? null : "B", ref.get()); if (AT_LEAST_JAVA_17) { assertEquals(1, IOStream.of("C", "D").skip(1).peek(e -> compareAndSetRE(ref, null, e)).count()); assertEquals(1, IOStream.of("C", "D").skip(1).peek(e -> compareAndSetIO(ref, null, e)).count()); assertNull(ref.get()); } else { if (AT_LEAST_JAVA_11) { assertThrows(RuntimeException.class, () -> IOStream.of("C", "D").skip(1).peek(e -> compareAndSetRE(ref, null, e)).count()); assertThrows(IOException.class, () -> IOStream.of("C", "D").skip(1).peek(e -> compareAndSetIO(ref, null, e)).count()); } else { assertThrows(RuntimeException.class, () -> IOStream.of("C", "D").skip(1).peek(e -> compareAndSetRE(ref, null, e)).count()); assertThrows(IOException.class, () -> IOStream.of("C", "D").skip(1).peek(e -> compareAndSetIO(ref, null, e)).count()); } assertEquals("B", ref.get()); } } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testSorted() throws IOException { assertEquals(Arrays.asList("A", "B", "C", "D"), IOStream.of("D", "A", "B", "C").sorted().collect(Collectors.toList())); assertEquals(Arrays.asList("A", "B", "C", "D"), IOStream.of("D", "A", "B", "C").sorted().peek(this::ioExceptionOnNull).collect(Collectors.toList())); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testSortedComparatorOfQsuperT() throws IOException { assertEquals(Arrays.asList("A", "B", "C", "D"), IOStream.of("D", "A", "B", "C").sorted(String::compareTo).collect(Collectors.toList())); assertEquals(Arrays.asList("A", "B", "C", "D"), IOStream.of("D", "A", "B", "C").sorted(String::compareTo).peek(this::ioExceptionOnNull).collect(Collectors.toList())); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testSpliterator() { final AtomicInteger ref = new AtomicInteger(); IOStream.of("A", "B").spliterator().forEachRemaining(e -> ref.incrementAndGet()); assertEquals(2, ref.get()); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testToArray() { assertArrayEquals(new String[] { "A", "B" }, IOStream.of("A", "B").toArray()); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testToArrayIntFunctionOfA() { assertArrayEquals(new String[] { "A", "B" }, IOStream.of("A", "B").toArray(String[]::new)); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testUnordered() { // Sanity check assertArrayEquals(new String[] { "A", "B" }, Stream.of("A", "B").unordered().toArray()); // Test assertArrayEquals(new String[] { "A", "B" }, IOStream.of("A", "B").unordered().toArray()); } @SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery @Test public void testUnwrap() { final Stream unwrap = IOStream.of("A", "B").unwrap(); assertNotNull(unwrap); assertEquals(2, unwrap.count()); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/function/IOSupplierTest.java0100644 0000000 0000000 00000004673 14603604450 031165 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.IOException; import java.io.UncheckedIOException; import java.util.concurrent.atomic.AtomicReference; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Tests {@link IOSupplier}. */ public class IOSupplierTest { private AtomicReference ref1; private String getThrowsIO(final IOSupplier supplier) throws IOException { return supplier.get(); } private String getThrowsNone(final IOSupplier supplier) { return supplier.asSupplier().get(); } @BeforeEach public void initEach() { ref1 = new AtomicReference<>(); } @Test public void testAsSupplier() { assertThrows(UncheckedIOException.class, () -> TestConstants.THROWING_IO_SUPPLIER.asSupplier().get()); assertEquals("new1", getThrowsNone(() -> TestUtils.compareAndSetThrowsIO(ref1, "new1"))); assertEquals("new1", ref1.get()); assertNotEquals(TestConstants.THROWING_IO_SUPPLIER.asSupplier(), TestConstants.THROWING_IO_SUPPLIER.asSupplier()); } @Test public void testGet() throws IOException { assertThrows(IOException.class, () -> TestConstants.THROWING_IO_SUPPLIER.get()); assertThrows(IOException.class, () -> { throw new IOException(); }); assertEquals("new1", getThrowsIO(() -> TestUtils.compareAndSetThrowsIO(ref1, "new1"))); assertEquals("new1", ref1.get()); } }commons-io-2.16.1-src/src/test/java/org/apache/commons/io/function/IOTriConsumerTest.java0100644 0000000 0000000 00000003702 14603604450 031624 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 java.io.IOException; import java.util.concurrent.atomic.AtomicReference; import org.junit.jupiter.api.Test; /** * Tests {@link IOTriConsumer}. */ public class IOTriConsumerTest { @Test public void testAccept() throws IOException { final AtomicReference ref = new AtomicReference<>(); final IOTriConsumer consumer = (s, i, b) -> ref.set(s + i + b); consumer.accept("A", 1, 'b'); assertEquals("A1b", ref.get()); } @Test public void testAndThen() throws IOException { final AtomicReference ref = new AtomicReference<>(); final IOTriConsumer consumer1 = (s, i, b) -> ref.set(s + i + b); final IOTriConsumer consumer2 = (s, i, b) -> ref.set(ref.get() + b + i + s); consumer1.andThen(consumer2).accept("B", 2, 'b'); assertEquals("B2bb2B", ref.get()); } @Test public void testNoop() throws IOException { IOTriConsumer.noop().accept(null, null, null); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/function/IOTriFunctionTest.java0100644 0000000 0000000 00000006312 14603604450 031616 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 java.io.IOException; import java.math.BigInteger; import java.util.concurrent.atomic.AtomicReference; import org.junit.jupiter.api.Test; /** * Tests {@link IOTriFunction}. */ public class IOTriFunctionTest { /** * Tests {@link IOTriFunction#apply(Object, Object, Object)}. * * @throws IOException thrown on test failure */ @Test public void testAccept() throws IOException { final AtomicReference ref1 = new AtomicReference<>(); final AtomicReference ref2 = new AtomicReference<>(); final AtomicReference ref3 = new AtomicReference<>(); final IOTriFunction, AtomicReference, AtomicReference, String> tri = (t, u, v) -> { ref1.set(Character.valueOf('a')); ref2.set(Short.valueOf((short) 1)); ref3.set("z"); return "ABC"; }; assertEquals("ABC", tri.apply(ref1, ref2, ref3)); assertEquals(Character.valueOf('a'), ref1.get()); assertEquals(Short.valueOf((short) 1), ref2.get()); assertEquals("z", ref3.get()); } /** * Tests {@link IOTriFunction#andThen(IOFunction)}. * * @throws IOException thrown on test failure */ @Test public void testAndThenIOFunction() throws IOException { final AtomicReference ref1 = new AtomicReference<>(); final AtomicReference ref2 = new AtomicReference<>(); final AtomicReference ref3 = new AtomicReference<>(); final IOTriFunction, AtomicReference, AtomicReference, String> tri = (t, u, v) -> { ref1.set(Character.valueOf('a')); ref2.set(Short.valueOf((short) 1)); ref3.set("z"); return "9"; }; final IOFunction after = t -> { ref1.set(Character.valueOf('b')); ref2.set(Short.valueOf((short) 2)); ref3.set("zz"); return BigInteger.valueOf(Long.parseLong(t)).add(BigInteger.ONE); }; assertEquals(BigInteger.TEN, tri.andThen(after).apply(ref1, ref2, ref3)); assertEquals(Character.valueOf('b'), ref1.get()); assertEquals(Short.valueOf((short) 2), ref2.get()); assertEquals("zz", ref3.get()); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/function/IOUnaryOperatorTest.java0100644 0000000 0000000 00000004374 14603604450 032172 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.IOException; import java.io.UncheckedIOException; import java.nio.file.Path; import java.util.Arrays; import java.util.List; import java.util.Optional; import org.junit.jupiter.api.Test; /** * Tests {@link IOUnaryOperator}. */ public class IOUnaryOperatorTest { @Test public void testAsUnaryOperator() { final List list = Arrays.asList(TestConstants.ABS_PATH_A, TestConstants.ABS_PATH_A); final IOUnaryOperator throwingIOUnaryOperator = TestUtils.throwingIOUnaryOperator(); assertThrows(UncheckedIOException.class, () -> list.replaceAll(throwingIOUnaryOperator.asUnaryOperator())); assertEquals("a", Optional.of("a").map(IOUnaryOperator.identity().asUnaryOperator()).get()); assertEquals("a", Optional.of("a").map(IOUnaryOperator.identity().asFunction()).get()); } @Test public void testIdentity() throws IOException { assertEquals(IOUnaryOperator.identity(), IOUnaryOperator.identity()); final IOUnaryOperator identityFunction = IOUnaryOperator.identity(); final byte[] buf = {(byte) 0xa, (byte) 0xb, (byte) 0xc}; assertEquals(buf, identityFunction.apply(buf)); assertArrayEquals(buf, identityFunction.apply(buf)); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/function/PathBaseStream.java0100644 0000000 0000000 00000001771 14603604450 031131 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.nio.file.Path; import java.util.stream.BaseStream; /** * Test fixture. */ interface PathBaseStream extends BaseStream { // empty } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/function/PathStream.java0100644 0000000 0000000 00000001735 14603604450 030336 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.nio.file.Path; import java.util.stream.Stream; /** * Test fixture. */ interface PathStream extends Stream { // empty } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/function/TestConstants.java0100644 0000000 0000000 00000006067 14603604450 031105 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.io.UncheckedIOException; import java.nio.file.Path; import java.nio.file.Paths; import java.util.function.Predicate; /** * Test fixtures for this package. */ final class TestConstants { static final Path ABS_PATH_A = Paths.get("LICENSE.txt").toAbsolutePath(); static final Path ABS_PATH_B = Paths.get("NOTICE.txt").toAbsolutePath(); static IOBiConsumer THROWING_IO_BI_CONSUMER = (t, u) -> throwIOException(); static IOBiFunction THROWING_IO_BI_FUNCTION = (t, u) -> throwIOException(); static IOBinaryOperator THROWING_IO_BINARY_OPERATOR = (t, u) -> throwIOException(); static IOComparator THROWING_IO_COMPARATOR = (t, u) -> throwIOException(); static IOConsumer THROWING_IO_CONSUMER = t -> throwIOException(); static IOFunction THROWING_IO_FUNCTION = t -> throwIOException(); static IOIntSupplier THROWING_IO_INT_SUPPLIER = TestConstants::throwIOException; static IOLongSupplier THROWING_IO_LONG_SUPPLIER = TestConstants::throwIOException; static IOPredicate THROWING_IO_PREDICATE = t -> throwIOException(); static IOQuadFunction THROWING_IO_QUAD_FUNCTION = (t, u, v, w) -> throwIOException(); static IORunnable THROWING_IO_RUNNABLE = TestConstants::throwIOException; static IOSupplier THROWING_IO_SUPPLIER = TestConstants::throwIOException; static IOTriConsumer THROWING_IO_TRI_CONSUMER = (t, u, v) -> throwIOException(); static IOTriFunction THROWING_IO_TRI_FUNCTION = (t, u, v) -> throwIOException(); static IOUnaryOperator THROWING_IO_UNARY_OPERATOR = t -> throwIOException(); static Predicate THROWING_PREDICATE = t -> { throw new UncheckedIOException(new IOException("Failure")); }; static T throwIOException() throws IOException { return throwIOException("Failure"); } static T throwIOException(final String message) throws IOException { throw new IOException(message); } static T throwRuntimeException(final String message) { throw new RuntimeException(message); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/function/TestUtils.java0100644 0000000 0000000 00000010353 14603604450 030222 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; final class TestUtils { static int compareAndSetThrowsIO(final AtomicInteger ref, final int update) throws IOException { return compareAndSetThrowsIO(ref, 0, update); } static int compareAndSetThrowsIO(final AtomicInteger ref, final int expected, final int update) throws IOException { if (!ref.compareAndSet(expected, update)) { throw new IOException("Unexpected"); } return ref.get(); // same as update } static long compareAndSetThrowsIO(final AtomicLong ref, final long update) throws IOException { return compareAndSetThrowsIO(ref, 0, update); } static long compareAndSetThrowsIO(final AtomicLong ref, final long expected, final long update) throws IOException { if (!ref.compareAndSet(expected, update)) { throw new IOException("Unexpected"); } return ref.get(); // same as update } static T compareAndSetThrowsIO(final AtomicReference ref, final T update) throws IOException { return compareAndSetThrowsIO(ref, null, update); } static T compareAndSetThrowsIO(final AtomicReference ref, final T expected, final T update) throws IOException { if (!ref.compareAndSet(expected, update)) { throw new IOException("Unexpected"); } return ref.get(); // same as update } static T compareAndSetThrowsRE(final AtomicReference ref, final T expected, final T update) { if (!ref.compareAndSet(expected, update)) { throw new RuntimeException("Unexpected"); } return ref.get(); // same as update } @SuppressWarnings("unchecked") static IOBiConsumer throwingIOBiConsumer() { return (IOBiConsumer) TestConstants.THROWING_IO_BI_CONSUMER; } @SuppressWarnings("unchecked") static IOBiFunction throwingIOBiFunction() { return (IOBiFunction) TestConstants.THROWING_IO_BI_FUNCTION; } @SuppressWarnings("unchecked") static IOBinaryOperator throwingIOBinaryOperator() { return (IOBinaryOperator) TestConstants.THROWING_IO_BINARY_OPERATOR; } @SuppressWarnings("unchecked") static IOComparator throwingIOComparator() { return (IOComparator) TestConstants.THROWING_IO_COMPARATOR; } @SuppressWarnings("unchecked") static IOConsumer throwingIOConsumer() { return (IOConsumer) TestConstants.THROWING_IO_CONSUMER; } @SuppressWarnings("unchecked") static IOFunction throwingIOFunction() { return (IOFunction) TestConstants.THROWING_IO_FUNCTION; } @SuppressWarnings("unchecked") static IOPredicate throwingIOPredicate() { return (IOPredicate) TestConstants.THROWING_IO_PREDICATE; } static IORunnable throwingIORunnable() { return TestConstants.THROWING_IO_RUNNABLE; } @SuppressWarnings("unchecked") static IOSupplier throwingIOSupplier() { return (IOSupplier) TestConstants.THROWING_IO_SUPPLIER; } @SuppressWarnings("unchecked") static IOUnaryOperator throwingIOUnaryOperator() { return (IOUnaryOperator) TestConstants.THROWING_IO_UNARY_OPERATOR; } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/function/UncheckTest.java0100644 0000000 0000000 00000033357 14603604450 030513 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 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.UncheckedIOException; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Supplier; import org.apache.commons.io.input.BrokenInputStream; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Tests {@link Uncheck}. */ public class UncheckTest { private static final byte[] BYTES = { 'a', 'b' }; private static final String CAUSE_MESSAGE = "CauseMessage"; private static final String CUSTOM_MESSAGE = "Custom message"; private AtomicInteger atomicInt; private AtomicLong atomicLong; private AtomicReference ref1; private AtomicReference ref2; private AtomicReference ref3; private AtomicReference ref4; private void assertUncheckedIOException(final IOException expected, final UncheckedIOException e) { assertEquals(CUSTOM_MESSAGE, e.getMessage()); final IOException cause = e.getCause(); assertEquals(expected.getClass(), cause.getClass()); assertEquals(CAUSE_MESSAGE, cause.getMessage()); } @BeforeEach public void initEach() { ref1 = new AtomicReference<>(); ref2 = new AtomicReference<>(); ref3 = new AtomicReference<>(); ref4 = new AtomicReference<>(); atomicInt = new AtomicInteger(); atomicLong = new AtomicLong(); } private ByteArrayInputStream newInputStream() { return new ByteArrayInputStream(BYTES); } /** * Tests {@link Uncheck#accept(IOConsumer, Object)}. */ @Test public void testAccept() { final ByteArrayInputStream stream = newInputStream(); Uncheck.accept(n -> stream.skip(n), 1); assertEquals('b', Uncheck.get(stream::read).intValue()); } @Test public void testAcceptIOBiConsumerOfTUTU() { assertThrows(UncheckedIOException.class, () -> Uncheck.accept((t, u) -> { throw new IOException(); }, null, null)); assertThrows(UncheckedIOException.class, () -> Uncheck.accept(TestConstants.THROWING_IO_BI_CONSUMER, null, null)); Uncheck.accept((t, u) -> { TestUtils.compareAndSetThrowsIO(ref1, t); TestUtils.compareAndSetThrowsIO(ref2, u); }, "new1", "new2"); assertEquals("new1", ref1.get()); assertEquals("new2", ref2.get()); } @Test public void testAcceptIOConsumerOfTT() { assertThrows(UncheckedIOException.class, () -> Uncheck.accept(t -> { throw new IOException(); }, null)); assertThrows(UncheckedIOException.class, () -> Uncheck.accept(TestUtils.throwingIOConsumer(), null)); Uncheck.accept(t -> TestUtils.compareAndSetThrowsIO(ref1, t), "new1"); assertEquals("new1", ref1.get()); } @Test public void testAcceptIOTriConsumerOfTUVTUV() { assertThrows(UncheckedIOException.class, () -> Uncheck.accept((t, u, v) -> { throw new IOException(); }, null, null, null)); assertThrows(UncheckedIOException.class, () -> Uncheck.accept(TestConstants.THROWING_IO_TRI_CONSUMER, null, null, null)); Uncheck.accept((t, u, v) -> { TestUtils.compareAndSetThrowsIO(ref1, t); TestUtils.compareAndSetThrowsIO(ref2, u); TestUtils.compareAndSetThrowsIO(ref3, v); }, "new1", "new2", "new3"); assertEquals("new1", ref1.get()); assertEquals("new2", ref2.get()); assertEquals("new3", ref3.get()); } /** * Tests {@link Uncheck#apply(IOFunction, Object)}. */ @Test public void testApply1() { final ByteArrayInputStream stream = newInputStream(); assertEquals(1, Uncheck.apply(n -> stream.skip(n), 1).intValue()); assertEquals('b', Uncheck.get(stream::read).intValue()); } /** * Tests {@link Uncheck#apply(IOBiFunction, Object, Object)}. */ @Test public void testApply2() { final ByteArrayInputStream stream = newInputStream(); final byte[] buf = new byte[BYTES.length]; assertEquals(1, Uncheck.apply((o, l) -> stream.read(buf, o, l), 0, 1).intValue()); assertEquals('a', buf[0]); } /** * Tests {@link Uncheck#apply(IOTriFunction, Object, Object, Object)}. */ @Test public void testApply3() { final ByteArrayInputStream stream = newInputStream(); final byte[] buf = new byte[BYTES.length]; assertEquals(1, Uncheck.apply((b, o, l) -> stream.read(b, o, l), buf, 0, 1).intValue()); assertEquals('a', buf[0]); } @Test public void testApplyIOBiFunctionOfTURTU() { assertThrows(UncheckedIOException.class, () -> Uncheck.apply((t, u) -> { throw new IOException(); }, null, null)); assertThrows(UncheckedIOException.class, () -> Uncheck.apply(TestConstants.THROWING_IO_BI_FUNCTION, null, null)); assertEquals("new0", Uncheck.apply((t, u) -> { TestUtils.compareAndSetThrowsIO(ref1, t); TestUtils.compareAndSetThrowsIO(ref2, u); return "new0"; }, "new1", "new2")); assertEquals("new1", ref1.get()); assertEquals("new2", ref2.get()); } @Test public void testApplyIOFunctionOfTRT() { assertThrows(UncheckedIOException.class, () -> Uncheck.apply(t -> { throw new IOException(); }, null)); assertThrows(UncheckedIOException.class, () -> Uncheck.apply(TestConstants.THROWING_IO_FUNCTION, null)); Uncheck.apply(t -> TestUtils.compareAndSetThrowsIO(ref1, t), "new1"); assertEquals("new1", ref1.get()); } @Test public void testApplyIOQuadFunctionOfTUVWRTUVW() { assertThrows(UncheckedIOException.class, () -> Uncheck.apply((t, u, v, w) -> { throw new IOException(); }, null, null, null, null)); assertThrows(UncheckedIOException.class, () -> Uncheck.apply(TestConstants.THROWING_IO_QUAD_FUNCTION, null, null, null, null)); assertEquals("new0", Uncheck.apply((t, u, v, w) -> { TestUtils.compareAndSetThrowsIO(ref1, t); TestUtils.compareAndSetThrowsIO(ref2, u); TestUtils.compareAndSetThrowsIO(ref3, v); TestUtils.compareAndSetThrowsIO(ref4, w); return "new0"; }, "new1", "new2", "new3", "new4")); assertEquals("new1", ref1.get()); assertEquals("new2", ref2.get()); assertEquals("new3", ref3.get()); assertEquals("new4", ref4.get()); } @Test public void testApplyIOTriFunctionOfTUVRTUV() { assertThrows(UncheckedIOException.class, () -> Uncheck.apply((t, u, v) -> { throw new IOException(); }, null, null, null)); assertThrows(UncheckedIOException.class, () -> Uncheck.apply(TestConstants.THROWING_IO_TRI_FUNCTION, null, null, null)); assertEquals("new0", Uncheck.apply((t, u, v) -> { TestUtils.compareAndSetThrowsIO(ref1, t); TestUtils.compareAndSetThrowsIO(ref2, u); TestUtils.compareAndSetThrowsIO(ref3, v); return "new0"; }, "new1", "new2", "new3")); assertEquals("new1", ref1.get()); assertEquals("new2", ref2.get()); assertEquals("new3", ref3.get()); } /** * Tests {@link Uncheck#get(IOSupplier)}. */ @Test public void testGet() { assertEquals('a', Uncheck.get(() -> newInputStream().read()).intValue()); assertThrows(UncheckedIOException.class, () -> Uncheck.get(() -> { throw new IOException(); })); assertThrows(UncheckedIOException.class, () -> Uncheck.get(TestConstants.THROWING_IO_SUPPLIER)); assertEquals("new1", Uncheck.get(() -> TestUtils.compareAndSetThrowsIO(ref1, "new1"))); assertEquals("new1", ref1.get()); } @Test public void testGetAsInt() { assertThrows(UncheckedIOException.class, () -> Uncheck.getAsInt(() -> { throw new IOException(); })); assertThrows(UncheckedIOException.class, () -> Uncheck.getAsInt(TestConstants.THROWING_IO_INT_SUPPLIER)); assertEquals(1, Uncheck.getAsInt(() -> TestUtils.compareAndSetThrowsIO(atomicInt, 1))); assertEquals(1, atomicInt.get()); } @Test public void testGetAsIntMessage() { // No exception assertThrows(UncheckedIOException.class, () -> Uncheck.getAsInt(() -> { throw new IOException(); }, () -> CUSTOM_MESSAGE)); assertThrows(UncheckedIOException.class, () -> Uncheck.getAsInt(TestConstants.THROWING_IO_INT_SUPPLIER, () -> CUSTOM_MESSAGE)); assertEquals(1, Uncheck.getAsInt(() -> TestUtils.compareAndSetThrowsIO(atomicInt, 1), () -> CUSTOM_MESSAGE)); assertEquals(1, atomicInt.get()); // exception final IOException expected = new IOException(CAUSE_MESSAGE); try { Uncheck.getAsInt(() -> new BrokenInputStream(expected).read(), () -> CUSTOM_MESSAGE); fail(); } catch (final UncheckedIOException e) { assertUncheckedIOException(expected, e); } } @Test public void testGetAsLong() { assertThrows(UncheckedIOException.class, () -> Uncheck.getAsLong(() -> { throw new IOException(); })); assertThrows(UncheckedIOException.class, () -> Uncheck.getAsLong(TestConstants.THROWING_IO_LONG_SUPPLIER)); assertEquals(1L, Uncheck.getAsLong(() -> TestUtils.compareAndSetThrowsIO(atomicLong, 1L))); assertEquals(1L, atomicLong.get()); } @Test public void testGetAsLongMessage() { // No exception assertThrows(UncheckedIOException.class, () -> Uncheck.getAsLong(() -> { throw new IOException(); }, () -> CUSTOM_MESSAGE)); assertThrows(UncheckedIOException.class, () -> Uncheck.getAsLong(TestConstants.THROWING_IO_LONG_SUPPLIER, () -> CUSTOM_MESSAGE)); assertEquals(1L, Uncheck.getAsLong(() -> TestUtils.compareAndSetThrowsIO(atomicLong, 1L), () -> CUSTOM_MESSAGE)); assertEquals(1L, atomicLong.get()); // exception final IOException expected = new IOException(CAUSE_MESSAGE); try { Uncheck.getAsLong(() -> new BrokenInputStream(expected).read(), () -> CUSTOM_MESSAGE); fail(); } catch (final UncheckedIOException e) { assertUncheckedIOException(expected, e); } } /** * Tests {@link Uncheck#get(IOSupplier, Supplier)}. */ @Test public void testGetMessage() { // No exception assertEquals('a', Uncheck.get(() -> newInputStream().read()).intValue(), () -> CUSTOM_MESSAGE); // Exception final IOException expected = new IOException(CAUSE_MESSAGE); try { Uncheck.get(() -> new BrokenInputStream(expected).read(), () -> CUSTOM_MESSAGE); fail(); } catch (final UncheckedIOException e) { assertUncheckedIOException(expected, e); } } /** * Tests {@link Uncheck#run(IORunnable)}. */ @Test public void testRun() { final ByteArrayInputStream stream = newInputStream(); Uncheck.run(() -> stream.skip(1)); assertEquals('b', Uncheck.get(stream::read).intValue()); // assertThrows(UncheckedIOException.class, () -> Uncheck.run(() -> { throw new IOException(); })); assertThrows(UncheckedIOException.class, () -> Uncheck.run(TestConstants.THROWING_IO_RUNNABLE)); Uncheck.run(() -> TestUtils.compareAndSetThrowsIO(ref1, "new1")); assertEquals("new1", ref1.get()); } /** * Tests {@link Uncheck#run(IORunnable, Supplier))}. * * @throws IOException */ @Test public void testRunMessage() throws IOException { // No exception final ByteArrayInputStream stream = newInputStream(); Uncheck.run(() -> stream.skip(1), () -> CUSTOM_MESSAGE); assertEquals('b', Uncheck.get(stream::read).intValue()); final IOException expected = new IOException(CAUSE_MESSAGE); // Exception try { Uncheck.run(() -> new BrokenInputStream(expected).read(), () -> CUSTOM_MESSAGE); fail(); } catch (final UncheckedIOException e) { assertUncheckedIOException(expected, e); } } @Test public void testTest() { assertThrows(UncheckedIOException.class, () -> Uncheck.test(t -> { throw new IOException(); }, null)); assertThrows(UncheckedIOException.class, () -> Uncheck.test(TestConstants.THROWING_IO_PREDICATE, null)); assertTrue(Uncheck.test(t -> TestUtils.compareAndSetThrowsIO(ref1, t).equals(t), "new1")); assertEquals("new1", ref1.get()); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/AbstractInputStreamTest.java0100644 0000000 0000000 00000013353 14603604450 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.input; import static org.junit.jupiter.api.Assertions.assertEquals; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; import org.apache.commons.io.IOUtils; 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 Path 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 = Files.createTempFile("temp-file", ".tmp"); Files.write(inputFile, randomBytes); } @AfterEach public void tearDown() throws IOException { Files.delete(inputFile); IOUtils.close(inputStreams); } @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]; while (is.read(buf, 0, buf.length) != -1) { // empty } 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.16.1-src/src/test/java/org/apache/commons/io/input/AutoCloseInputStreamTest.java0100644 0000000 0000000 00000012746 14603604450 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.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.BeforeEach; import org.junit.jupiter.api.Test; /** * Tests {@link AutoCloseInputStream}. */ public class AutoCloseInputStreamTest { private byte[] data; private AutoCloseInputStream 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 testBuilderGet() { // java.lang.IllegalStateException: origin == null assertThrows(IllegalStateException.class, () -> AutoCloseInputStream.builder().get()); } @Test public void testClose() throws IOException { stream.close(); assertTrue(closed, "closed"); assertEquals(-1, stream.read(), "read()"); } @Test public void testFinalize() throws Throwable { stream.finalize(); 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)"); } private void testResetBeforeEnd(final AutoCloseInputStream inputStream) throws IOException { 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()); } @Test public void testResetBeforeEndCtor() throws IOException { try (final AutoCloseInputStream inputStream = new AutoCloseInputStream(new ByteArrayInputStream("1234".getBytes()))) { testResetBeforeEnd(inputStream); } } @Test public void testResetBeforeEndSetByteArray() throws IOException { try (final AutoCloseInputStream inputStream = AutoCloseInputStream.builder().setByteArray("1234".getBytes()).get()) { testResetBeforeEnd(inputStream); } } @Test public void testResetBeforeEndSetCharSequence() throws IOException { try (final AutoCloseInputStream inputStream = AutoCloseInputStream.builder().setCharSequence("1234").get()) { testResetBeforeEnd(inputStream); } } @Test public void testResetBeforeEndSetInputStream() throws IOException { try (final AutoCloseInputStream inputStream = AutoCloseInputStream.builder().setInputStream(new ByteArrayInputStream("1234".getBytes())).get()) { testResetBeforeEnd(inputStream); } } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/BOMInputStreamTest.java0100644 0000000 0000000 00000074732 14603604450 031260 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; 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 { /** * A mock InputStream that expects {@code close()} to be called. */ private static final 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 createUtf8Input(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); } private boolean doesSaxSupportCharacterSet(final String charsetName) throws ParserConfigurationException, SAXException, IOException { final DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); try (InputStream byteStream = CharSequenceInputStream.builder().setCharSequence("") .setCharset(charsetName).get()) { final InputSource is = new InputSource(byteStream); is.setEncoding(charsetName); documentBuilder.parse(is); } catch (final SAXParseException e) { if (e.getMessage().contains(charsetName)) { return false; } } return true; } private boolean jvmAndSaxBothSupportCharset(final String charSetName) throws ParserConfigurationException, SAXException, IOException { return Charset.isSupported(charSetName) && doesSaxSupportCharacterSet(charSetName); } 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 { try (InputStream inputStream = this.getClass().getResourceAsStream(resource)) { assertNotNull(inputStream); try (BOMInputStream bomInputStream = BOMInputStream.builder().setInputStream(inputStream).get()) { bomInputStream.mark(1_000_000); this.readFile(bomInputStream); bomInputStream.reset(); this.readFile(bomInputStream); inputStream.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 (InputStream in = BOMInputStream.builder().setInputStream(createUtf8Input(data, true)).get()) { assertEquals(7, in.available()); } } @Test public void testAvailableWithoutBOM() throws Exception { final byte[] data = { 'A', 'B', 'C', 'D' }; try (InputStream in = BOMInputStream.builder().setInputStream(createUtf8Input(data, false)).get()) { assertEquals(4, in.available()); } } @Test public void testBuilderGet() { // java.lang.IllegalStateException: origin == null assertThrows(IllegalStateException.class, () -> BOMInputStream.builder().get()); } @Test // this is here for coverage public void testClose() throws Exception { try (ExpectCloseInputStream del = new ExpectCloseInputStream()) { try (InputStream in = new BOMInputStream(del)) { // nothing } del.assertCloseCalled(); } } @Test public void testEmptyBufferWithBOM() throws Exception { final byte[] data = {}; try (InputStream in = BOMInputStream.builder().setInputStream(createUtf8Input(data, true)).get()) { final byte[] buf = new byte[1024]; assertEquals(-1, in.read(buf)); } } @Test public void testEmptyBufferWithoutBOM() throws Exception { final byte[] data = {}; try (InputStream in = BOMInputStream.builder().setInputStream(createUtf8Input(data, false)).get()) { final byte[] buf = new byte[1024]; assertEquals(-1, in.read(buf)); } } @Test public void testGetBOMFirstThenRead() throws Exception { final byte[] data = { 'A', 'B', 'C' }; try (BOMInputStream in = BOMInputStream.builder().setInputStream(createUtf8Input(data, true)).get()) { 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 (BOMInputStream in = BOMInputStream.builder().setInputStream(createUtf8Input(data, true)).setInclude(true).get()) { 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 (InputStream in = BOMInputStream.builder().setInputStream(createUtf8Input(data, true)).get()) { 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 (InputStream in = BOMInputStream.builder().setInputStream(createUtf8Input(data, false)).get()) { 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 (InputStream in = BOMInputStream.builder().setInputStream(createUtf8Input(data, false)).get()) { 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 (InputStream in = BOMInputStream.builder().setInputStream(createUtf8Input(data, false)).get()) { 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 (InputStream in = BOMInputStream.builder().setInputStream(createUtf8Input(data, true)).get()) { 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 (InputStream in = BOMInputStream.builder().setInputStream(createUtf8Input(data, false)).get()) { 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 (InputStream in = BOMInputStream.builder().setInputStream(createUtf8Input(data, true)).get()) { 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 (InputStream in = BOMInputStream.builder().setInputStream(createUtf8Input(data, false)).get()) { 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' }; assertThrows(IllegalArgumentException.class, () -> new BOMInputStream(createUtf8Input(data, true), false, (ByteOrderMark[]) null).close()); assertThrows(IllegalArgumentException.class, () -> new BOMInputStream(createUtf8Input(data, true), false, new ByteOrderMark[0]).close()); // try (final BOMInputStream bomInputStream = BOMInputStream.builder() .setInputStream(createUtf8Input(data, true)) .setInclude(true) .setByteOrderMarks((ByteOrderMark[]) null) .get()) { assertEquals(BOMInputStream.Builder.getDefaultByteOrderMark(), bomInputStream.getBOM()); } assertThrows(IllegalArgumentException.class, () -> BOMInputStream.builder() .setInputStream(createUtf8Input(data, true)) .setInclude(true) .setByteOrderMarks() .get() .close()); } @Test public void testReadEmpty() throws Exception { final byte[] data = {}; try (BOMInputStream in = BOMInputStream.builder().setInputStream(createUtf8Input(data, false)).get()) { 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 (BOMInputStream in = BOMInputStream.builder().setInputStream(createUtf8Input(data, false)).get()) { 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 (BOMInputStream in = new BOMInputStream(createUtf8Input(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 (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"); assertThrows(IllegalArgumentException.class, () -> in.hasBOM(ByteOrderMark.UTF_16LE)); } } @Test public void testReadWithBOMUtf16Le() throws Exception { final byte[] data = "ABC".getBytes(StandardCharsets.UTF_16LE); try (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"); assertThrows(IllegalArgumentException.class, () -> in.hasBOM(ByteOrderMark.UTF_16BE)); } } @Test public void testReadWithBOMUtf32Be() throws Exception { assumeTrue(Charset.isSupported("UTF_32BE")); final byte[] data = "ABC".getBytes("UTF_32BE"); try (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"); assertThrows(IllegalArgumentException.class, () -> in.hasBOM(ByteOrderMark.UTF_32LE)); } } @Test public void testReadWithBOMUtf32Le() throws Exception { assumeTrue(Charset.isSupported("UTF_32LE")); final byte[] data = "ABC".getBytes("UTF_32LE"); try (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"); assertThrows(IllegalArgumentException.class, () -> in.hasBOM(ByteOrderMark.UTF_32BE)); } } @Test public void testReadWithBOMUtf8() throws Exception { final byte[] data = "ABC".getBytes(StandardCharsets.UTF_8); try (BOMInputStream in = new BOMInputStream(createUtf8Input(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"); assertThrows(IllegalArgumentException.class, () -> in.hasBOM(ByteOrderMark.UTF_16BE)); } } @Test public void testReadWithMultipleBOM() throws Exception { final byte[] data = { 'A', 'B', 'C' }; try (BOMInputStream in = new BOMInputStream(createUtf8Input(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 (BOMInputStream in = BOMInputStream.builder().setInputStream(createUtf8Input(data, false)).get()) { 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 = BOMInputStream.builder().setInputStream(createUtf8Input(data, true)).get()) { parseXml(in); } parseXml(createUtf8Input(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 = BOMInputStream.builder().setInputStream(createUtf8Input(data, false)).get()) { 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 = BOMInputStream.builder().setInputStream(createUtf8Input(data, false)).get()) { parseXml(in); } parseXml(createUtf32BeDataStream(data, false)); } @Test public void testSkipReturnValueWithBom() throws IOException { final byte[] data = { (byte) 0x31, (byte) 0x32, (byte) 0x33 }; try (BOMInputStream is1 = BOMInputStream.builder().setInputStream(createUtf8Input(data, true)).get()) { assertEquals(2, is1.skip(2)); assertEquals((byte) 0x33, is1.read()); } } @Test public void testSkipReturnValueWithoutBom() throws IOException { final byte[] data = { (byte) 0x31, (byte) 0x32, (byte) 0x33 }; try (BOMInputStream is2 = BOMInputStream.builder().setInputStream(createUtf8Input(data, false)).get()) { assertEquals(2, is2.skip(2)); // IO-428 assertEquals((byte) 0x33, is2.read()); } } @Test public void testSkipWithBOM() throws Exception { final byte[] data = { 'A', 'B', 'C', 'D' }; try (InputStream in = BOMInputStream.builder().setInputStream(createUtf8Input(data, true)).get()) { in.skip(2L); assertEquals('C', in.read()); } } @Test public void testSkipWithoutBOM() throws Exception { final byte[] data = { 'A', 'B', 'C', 'D' }; try (InputStream in = BOMInputStream.builder().setInputStream(createUtf8Input(data, false)).get()) { in.skip(2L); assertEquals('C', in.read()); } } @Test public void testSmallBufferWithBOM() throws Exception { final byte[] data = { 'A', 'B', 'C' }; try (InputStream in = BOMInputStream.builder().setInputStream(createUtf8Input(data, true)).get()) { 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 (InputStream in = BOMInputStream.builder().setInputStream(createUtf8Input(data, false)).get()) { 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 (InputStream in = createUtf8Input(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); } } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/BoundedInputStreamTest.java0100644 0000000 0000000 00000061542 14603604450 032216 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.ByteArrayInputStream; import java.nio.charset.StandardCharsets; import java.util.concurrent.atomic.AtomicBoolean; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.mutable.MutableInt; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; /** * Tests for {@link BoundedInputStream}. */ public class BoundedInputStreamTest { private void compare(final String message, final byte[] expected, final byte[] actual) { assertEquals(expected.length, actual.length, () -> message + " (array length equals check)"); final MutableInt mi = new MutableInt(); for (int i = 0; i < expected.length; i++) { mi.setValue(i); assertEquals(expected[i], actual[i], () -> message + " byte[" + mi + "]"); } } @Test public void testBuilderGet() { // java.lang.IllegalStateException: origin == null assertThrows(IllegalStateException.class, () -> BoundedInputStream.builder().get()); } @SuppressWarnings("deprecation") @ParameterizedTest @ValueSource(longs = { -100, -1, 0, 1, 2, 4, 8, 16, 32, 64 }) public void testCounts(final long startCount) throws Exception { final byte[] helloWorld = "Hello World".getBytes(StandardCharsets.UTF_8); final byte[] hello = "Hello".getBytes(StandardCharsets.UTF_8); final long actualStart = startCount < 0 ? 0 : startCount; // limit = length try (BoundedInputStream bounded = BoundedInputStream.builder().setInputStream(new ByteArrayInputStream(helloWorld)).setCount(startCount) .setMaxCount(helloWorld.length).get()) { assertTrue(bounded.markSupported()); assertEquals(helloWorld.length, bounded.getMaxCount()); assertEquals(helloWorld.length, bounded.getMaxLength()); assertEquals(actualStart, bounded.getCount()); assertEquals(Math.max(0, bounded.getMaxCount() - actualStart), bounded.getRemaining()); assertEquals(Math.max(0, bounded.getMaxLength() - actualStart), bounded.getRemaining()); int readCount = 0; for (int i = 0; i < helloWorld.length; i++) { final byte expectedCh = bounded.getRemaining() > 0 ? helloWorld[i] : EOF; final int actualCh = bounded.read(); assertEquals(expectedCh, actualCh, "limit = length byte[" + i + "]"); if (actualCh != EOF) { readCount++; } assertEquals(helloWorld.length, bounded.getMaxCount()); assertEquals(helloWorld.length, bounded.getMaxLength()); assertEquals(actualStart + readCount, bounded.getCount(), "i=" + i); assertEquals(Math.max(0, bounded.getMaxCount() - (readCount + actualStart)), bounded.getRemaining()); assertEquals(Math.max(0, bounded.getMaxLength() - (readCount + actualStart)), bounded.getRemaining()); } assertEquals(-1, bounded.read(), "limit = length end"); assertEquals(helloWorld.length, bounded.getMaxLength()); assertEquals(readCount + actualStart, bounded.getCount()); assertEquals(0, bounded.getRemaining()); assertEquals(0, bounded.available()); // should be invariant assertTrue(bounded.markSupported()); } // limit > length final int maxCountP1 = helloWorld.length + 1; try (BoundedInputStream bounded = BoundedInputStream.builder().setInputStream(new ByteArrayInputStream(helloWorld)).setCount(startCount) .setMaxCount(maxCountP1).get()) { assertTrue(bounded.markSupported()); assertEquals(maxCountP1, bounded.getMaxLength()); assertEquals(actualStart, bounded.getCount()); assertEquals(Math.max(0, bounded.getMaxCount() - actualStart), bounded.getRemaining()); assertEquals(Math.max(0, bounded.getMaxLength() - actualStart), bounded.getRemaining()); int readCount = 0; for (int i = 0; i < helloWorld.length; i++) { final byte expectedCh = bounded.getRemaining() > 0 ? helloWorld[i] : EOF; final int actualCh = bounded.read(); assertEquals(expectedCh, actualCh, "limit = length byte[" + i + "]"); if (actualCh != EOF) { readCount++; } assertEquals(maxCountP1, bounded.getMaxCount()); assertEquals(maxCountP1, bounded.getMaxLength()); assertEquals(actualStart + readCount, bounded.getCount(), "i=" + i); assertEquals(Math.max(0, bounded.getMaxCount() - (readCount + actualStart)), bounded.getRemaining()); assertEquals(Math.max(0, bounded.getMaxLength() - (readCount + actualStart)), bounded.getRemaining()); } assertEquals(-1, bounded.read(), "limit > length end"); assertEquals(0, bounded.available()); assertEquals(maxCountP1, bounded.getMaxLength()); assertEquals(readCount + actualStart, bounded.getCount()); assertEquals(Math.max(0, maxCountP1 - bounded.getCount()), bounded.getRemaining()); // should be invariant assertTrue(bounded.markSupported()); } // limit < length try (BoundedInputStream bounded = new BoundedInputStream(new ByteArrayInputStream(helloWorld), hello.length)) { assertTrue(bounded.markSupported()); assertEquals(hello.length, bounded.getMaxLength()); assertEquals(0, bounded.getCount()); assertEquals(bounded.getMaxLength(), bounded.getRemaining()); int readCount = 0; for (int i = 0; i < hello.length; i++) { assertEquals(hello[i], bounded.read(), "limit < length byte[" + i + "]"); readCount++; assertEquals(hello.length, bounded.getMaxLength()); assertEquals(readCount, bounded.getCount()); assertEquals(bounded.getMaxLength() - readCount, bounded.getRemaining()); } assertEquals(-1, bounded.read(), "limit < length end"); assertEquals(0, bounded.available()); assertEquals(hello.length, bounded.getMaxLength()); assertEquals(readCount, bounded.getCount()); assertEquals(bounded.getMaxLength() - readCount, bounded.getRemaining()); // should be invariant assertTrue(bounded.markSupported()); } } @Test public void testMarkReset() throws Exception { final byte[] helloWorld = "Hello World".getBytes(StandardCharsets.UTF_8); final int helloWorldLen = helloWorld.length; final byte[] hello = "Hello".getBytes(StandardCharsets.UTF_8); final byte[] world = " World".getBytes(StandardCharsets.UTF_8); final int helloLen = hello.length; // limit = -1 try (BoundedInputStream bounded = BoundedInputStream.builder().setInputStream(new ByteArrayInputStream(helloWorld)).get()) { assertTrue(bounded.markSupported()); bounded.mark(0); compare("limit = -1", helloWorld, IOUtils.toByteArray(bounded)); // should be invariant assertTrue(bounded.markSupported()); // again bounded.reset(); compare("limit = -1", hello, IOUtils.toByteArray(bounded, helloLen)); bounded.mark(helloWorldLen); compare("limit = -1", world, IOUtils.toByteArray(bounded)); bounded.reset(); compare("limit = -1", world, IOUtils.toByteArray(bounded)); // should be invariant assertTrue(bounded.markSupported()); } // limit = 0 try (BoundedInputStream bounded = BoundedInputStream.builder().setInputStream(new ByteArrayInputStream(helloWorld)).setMaxCount(0).get()) { assertTrue(bounded.markSupported()); bounded.mark(0); compare("limit = 0", IOUtils.EMPTY_BYTE_ARRAY, IOUtils.toByteArray(bounded)); // should be invariant assertTrue(bounded.markSupported()); // again bounded.reset(); compare("limit = 0", IOUtils.EMPTY_BYTE_ARRAY, IOUtils.toByteArray(bounded)); bounded.mark(helloWorldLen); compare("limit = 0", IOUtils.EMPTY_BYTE_ARRAY, IOUtils.toByteArray(bounded)); // should be invariant assertTrue(bounded.markSupported()); } // limit = length try (BoundedInputStream bounded = BoundedInputStream.builder().setInputStream(new ByteArrayInputStream(helloWorld)) .setMaxCount(helloWorld.length).get()) { assertTrue(bounded.markSupported()); bounded.mark(0); compare("limit = length", helloWorld, IOUtils.toByteArray(bounded)); // should be invariant assertTrue(bounded.markSupported()); // again bounded.reset(); compare("limit = length", hello, IOUtils.toByteArray(bounded, helloLen)); bounded.mark(helloWorldLen); compare("limit = length", world, IOUtils.toByteArray(bounded)); bounded.reset(); compare("limit = length", world, IOUtils.toByteArray(bounded)); // should be invariant assertTrue(bounded.markSupported()); } // limit > length try (BoundedInputStream bounded = BoundedInputStream.builder().setInputStream(new ByteArrayInputStream(helloWorld)) .setMaxCount(helloWorld.length + 1).get()) { assertTrue(bounded.markSupported()); bounded.mark(0); compare("limit > length", helloWorld, IOUtils.toByteArray(bounded)); // should be invariant assertTrue(bounded.markSupported()); // again bounded.reset(); compare("limit > length", helloWorld, IOUtils.toByteArray(bounded)); bounded.reset(); compare("limit > length", hello, IOUtils.toByteArray(bounded, helloLen)); bounded.mark(helloWorldLen); compare("limit > length", world, IOUtils.toByteArray(bounded)); bounded.reset(); compare("limit > length", world, IOUtils.toByteArray(bounded)); // should be invariant assertTrue(bounded.markSupported()); } // limit < length try (BoundedInputStream bounded = BoundedInputStream.builder().setInputStream(new ByteArrayInputStream(helloWorld)) .setMaxCount(helloWorld.length - (hello.length + 1)).get()) { assertTrue(bounded.markSupported()); bounded.mark(0); compare("limit < length", hello, IOUtils.toByteArray(bounded)); // should be invariant assertTrue(bounded.markSupported()); // again bounded.reset(); compare("limit < length", hello, IOUtils.toByteArray(bounded)); bounded.reset(); compare("limit < length", hello, IOUtils.toByteArray(bounded, helloLen)); bounded.mark(helloWorldLen); compare("limit < length", IOUtils.EMPTY_BYTE_ARRAY, IOUtils.toByteArray(bounded)); bounded.reset(); compare("limit < length", IOUtils.EMPTY_BYTE_ARRAY, IOUtils.toByteArray(bounded)); // should be invariant assertTrue(bounded.markSupported()); } } @SuppressWarnings("deprecation") @Test public void testOnMaxLength() throws Exception { final byte[] helloWorld = "Hello World".getBytes(StandardCharsets.UTF_8); final byte[] hello = "Hello".getBytes(StandardCharsets.UTF_8); final AtomicBoolean boolRef = new AtomicBoolean(); // limit = length try (BoundedInputStream bounded = new BoundedInputStream(new ByteArrayInputStream(helloWorld), helloWorld.length) { @Override protected void onMaxLength(final long max, final long readCount) { boolRef.set(true); } }) { assertTrue(bounded.markSupported()); assertEquals(helloWorld.length, bounded.getMaxCount()); assertEquals(helloWorld.length, bounded.getMaxLength()); assertEquals(0, bounded.getCount()); assertEquals(bounded.getMaxCount(), bounded.getRemaining()); assertEquals(bounded.getMaxLength(), bounded.getRemaining()); assertFalse(boolRef.get()); int readCount = 0; for (int i = 0; i < helloWorld.length; i++) { assertEquals(helloWorld[i], bounded.read(), "limit = length byte[" + i + "]"); readCount++; assertEquals(helloWorld.length, bounded.getMaxCount()); assertEquals(helloWorld.length, bounded.getMaxLength()); assertEquals(readCount, bounded.getCount()); assertEquals(bounded.getMaxCount() - readCount, bounded.getRemaining()); assertEquals(bounded.getMaxLength() - readCount, bounded.getRemaining()); } assertEquals(-1, bounded.read(), "limit = length end"); assertEquals(0, bounded.available()); assertEquals(helloWorld.length, bounded.getMaxLength()); assertEquals(readCount, bounded.getCount()); assertEquals(bounded.getMaxLength() - readCount, bounded.getRemaining()); assertTrue(boolRef.get()); // should be invariant assertTrue(bounded.markSupported()); } // limit > length boolRef.set(false); final int length2 = helloWorld.length + 1; try (BoundedInputStream bounded = new BoundedInputStream(new ByteArrayInputStream(helloWorld), length2) { @Override protected void onMaxLength(final long max, final long readCount) { boolRef.set(true); } }) { assertTrue(bounded.markSupported()); assertEquals(length2, bounded.getMaxLength()); assertEquals(0, bounded.getCount()); assertEquals(bounded.getMaxLength(), bounded.getRemaining()); assertFalse(boolRef.get()); int readCount = 0; for (int i = 0; i < helloWorld.length; i++) { assertEquals(helloWorld[i], bounded.read(), "limit > length byte[" + i + "]"); readCount++; assertEquals(length2, bounded.getMaxLength()); assertEquals(readCount, bounded.getCount()); assertEquals(bounded.getMaxLength() - readCount, bounded.getRemaining()); } assertEquals(0, bounded.available()); assertEquals(-1, bounded.read(), "limit > length end"); assertEquals(length2, bounded.getMaxLength()); assertEquals(readCount, bounded.getCount()); assertEquals(bounded.getMaxLength() - readCount, bounded.getRemaining()); assertFalse(boolRef.get()); // should be invariant assertTrue(bounded.markSupported()); } // limit < length boolRef.set(false); try (BoundedInputStream bounded = new BoundedInputStream(new ByteArrayInputStream(helloWorld), hello.length) { @Override protected void onMaxLength(final long max, final long readCount) { boolRef.set(true); } }) { assertTrue(bounded.markSupported()); assertEquals(hello.length, bounded.getMaxLength()); assertEquals(0, bounded.getCount()); assertEquals(bounded.getMaxLength(), bounded.getRemaining()); assertFalse(boolRef.get()); int readCount = 0; for (int i = 0; i < hello.length; i++) { assertEquals(hello[i], bounded.read(), "limit < length byte[" + i + "]"); readCount++; assertEquals(hello.length, bounded.getMaxLength()); assertEquals(readCount, bounded.getCount()); assertEquals(bounded.getMaxLength() - readCount, bounded.getRemaining()); } assertEquals(-1, bounded.read(), "limit < length end"); assertEquals(hello.length, bounded.getMaxLength()); assertEquals(readCount, bounded.getCount()); assertEquals(bounded.getMaxLength() - readCount, bounded.getRemaining()); assertTrue(boolRef.get()); // should be invariant assertTrue(bounded.markSupported()); } } @Test public void testReadArray() throws Exception { final byte[] helloWorld = "Hello World".getBytes(StandardCharsets.UTF_8); final byte[] hello = "Hello".getBytes(StandardCharsets.UTF_8); try (BoundedInputStream bounded = BoundedInputStream.builder().setInputStream(new ByteArrayInputStream(helloWorld)).get()) { assertTrue(bounded.markSupported()); compare("limit = -1", helloWorld, IOUtils.toByteArray(bounded)); // should be invariant assertTrue(bounded.markSupported()); } try (BoundedInputStream bounded = BoundedInputStream.builder().setInputStream(new ByteArrayInputStream(helloWorld)).setMaxCount(0).get()) { assertTrue(bounded.markSupported()); compare("limit = 0", IOUtils.EMPTY_BYTE_ARRAY, IOUtils.toByteArray(bounded)); // should be invariant assertTrue(bounded.markSupported()); } try (BoundedInputStream bounded = BoundedInputStream.builder().setInputStream(new ByteArrayInputStream(helloWorld)) .setMaxCount(helloWorld.length).get()) { assertTrue(bounded.markSupported()); compare("limit = length", helloWorld, IOUtils.toByteArray(bounded)); // should be invariant assertTrue(bounded.markSupported()); } try (BoundedInputStream bounded = BoundedInputStream.builder().setInputStream(new ByteArrayInputStream(helloWorld)) .setMaxCount(helloWorld.length + 1).get()) { assertTrue(bounded.markSupported()); compare("limit > length", helloWorld, IOUtils.toByteArray(bounded)); // should be invariant assertTrue(bounded.markSupported()); } try (BoundedInputStream bounded = BoundedInputStream.builder().setInputStream(new ByteArrayInputStream(helloWorld)) .setMaxCount(helloWorld.length - 6).get()) { assertTrue(bounded.markSupported()); compare("limit < length", hello, IOUtils.toByteArray(bounded)); // should be invariant assertTrue(bounded.markSupported()); } } @SuppressWarnings("deprecation") @Test public void testReadSingle() throws Exception { final byte[] helloWorld = "Hello World".getBytes(StandardCharsets.UTF_8); final byte[] hello = "Hello".getBytes(StandardCharsets.UTF_8); // limit = length try (BoundedInputStream bounded = new BoundedInputStream(new ByteArrayInputStream(helloWorld), helloWorld.length)) { assertTrue(bounded.markSupported()); for (int i = 0; i < helloWorld.length; i++) { assertEquals(helloWorld[i], bounded.read(), "limit = length byte[" + i + "]"); } assertEquals(-1, bounded.read(), "limit = length end"); // should be invariant assertTrue(bounded.markSupported()); } // limit > length try (BoundedInputStream bounded = new BoundedInputStream(new ByteArrayInputStream(helloWorld), helloWorld.length + 1)) { assertTrue(bounded.markSupported()); for (int i = 0; i < helloWorld.length; i++) { assertEquals(helloWorld[i], bounded.read(), "limit > length byte[" + i + "]"); } assertEquals(-1, bounded.read(), "limit > length end"); // should be invariant assertTrue(bounded.markSupported()); } // limit < length try (BoundedInputStream bounded = new BoundedInputStream(new ByteArrayInputStream(helloWorld), hello.length)) { assertTrue(bounded.markSupported()); for (int i = 0; i < hello.length; i++) { assertEquals(hello[i], bounded.read(), "limit < length byte[" + i + "]"); } assertEquals(-1, bounded.read(), "limit < length end"); // should be invariant assertTrue(bounded.markSupported()); } } @Test public void testReset() throws Exception { final byte[] helloWorld = "Hello World".getBytes(StandardCharsets.UTF_8); final byte[] hello = "Hello".getBytes(StandardCharsets.UTF_8); // limit = -1 try (BoundedInputStream bounded = BoundedInputStream.builder().setInputStream(new ByteArrayInputStream(helloWorld)).get()) { assertTrue(bounded.markSupported()); bounded.reset(); compare("limit = -1", helloWorld, IOUtils.toByteArray(bounded)); // should be invariant assertTrue(bounded.markSupported()); // again bounded.reset(); compare("limit = -1", helloWorld, IOUtils.toByteArray(bounded)); // should be invariant assertTrue(bounded.markSupported()); } // limit = 0 try (BoundedInputStream bounded = BoundedInputStream.builder().setInputStream(new ByteArrayInputStream(helloWorld)).setMaxCount(0).get()) { assertTrue(bounded.markSupported()); bounded.reset(); compare("limit = 0", IOUtils.EMPTY_BYTE_ARRAY, IOUtils.toByteArray(bounded)); // should be invariant assertTrue(bounded.markSupported()); // again bounded.reset(); compare("limit = 0", IOUtils.EMPTY_BYTE_ARRAY, IOUtils.toByteArray(bounded)); // should be invariant assertTrue(bounded.markSupported()); } // limit = length try (BoundedInputStream bounded = BoundedInputStream.builder().setInputStream(new ByteArrayInputStream(helloWorld)) .setMaxCount(helloWorld.length).get()) { assertTrue(bounded.markSupported()); bounded.reset(); compare("limit = length", helloWorld, IOUtils.toByteArray(bounded)); // should be invariant assertTrue(bounded.markSupported()); // again bounded.reset(); compare("limit = length", helloWorld, IOUtils.toByteArray(bounded)); // should be invariant assertTrue(bounded.markSupported()); } // limit > length try (BoundedInputStream bounded = BoundedInputStream.builder().setInputStream(new ByteArrayInputStream(helloWorld)) .setMaxCount(helloWorld.length + 1).get()) { assertTrue(bounded.markSupported()); bounded.reset(); compare("limit > length", helloWorld, IOUtils.toByteArray(bounded)); // should be invariant assertTrue(bounded.markSupported()); // again bounded.reset(); compare("limit > length", helloWorld, IOUtils.toByteArray(bounded)); // should be invariant assertTrue(bounded.markSupported()); } // limit < length try (BoundedInputStream bounded = BoundedInputStream.builder().setInputStream(new ByteArrayInputStream(helloWorld)) .setMaxCount(helloWorld.length - 6).get()) { assertTrue(bounded.markSupported()); bounded.reset(); compare("limit < length", hello, IOUtils.toByteArray(bounded)); // should be invariant assertTrue(bounded.markSupported()); // again bounded.reset(); compare("limit < length", hello, IOUtils.toByteArray(bounded)); // should be invariant assertTrue(bounded.markSupported()); } } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/BoundedReaderTest.java0100644 0000000 0000000 00000016736 14603604450 031152 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * 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.time.Duration; import java.util.Arrays; import java.util.concurrent.atomic.AtomicBoolean; import org.apache.commons.io.FileUtils; import org.apache.commons.io.file.TempFile; import org.junit.jupiter.api.Test; /** * Tests {@link BoundedReader}. */ public class BoundedReaderTest { private static final Duration TIMEOUT = Duration.ofSeconds(10); 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 testCloseTest() throws IOException { final AtomicBoolean closed = new AtomicBoolean(); try (Reader sr = new BufferedReader(new StringReader("01234567890")) { @Override public void close() throws IOException { closed.set(true); super.close(); } }) { try (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 } } } public void testLineNumberReaderAndFileReaderLastLine(final String data) throws IOException { try (TempFile path = TempFile.create(getClass().getSimpleName(), ".txt")) { final File file = path.toFile(); FileUtils.write(file, data, StandardCharsets.ISO_8859_1); try (Reader source = Files.newBufferedReader(file.toPath())) { testLineNumberReader(source); } } } @Test public void testLineNumberReaderAndFileReaderLastLineEolNo() { assertTimeout(TIMEOUT, () -> testLineNumberReaderAndFileReaderLastLine(STRING_END_NO_EOL)); } @Test public void testLineNumberReaderAndFileReaderLastLineEolYes() { assertTimeout(TIMEOUT, () -> testLineNumberReaderAndFileReaderLastLine(STRING_END_EOL)); } @Test public void testLineNumberReaderAndStringReaderLastLineEolNo() { assertTimeout(TIMEOUT, () -> testLineNumberReader(new StringReader(STRING_END_NO_EOL))); } @Test public void testLineNumberReaderAndStringReaderLastLineEolYes() { assertTimeout(TIMEOUT, () -> testLineNumberReader(new StringReader(STRING_END_EOL))); } @Test public void testMarkReset() throws IOException { try (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 testMarkResetFromOffset1() throws IOException { try (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 testMarkResetMarkMore() throws IOException { try (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 testMarkResetWithMarkOutsideBoundedReaderMax() throws IOException { try (BoundedReader mr = new BoundedReader(sr, 3)) { mr.mark(4); mr.read(); mr.read(); mr.read(); assertEquals(-1, mr.read()); } } @Test public void testMarkResetWithMarkOutsideBoundedReaderMaxAndInitialOffset() throws IOException { try (BoundedReader mr = new BoundedReader(sr, 3)) { mr.read(); mr.mark(3); mr.read(); mr.read(); assertEquals(-1, mr.read()); } } @Test public void testReadBytesEOF() { assertTimeout(TIMEOUT, () -> { final BoundedReader mr = new BoundedReader(sr, 3); try (BufferedReader br = new BufferedReader(mr)) { br.readLine(); br.readLine(); } }); } @Test public void testReadMulti() throws IOException { try (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 testReadMultiWithOffset() throws IOException { try (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 testReadTillEnd() throws IOException { try (BoundedReader mr = new BoundedReader(sr, 3)) { mr.read(); mr.read(); mr.read(); assertEquals(-1, mr.read()); } } @Test public void testShortReader() throws IOException { try (BoundedReader mr = new BoundedReader(shortReader, 3)) { mr.read(); mr.read(); assertEquals(-1, mr.read()); } } @Test public void testSkipTest() throws IOException { try (BoundedReader mr = new BoundedReader(sr, 3)) { mr.skip(2); mr.read(); assertEquals(-1, mr.read()); } } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/BrokenInputStreamTest.java0100644 0000000 0000000 00000013124 14603604450 032047 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.IOException; import java.io.InputStream; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; /** * Tests {@link BrokenInputStream}. */ public class BrokenInputStreamTest { private static BrokenInputStream createBrokenInputStream(final Throwable exception) { if (exception instanceof IOException) { return new BrokenInputStream((IOException) exception); } return new BrokenInputStream(exception); } @ParameterizedTest @MethodSource("org.apache.commons.io.BrokenTestFactories#parameters") public void testAvailable(final Class clazz) throws Exception { final Throwable exception = clazz.newInstance(); @SuppressWarnings("resource") final BrokenInputStream stream = createBrokenInputStream(exception); assertEquals(exception, assertThrows(clazz, () -> stream.available())); } @ParameterizedTest @MethodSource("org.apache.commons.io.BrokenTestFactories#parameters") public void testClose(final Class clazz) throws Exception { final Throwable exception = clazz.newInstance(); @SuppressWarnings("resource") final BrokenInputStream stream = createBrokenInputStream(exception); assertEquals(exception, assertThrows(clazz, () -> stream.close())); } @Test public void testInstance() { assertNotNull(BrokenInputStream.INSTANCE); } @Test public void testIO469() throws Throwable { // The exception handling and nested blocks here look ugly. // Do NOT try to rationalize them by combining them, using try-with-resources or assertThrows, // or any similar improvements one would make in normal code. This tests // a very specific bug that comes up in unusual exception structures like this. // If this is improved, that bug will no longer be tested. final InputStream in = new BrokenInputStream(); Throwable localThrowable2 = null; try { try { in.read(); } catch (Throwable localThrowable1) { localThrowable2 = localThrowable1; throw localThrowable1; } finally { try { in.close(); } catch (Throwable x2) { localThrowable2.addSuppressed(x2); } } } catch (IOException expected) { final Throwable[] suppressed = expected.getSuppressed(); assertEquals(1, suppressed.length); } } @ParameterizedTest @MethodSource("org.apache.commons.io.BrokenTestFactories#parameters") public void testRead(final Class clazz) throws Exception { final Throwable exception = clazz.newInstance(); @SuppressWarnings("resource") final BrokenInputStream stream = createBrokenInputStream(exception); assertEquals(exception, assertThrows(clazz, () -> stream.read())); assertEquals(exception, assertThrows(clazz, () -> stream.read(new byte[1]))); assertEquals(exception, assertThrows(clazz, () -> stream.read(new byte[1], 0, 1))); } @ParameterizedTest @MethodSource("org.apache.commons.io.BrokenTestFactories#parameters") public void testReset(final Class clazz) throws Exception { final Throwable exception = clazz.newInstance(); @SuppressWarnings("resource") final BrokenInputStream stream = createBrokenInputStream(exception); assertEquals(exception, assertThrows(clazz, () -> stream.reset())); } @ParameterizedTest @MethodSource("org.apache.commons.io.BrokenTestFactories#parameters") public void testSkip(final Class clazz) throws Exception { final Throwable exception = clazz.newInstance(); @SuppressWarnings("resource") final BrokenInputStream stream = createBrokenInputStream(exception); assertEquals(exception, assertThrows(clazz, () -> stream.skip(1))); } @Test public void testTryWithResources() { final IOException thrown = assertThrows(IOException.class, () -> { try (InputStream newStream = new BrokenInputStream()) { newStream.read(); } }); assertEquals("Broken input stream", thrown.getMessage()); final Throwable[] suppressed = thrown.getSuppressed(); assertEquals(1, suppressed.length); assertEquals(IOException.class, suppressed[0].getClass()); assertEquals("Broken input stream", suppressed[0].getMessage()); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/BrokenReaderTest.java0100644 0000000 0000000 00000013047 14603604450 031002 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.IOException; import java.io.Reader; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; /** * Tests {@link BrokenReader}. */ public class BrokenReaderTest { private static BrokenReader createBrokenReader(final Throwable exception) { if (exception instanceof IOException) { return new BrokenReader((IOException) exception); } return new BrokenReader(exception); } @ParameterizedTest @MethodSource("org.apache.commons.io.BrokenTestFactories#parameters") public void testClose(final Class clazz) throws Exception { final Throwable exception = clazz.newInstance(); @SuppressWarnings("resource") final BrokenReader brokenReader = createBrokenReader(exception); assertEquals(exception, assertThrows(clazz, () -> brokenReader.close())); } @Test public void testInstance() { assertNotNull(BrokenReader.INSTANCE); } @ParameterizedTest @MethodSource("org.apache.commons.io.BrokenTestFactories#parameters") public void testMark(final Class clazz) throws Exception { final Throwable exception = clazz.newInstance(); @SuppressWarnings("resource") final BrokenReader brokenReader = createBrokenReader(exception); assertEquals(exception, assertThrows(clazz, () -> brokenReader.mark(1))); } @ParameterizedTest @MethodSource("org.apache.commons.io.BrokenTestFactories#parameters") public void testRead(final Class clazz) throws Exception { final Throwable exception = clazz.newInstance(); @SuppressWarnings("resource") final BrokenReader brokenReader = createBrokenReader(exception); assertEquals(exception, assertThrows(clazz, () -> brokenReader.read())); } @ParameterizedTest @MethodSource("org.apache.commons.io.BrokenTestFactories#parameters") public void testReadCharArray(final Class clazz) throws Exception { final Throwable exception = clazz.newInstance(); @SuppressWarnings("resource") final BrokenReader brokenReader = createBrokenReader(exception); assertEquals(exception, assertThrows(clazz, () -> brokenReader.read(new char[1]))); } @ParameterizedTest @MethodSource("org.apache.commons.io.BrokenTestFactories#parameters") public void testReadCharArrayIndexed(final Class clazz) throws Exception { final Throwable exception = clazz.newInstance(); @SuppressWarnings("resource") final BrokenReader brokenReader = createBrokenReader(exception); assertEquals(exception, assertThrows(clazz, () -> brokenReader.read(new char[1], 0, 1))); } @ParameterizedTest @MethodSource("org.apache.commons.io.BrokenTestFactories#parameters") public void testReady(final Class clazz) throws Exception { final Throwable exception = clazz.newInstance(); @SuppressWarnings("resource") final BrokenReader brokenReader = createBrokenReader(exception); assertEquals(exception, assertThrows(clazz, () -> brokenReader.ready())); } @ParameterizedTest @MethodSource("org.apache.commons.io.BrokenTestFactories#parameters") public void testReset(final Class clazz) throws Exception { final Throwable exception = clazz.newInstance(); @SuppressWarnings("resource") final BrokenReader brokenReader = createBrokenReader(exception); assertEquals(exception, assertThrows(clazz, () -> brokenReader.reset())); } @ParameterizedTest @MethodSource("org.apache.commons.io.BrokenTestFactories#parameters") public void testSkip(final Class clazz) throws Exception { final Throwable exception = clazz.newInstance(); @SuppressWarnings("resource") final BrokenReader brokenReader = createBrokenReader(exception); assertEquals(exception, assertThrows(clazz, () -> brokenReader.skip(1))); } @Test public void testTryWithResources() { final IOException thrown = assertThrows(IOException.class, () -> { try (Reader newReader = new BrokenReader()) { newReader.read(); } }); assertEquals("Broken reader", thrown.getMessage()); final Throwable[] suppressed = thrown.getSuppressed(); assertEquals(1, suppressed.length); assertEquals(IOException.class, suppressed[0].getClass()); assertEquals("Broken reader", suppressed[0].getMessage()); } } ././@LongLink0100644 0000000 0000000 00000000150 14603604450 011631 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/BufferedFileChannelInputStreamTest.javacommons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/BufferedFileChannelInputStreamTest.j0100644 0000000 0000000 00000004726 14603604450 033762 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.assertThrows; import java.io.IOException; import java.io.InputStream; import java.nio.file.StandardOpenOption; 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 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 size BufferedFileChannelInputStream.builder().setPath(inputFile).get(), // default BufferedFileChannelInputStream.builder().setPath(inputFile).setBufferSize(123).get(), // small, unaligned buffer size BufferedFileChannelInputStream.builder().setURI(inputFile.toUri()).setBufferSize(1024).get(), // URI and buffer size BufferedFileChannelInputStream.builder().setPath(inputFile).setOpenOptions(StandardOpenOption.READ).get(), // open options }; //@formatter:on } @Test public void testBuilderGet() { // java.lang.IllegalStateException: origin == null assertThrows(IllegalStateException.class, () -> BufferedFileChannelInputStream.builder().get()); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/ByteBufferCleanerTest.java0100644 0000000 0000000 00000003545 14603604450 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; import static org.junit.jupiter.api.Assertions.assertTrue; import java.nio.ByteBuffer; import org.apache.commons.lang3.RandomUtils; import org.junit.jupiter.api.Test; /** * Tests {@code ByteBufferCleaner}. */ public class ByteBufferCleanerTest { @Test void testCleanEmpty() { final ByteBuffer buffer = ByteBuffer.allocateDirect(10); // There is no way verify that the buffer has been cleaned up, we are just verifying that // clean() doesn't blow up ByteBufferCleaner.clean(buffer); } @Test void testCleanFull() { final ByteBuffer buffer = ByteBuffer.allocateDirect(10); buffer.put(RandomUtils.nextBytes(10), 0, 10); // There is no way verify that the buffer has been cleaned up, we are just verifying that // clean() doesn't blow up ByteBufferCleaner.clean(buffer); } @Test void testSupported() { assertTrue(ByteBufferCleaner.isSupported(), "ByteBufferCleaner does not work on this platform, please investigate and fix"); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/CharSequenceInputStreamTest.java0100644 0000000 0000000 00000055075 14603604450 033210 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.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.IOException; import java.io.InputStream; import java.io.StringReader; 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.nio.charset.StandardCharsets; import java.nio.charset.UnmappableCharacterException; import java.util.Random; import org.apache.commons.io.CharsetsTest; import org.apache.commons.io.IOUtils; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; public class CharSequenceInputStreamTest { private static final String UTF_16 = StandardCharsets.UTF_16.name(); private static final String UTF_8 = StandardCharsets.UTF_8.name(); 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 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 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); } /** * IO-781 available() returns 2 but only 1 byte is read afterwards. */ @Test public void testAvailable() throws IOException { final Charset charset = Charset.forName("Big5"); final CharSequenceInputStream in = new CharSequenceInputStream("\uD800\uDC00", charset); final int available = in.available(); final byte[] data = new byte[available]; final int bytesRead = in.read(data); assertEquals(available, bytesRead); } @ParameterizedTest(name = "{0}") @MethodSource(CharsetsTest.AVAIL_CHARSETS) public void testAvailable(final String csName) throws Exception { // prevent java.lang.UnsupportedOperationException at sun.nio.cs.ext.ISO2022_CN.newEncoder. // also try and avoid the following exception // 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 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)); } } 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 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) @ParameterizedTest(name = "{0}") @MethodSource(CharsetsTest.AVAIL_CHARSETS) public void testBufferedRead_AvailableCharset(final String csName) throws IOException { // prevent java.lang.UnsupportedOperationException at sun.nio.cs.ext.ISO2022_CN.newEncoder. if (isAvailabilityTestableForCharset(csName)) { testBufferedRead(TEST_STRING, csName); } } @ParameterizedTest @MethodSource(CharsetsTest.REQUIRED_CHARSETS) public void testBufferedRead_RequiredCharset(final String csName) throws IOException { testBufferedRead(TEST_STRING, csName); } @Test public void testBufferedRead_UTF8() throws IOException { testBufferedRead(TEST_STRING, UTF_8); } @Test public void testCharacterCodingException() throws IOException { final Charset charset = StandardCharsets.US_ASCII; final CharSequenceInputStream in = CharSequenceInputStream.builder() .setCharsetEncoder(charset.newEncoder().onUnmappableCharacter(CodingErrorAction.REPORT)) .setCharSequence("\u0080") .get(); assertEquals(0, in.available()); assertThrows(UnmappableCharacterException.class, in::read); } 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)) { IOUtils.toCharArray(stream, charset); } try (InputStream stream = CharSequenceInputStream.builder().setCharSequence(new String(inputChars)).setCharset(charset).setBufferSize(512).get()) { IOUtils.toCharArray(stream, charset); } } @ParameterizedTest @MethodSource(CharsetsTest.REQUIRED_CHARSETS) public void testCharsetMismatchInfiniteLoop_RequiredCharsets(final String csName) throws IOException { 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 byte[] data1; final byte[] data2; try (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); data1 = new byte[dataSize]; final int readCount1 = is.read(data1); assertEquals(dataSize, readCount1); is.reset(); // should allow data to be re-read data2 = new byte[dataSize]; final int readCount2 = is.read(data2); assertEquals(dataSize, readCount2); } // 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 { final Charset charset = StandardCharsets.UTF_16; testIO_356_Loop(charset.displayName(), (int) ReaderInputStream.minBufferSize(charset.newEncoder())); } @Test public void testIO_356_Loop_UTF8() throws Exception { final Charset charset = StandardCharsets.UTF_8; testIO_356_Loop(charset.displayName(), (int) ReaderInputStream.minBufferSize(charset.newEncoder())); } @ParameterizedTest @MethodSource(CharsetsTest.REQUIRED_CHARSETS) public void testLargeBufferedRead_RequiredCharsets(final String csName) throws IOException { testBufferedRead(LARGE_TEST_STRING, csName); } @Test public void testLargeBufferedRead_UTF8() throws IOException { testBufferedRead(LARGE_TEST_STRING, UTF_8); } @ParameterizedTest @MethodSource(CharsetsTest.REQUIRED_CHARSETS) public void testLargeSingleByteRead_RequiredCharsets(final String csName) throws IOException { testSingleByteRead(LARGE_TEST_STRING, csName); } @Test public void testLargeSingleByteRead_UTF8() throws IOException { testSingleByteRead(LARGE_TEST_STRING, UTF_8); } // This test doesn't work for charsets that don't create a single byte for each char. // Use testMarkResetMultiByteChars() instead for those cases. 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(); } } @ParameterizedTest @MethodSource(CharsetsTest.REQUIRED_CHARSETS) public void testMarkReset_RequiredCharsets(final String csName) throws Exception { testMarkResetMultiByteChars(csName); } @Test public void testMarkReset_USASCII() throws Exception { testMarkReset(StandardCharsets.US_ASCII.name()); } @Test public void testMarkReset_UTF8() throws Exception { testMarkReset(UTF_8); } private void testMarkResetMultiByteChars(final String csName) throws IOException { // This test quietly skips Charsets that can't handle multibyte characters like ASCII. final String sequenceEnglish = "Test Sequence"; final String sequenceCJK = "\u4e01\u4f23\u5045\u5167\u5289\u53ab"; // Kanji text final String[] sequences = {sequenceEnglish, sequenceCJK}; for (final String testSequence : sequences) { final CharsetEncoder charsetEncoder = Charset.forName(csName).newEncoder(); final ByteBuffer byteBuffer = ByteBuffer.allocate(testSequence.length() * 3); final CharBuffer charBuffer = CharBuffer.wrap(testSequence); final CoderResult result = charsetEncoder.encode(charBuffer, byteBuffer, true); if (result.isUnmappable()) { continue; // Skip character sets that can't handle multibyte characters. } final byte[] expectedBytes = byteBuffer.array(); final int bLength = byteBuffer.position(); final int skip = bLength - 4; try (InputStream r = new CharSequenceInputStream(testSequence, csName)) { assertEquals(skip, r.skip(skip)); r.mark(0); assertEquals(expectedBytes[bLength - 4], (byte) r.read(), csName); assertEquals(expectedBytes[bLength - 3], (byte) r.read(), csName); assertEquals(expectedBytes[bLength - 2], (byte) r.read(), csName); assertEquals(expectedBytes[bLength - 1], (byte) r.read(), csName); assertEquals(-1, (byte) r.read(), csName); r.reset(); assertEquals(expectedBytes[bLength - 4], (byte) r.read(), csName); assertEquals(expectedBytes[bLength - 3], (byte) r.read(), csName); assertEquals(expectedBytes[bLength - 2], (byte) r.read(), csName); assertEquals(expectedBytes[bLength - 1], (byte) r.read(), csName); assertEquals(-1, (byte) r.read(), csName); r.reset(); assertEquals(expectedBytes[bLength - 4], (byte) r.read(), csName); assertEquals(expectedBytes[bLength - 3], (byte) r.read(), csName); assertEquals(expectedBytes[bLength - 2], (byte) r.read(), csName); assertEquals(expectedBytes[bLength - 1], (byte) r.read(), csName); assertEquals(-1, (byte) r.read(), csName); } } } @Test public void testMarkSupported() throws Exception { try (@SuppressWarnings("deprecation") InputStream r = new CharSequenceInputStream("test", UTF_8)) { assertTrue(r.markSupported()); } try (InputStream r = CharSequenceInputStream.builder().setCharSequence("test").setCharset(UTF_8).get()) { assertTrue(r.markSupported()); } } @Test public void testNullCharset() throws IOException { try (CharSequenceInputStream in = new CharSequenceInputStream("A", (Charset) null)) { IOUtils.toByteArray(in); assertEquals(Charset.defaultCharset(), in.getCharsetEncoder().charset()); } try (CharSequenceInputStream in = CharSequenceInputStream.builder().setCharSequence("test").setCharset((Charset) null).get()) { IOUtils.toByteArray(in); assertEquals(Charset.defaultCharset(), in.getCharsetEncoder().charset()); } } @Test public void testNullCharsetName() throws IOException { try (CharSequenceInputStream in = new CharSequenceInputStream("A", (String) null)) { IOUtils.toByteArray(in); assertEquals(Charset.defaultCharset(), in.getCharsetEncoder().charset()); } try (CharSequenceInputStream in = CharSequenceInputStream.builder().setCharSequence("test").setCharset((String) null).get()) { IOUtils.toByteArray(in); assertEquals(Charset.defaultCharset(), in.getCharsetEncoder().charset()); } } 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)); } } @ParameterizedTest @MethodSource(CharsetsTest.REQUIRED_CHARSETS) public void testReadZero_RequiredCharsets(final String csName) throws Exception { testReadZero(csName); } private void testResetBeforeEnd(final CharSequenceInputStream inputStream) throws IOException { 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()); } @Test public void testResetBeforeEndSetCharSequence() throws IOException { try (final CharSequenceInputStream inputStream = CharSequenceInputStream.builder().setCharSequence("1234").get()) { testResetBeforeEnd(inputStream); } } @Test public void testResetCharset() { assertNotNull(CharSequenceInputStream.builder().setReader(new StringReader("\uD800")).setCharset((Charset) null).getCharset()); } @Test public void testResetCharsetEncoder() { assertNotNull(CharSequenceInputStream.builder().setReader(new StringReader("\uD800")).setCharsetEncoder(null).getCharsetEncoder()); } @Test public void testResetCharsetName() { assertNotNull(CharSequenceInputStream.builder().setReader(new StringReader("\uD800")).setCharset((String) null).getCharset()); } 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()); } } @ParameterizedTest @MethodSource(CharsetsTest.REQUIRED_CHARSETS) public void testSingleByteRead_RequiredCharsets(final String csName) throws IOException { 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); } @ParameterizedTest @MethodSource(CharsetsTest.REQUIRED_CHARSETS) public void testSkip_RequiredCharsets(final String csName) throws Exception { try (InputStream r = new CharSequenceInputStream("test", csName)) { assertEquals(1, r.skip(1)); assertEquals(2, r.skip(2)); r.skip(100); assertEquals(-1, r.read(), csName); } } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/CharSequenceReaderTest.java0100644 0000000 0000000 00000030136 14603604450 032126 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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]; 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 + "'"); } } @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 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 public void testMark() throws IOException { try (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 (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 testMarkSupported() throws Exception { try (Reader reader = new CharSequenceReader("FooBar")) { assertTrue(reader.markSupported()); } } @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 (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 (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 (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 (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 (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 (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)); } } @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 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()); } } @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 @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()); } } ././@LongLink0100644 0000000 0000000 00000000153 14603604450 011634 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/CharacterFilterReaderIntPredicateTest.javacommons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/CharacterFilterReaderIntPredicateTes0100644 0000000 0000000 00000011726 14603604450 034016 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.16.1-src/src/test/java/org/apache/commons/io/input/CharacterFilterReaderTest.java0100644 0000000 0000000 00000010516 14603604450 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.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.16.1-src/src/test/java/org/apache/commons/io/input/CharacterSetFilterReaderTest.java0100644 0000000 0000000 00000014152 14603604450 033276 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 (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.16.1-src/src/test/java/org/apache/commons/io/input/ChecksumInputStreamTest.java0100644 0000000 0000000 00000015320 14603604450 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.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.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.util.zip.Adler32; import java.util.zip.CRC32; import org.junit.jupiter.api.Test; /** * Tests {@link ChecksumInputStream}. */ public class ChecksumInputStreamTest { @Test public void testDefaultThresholdFailure() throws IOException { final byte[] byteArray = new byte[3]; final Adler32 adler32 = new Adler32(); try (ChecksumInputStream checksum = ChecksumInputStream.builder() // @formatter:off .setByteArray(byteArray) .setChecksum(adler32) .setExpectedChecksumValue((byte) -68) .get()) { // @formatter:on assertEquals(0, checksum.getByteCount()); assertEquals(-1, checksum.getRemaining()); // Ask to read one more byte than there is, we get the correct byte count. assertEquals(byteArray.length, checksum.read(new byte[byteArray.length + 1])); // Next read is at EOF assertThrows(IOException.class, () -> checksum.read(new byte[1])); assertEquals(byteArray.length, checksum.getByteCount()); assertEquals(-4, checksum.getRemaining()); } } @Test public void testDefaultThresholdSuccess() throws IOException { // sanity-check final Adler32 sanityCheck = new Adler32(); final byte[] byteArray = new byte[3]; sanityCheck.update(byteArray); final long expectedChecksum = sanityCheck.getValue(); // actual final Adler32 adler32 = new Adler32(); try (ChecksumInputStream checksum = ChecksumInputStream.builder() // @formatter:off .setByteArray(byteArray) .setChecksum(adler32) .setExpectedChecksumValue(expectedChecksum) .get()) { // @formatter:on assertEquals(0, checksum.getByteCount()); assertEquals(-1, checksum.getRemaining()); assertEquals(3, checksum.read(byteArray)); assertEquals(byteArray.length, checksum.getByteCount()); assertEquals(-4, checksum.getRemaining()); assertEquals(-1, checksum.read(byteArray)); assertEquals(byteArray.length, checksum.getByteCount()); assertEquals(-4, checksum.getRemaining()); } } @Test public void testReadTakingByteArrayThrowsException() throws IOException { final Adler32 adler32 = new Adler32(); final byte[] byteArray = new byte[3]; final long sizeThreshold = -1859L; try (ChecksumInputStream checksum = ChecksumInputStream.builder() // @formatter:off .setByteArray(byteArray) .setChecksum(adler32) .setExpectedChecksumValue((byte) -68) .setCountThreshold(sizeThreshold) .get()) { // @formatter:on assertEquals(0, checksum.getByteCount()); assertEquals(sizeThreshold, checksum.getRemaining()); // Ask to read one more byte than there is. assertEquals(byteArray.length, checksum.read(new byte[byteArray.length + 1])); // Next read is at EOF assertThrows(IOException.class, () -> checksum.read(new byte[1])); assertEquals(byteArray.length, checksum.getByteCount()); assertEquals(sizeThreshold - byteArray.length, checksum.getRemaining()); } } @Test public void testReadTakingNoArgumentsThrowsException() throws IOException { final CRC32 crc32 = new CRC32(); final byte[] byteArray = new byte[9]; try (ChecksumInputStream checksum = ChecksumInputStream.builder() // @formatter:off .setByteArray(byteArray) .setChecksum(crc32) .setExpectedChecksumValue((byte) 1) .setCountThreshold(1) .get()) { // @formatter:on assertEquals(0, checksum.getByteCount()); assertEquals(1, checksum.getRemaining()); assertThrows(IOException.class, () -> checksum.read()); assertEquals(1, checksum.getByteCount()); assertEquals(0, checksum.getRemaining()); } } @Test public void testSkip() throws IOException { // sanity-check final CRC32 sanityCheck = new CRC32(); final byte[] byteArray = new byte[4]; sanityCheck.update(byteArray); final long expectedChecksum = sanityCheck.getValue(); // actual final CRC32 crc32 = new CRC32(); final InputStream byteArrayInputStream = new ByteArrayInputStream(byteArray); try (ChecksumInputStream checksum = ChecksumInputStream.builder() // @formatter:off .setInputStream(byteArrayInputStream) .setChecksum(crc32) .setExpectedChecksumValue(expectedChecksum) .setCountThreshold(33) .get()) { // @formatter:on assertEquals(0, checksum.getByteCount()); assertEquals(4, checksum.read(byteArray)); assertEquals(byteArray.length, checksum.getByteCount()); assertEquals(29, checksum.getRemaining()); final long skipReturnValue = checksum.skip((byte) 1); assertEquals(byteArray.length, checksum.getByteCount()); assertEquals(29, checksum.getRemaining()); assertEquals(558161692L, crc32.getValue()); assertEquals(0, byteArrayInputStream.available()); assertArrayEquals(new byte[4], byteArray); assertEquals(0L, skipReturnValue); assertEquals(29, checksum.getRemaining()); } } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/CircularInputStreamTest.java0100644 0000000 0000000 00000007214 14603604450 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.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 14603604450 011636 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/ClassLoaderObjectInputStreamTest.javacommons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/ClassLoaderObjectInputStreamTest.jav0100644 0000000 0000000 00000014460 14603604450 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.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; import org.apache.commons.lang3.SerializationUtils; /** * Tests {@link ClassLoaderObjectInputStream}. */ 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 */ private enum E { A, B, C } private static final 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; } private boolean equalObject(final Object other) { if (this.o == null) { return other == null; } return o.equals(other); } @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; } @Override public int hashCode() { return super.hashCode(); } } @org.junit.jupiter.api.Test public void testExpected() throws Exception { final Boolean input = Boolean.FALSE; final InputStream bais = new ByteArrayInputStream(SerializationUtils.serialize(input)); try (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 Long input = 123L; final InputStream bais = new ByteArrayInputStream(SerializationUtils.serialize(input)); try (ClassLoaderObjectInputStream clois = new ClassLoaderObjectInputStream(getClass().getClassLoader(), bais)) { final Object result = clois.readObject(); assertEquals(input, result); } } @org.junit.jupiter.api.Test public void testObject1() throws Exception { final Test input = new Test(123, null); final InputStream bais = new ByteArrayInputStream(SerializationUtils.serialize(input)); try (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 Test input = new Test(123, 0); final InputStream bais = new ByteArrayInputStream(SerializationUtils.serialize(input)); try (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 long input = 12345L; final ByteArrayOutputStream baos = new ByteArrayOutputStream(); try (final ObjectOutputStream oos = new ObjectOutputStream(baos)) { oos.writeLong(input); } final InputStream bais = new ByteArrayInputStream(baos.toByteArray()); try (ClassLoaderObjectInputStream clois = new ClassLoaderObjectInputStream(getClass().getClassLoader(), bais)) { final long result = clois.readLong(); assertEquals(input, result); } } @org.junit.jupiter.api.Test public void testResolveProxyClass() throws Exception { final InputStream bais = new ByteArrayInputStream(SerializationUtils.serialize(Boolean.FALSE)); try (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 InputStream bais = new ByteArrayInputStream(SerializationUtils.serialize(Boolean.FALSE)); try (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.16.1-src/src/test/java/org/apache/commons/io/input/CloseShieldInputStreamTest.java0100644 0000000 0000000 00000003617 14603604450 033033 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; /** * Tests {@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.16.1-src/src/test/java/org/apache/commons/io/input/CloseShieldReaderTest.java0100644 0000000 0000000 00000003566 14603604450 031765 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; /** * Tests {@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.16.1-src/src/test/java/org/apache/commons/io/input/ClosedInputStreamTest.java0100644 0000000 0000000 00000004416 14603604450 032044 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 org.junit.jupiter.api.Test; /** * Tests {@link ClosedInputStream}. */ public class ClosedInputStreamTest { private void assertEof(final ClosedInputStream cis) { assertEquals(EOF, cis.read(), "read()"); } @Test public void testRead() throws Exception { try (ClosedInputStream cis = new ClosedInputStream()) { assertEof(cis); } } @Test public void testReadArray() throws Exception { try (ClosedInputStream cis = new ClosedInputStream()) { assertEquals(EOF, cis.read(new byte[4096])); assertEquals(EOF, cis.read(new byte[1])); assertEquals(EOF, cis.read(new byte[0])); } } @Test public void testReadArrayIndex() throws Exception { try (ClosedInputStream cis = new ClosedInputStream()) { assertEquals(EOF, cis.read(new byte[4096], 0, 1)); assertEquals(EOF, cis.read(new byte[1], 0, 1)); assertEquals(EOF, cis.read(new byte[0], 0, 0)); } } @Test public void testSingleton() throws Exception { try (@SuppressWarnings("deprecation") ClosedInputStream cis = ClosedInputStream.CLOSED_INPUT_STREAM) { assertEof(cis); } try (ClosedInputStream cis = ClosedInputStream.INSTANCE) { assertEof(cis); } } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/ClosedReaderTest.java0100644 0000000 0000000 00000005623 14603604450 030774 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 java.io.IOException; import java.io.Reader; import java.nio.CharBuffer; import org.junit.jupiter.api.Test; /** * Tests {@link ClosedReader}. */ public class ClosedReaderTest { private void assertEof(final Reader reader) throws IOException { assertEquals(EOF, reader.read(), "read()"); } @Test public void testRead() throws IOException { try (Reader reader = new ClosedReader()) { assertEof(reader); } } @Test public void testReadArray() throws Exception { try (Reader reader = new ClosedReader()) { assertEquals(EOF, reader.read(new char[4096])); assertEquals(EOF, reader.read(new char[1])); assertEquals(EOF, reader.read(new char[0])); } } @Test public void testReadArrayIndex() throws Exception { try (Reader reader = new ClosedReader()) { assertEquals(EOF, reader.read(CharBuffer.wrap(new char[4096]))); assertEquals(EOF, reader.read(CharBuffer.wrap(new char[1]))); assertEquals(EOF, reader.read(CharBuffer.wrap(new char[0]))); } } @Test public void testReadCharBuffer() throws Exception { try (Reader reader = new ClosedReader()) { assertEquals(EOF, reader.read(new char[4096])); assertEquals(EOF, reader.read(new char[1])); assertEquals(EOF, reader.read(new char[0])); } } @Test public void testSingleton() throws Exception { try (@SuppressWarnings("deprecation") Reader reader = ClosedReader.CLOSED_READER) { assertEof(reader); } try (Reader reader = ClosedReader.INSTANCE) { assertEof(reader); } } @Test public void testSkip() throws Exception { try (Reader reader = new ClosedReader()) { assertEquals(0, reader.skip(4096)); assertEquals(0, reader.skip(1)); assertEquals(0, reader.skip(0)); } } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/CountingInputStreamTest.java0100644 0000000 0000000 00000015364 14603604450 032425 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 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"; try (CountingInputStream cis = new CountingInputStream(CharSequenceInputStream.builder().setCharSequence(text).get())) { // 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 public void testEOF1() throws Exception { final ByteArrayInputStream bais = new ByteArrayInputStream(new byte[2]); try (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 (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 (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 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); assertThrows(ArithmeticException.class, () -> cis.getCount()); assertThrows(ArithmeticException.class, () -> cis.resetCount()); 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 (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 testSkipping() throws IOException { final String text = "Hello World!"; try (CountingInputStream cis = new CountingInputStream(CharSequenceInputStream.builder().setCharSequence(text).get())) { assertEquals(6, cis.skip(6)); assertEquals(6, cis.getCount()); final byte[] result = new byte[6]; assertEquals(result.length, cis.read(result)); assertEquals("World!", new String(result)); assertEquals(12, cis.getCount()); } } @Test public void testZeroLength1() throws Exception { final ByteArrayInputStream bais = new ByteArrayInputStream(IOUtils.EMPTY_BYTE_ARRAY); try (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 (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 (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()); } } } ././@LongLink0100644 0000000 0000000 00000000145 14603604450 011635 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/InfiniteCircularInputStreamTest.javacommons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/InfiniteCircularInputStreamTest.java0100644 0000000 0000000 00000006601 14603604450 034063 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.16.1-src/src/test/java/org/apache/commons/io/input/MarkShieldInputStreamTest.java0100644 0000000 0000000 00000010230 14603604450 032645 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 { private static final 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); } } @Test public void testMarkIsNoOpWhenUnderlyingDoesNotSupport() throws IOException { try (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 testMarkIsNoOpWhenUnderlyingSupports() throws IOException { try (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 testMarkSupportedIsFalseWhenUnderlyingFalse() throws IOException { // test wrapping an underlying stream which does NOT support marking try (InputStream is = new NullInputStream(64, false, false)) { assertFalse(is.markSupported()); try (MarkShieldInputStream msis = new MarkShieldInputStream(is)) { assertFalse(msis.markSupported()); } } } @Test public void testMarkSupportedIsFalseWhenUnderlyingTrue() throws IOException { // test wrapping an underlying stream which supports marking try (InputStream is = new NullInputStream(64, true, false)) { assertTrue(is.markSupported()); try (MarkShieldInputStream msis = new MarkShieldInputStream(is)) { assertFalse(msis.markSupported()); } } } @Test public void testResetThrowsExceptionWhenUnderlyingDoesNotSupport() throws IOException { // test wrapping an underlying stream which does NOT support marking try (MarkShieldInputStream msis = new MarkShieldInputStream( new NullInputStream(64, false, false))) { assertThrows(UnsupportedOperationException.class, msis::reset); } } @Test public void testResetThrowsExceptionWhenUnderlyingSupports() throws IOException { // test wrapping an underlying stream which supports marking try (MarkShieldInputStream msis = new MarkShieldInputStream( new NullInputStream(64, true, false))) { assertThrows(UnsupportedOperationException.class, msis::reset); } } } ././@LongLink0100644 0000000 0000000 00000000145 14603604450 011635 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/MemoryMappedFileInputStreamTest.javacommons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/MemoryMappedFileInputStreamTest.java0100644 0000000 0000000 00000023677 14603604450 034044 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.lang3.ArrayUtils.EMPTY_BYTE_ARRAY; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; import java.util.Arrays; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.RandomUtils; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; /** * Tests {@link MemoryMappedFileInputStream}. */ public class MemoryMappedFileInputStreamTest { @TempDir Path tempDir; @AfterEach void afterEach() { // Ask to run the garbage collector to clean up memory mapped buffers, // otherwise the temporary files won't be able to be removed when running on // Windows. Calling gc() is just a hint to the VM. System.gc(); Thread.yield(); System.runFinalization(); Thread.yield(); System.gc(); Thread.yield(); System.runFinalization(); Thread.yield(); } private Path createTestFile(final int size) throws IOException { return Files.write(Files.createTempFile(tempDir, null, null), RandomUtils.nextBytes(size)); } private MemoryMappedFileInputStream newStream(final Path file) throws IOException { return MemoryMappedFileInputStream.builder().setPath(file).get(); } private MemoryMappedFileInputStream newStream(final Path file, final int bufferSize) throws IOException { return MemoryMappedFileInputStream.builder().setPath(file).setBufferSize(bufferSize).get(); } @Test void testAlternateBufferSize() throws IOException { // setup final Path file = createTestFile(1024 * 1024); final byte[] expectedData = Files.readAllBytes(file); // test try (InputStream inputStream = newStream(file, 1024)) { // verify assertArrayEquals(expectedData, IOUtils.toByteArray(inputStream)); } } @Test void testEmptyFile() throws IOException { // setup final Path file = createTestFile(0); // test try (InputStream inputStream = newStream(file)) { // verify assertArrayEquals(EMPTY_BYTE_ARRAY, IOUtils.toByteArray(inputStream)); } } @Test void testLargerFile() throws IOException { // setup final Path file = createTestFile(1024 * 1024); final byte[] expectedData = Files.readAllBytes(file); // test try (InputStream inputStream = newStream(file)) { // verify assertArrayEquals(expectedData, IOUtils.toByteArray(inputStream)); } } @Test void testReadAfterClose() throws IOException { // setup final Path file = createTestFile(1 * 1024 * 1024); // test try (InputStream inputStream = newStream(file, 1024)) { inputStream.close(); // verify Assertions.assertThrows(IOException.class, () -> IOUtils.toByteArray(inputStream)); } } @Test void testReadSingleByte() throws IOException { // setup final Path file = createTestFile(2); final byte[] expectedData = Files.readAllBytes(file); // test try (InputStream inputStream = newStream(file, 1024)) { final int b1 = inputStream.read(); final int b2 = inputStream.read(); assertEquals(-1, inputStream.read()); // verify assertArrayEquals(expectedData, new byte[] {(byte) b1, (byte) b2}); } } @Test void testSkipAtStart() throws IOException { // setup final Path file = createTestFile(100); final byte[] expectedData = Files.readAllBytes(file); // test try (InputStream inputStream = newStream(file, 10)) { assertEquals(1, inputStream.skip(1)); final byte[] data = IOUtils.toByteArray(inputStream); // verify assertArrayEquals(Arrays.copyOfRange(expectedData, 1, expectedData.length), data); } } @Test void testSkipEmpty() throws IOException { // setup final Path file = createTestFile(0); // test try (InputStream inputStream = newStream(file)) { assertEquals(0, inputStream.skip(5)); // verify assertArrayEquals(EMPTY_BYTE_ARRAY, IOUtils.toByteArray(inputStream)); } } @Test void testSkipInCurrentBuffer() throws IOException { // setup final Path file = createTestFile(100); final byte[] expectedData = Files.readAllBytes(file); // test try (InputStream inputStream = newStream(file, 10)) { IOUtils.toByteArray(inputStream, 5); assertEquals(3, inputStream.skip(3)); final byte[] data = IOUtils.toByteArray(inputStream); // verify assertArrayEquals(Arrays.copyOfRange(expectedData, 8, expectedData.length), data); } } @ParameterizedTest @ValueSource(ints = {-5, -1, 0}) void testSkipNoop(final int amountToSkip) throws IOException { // setup final Path file = createTestFile(10); final byte[] expectedData = Files.readAllBytes(file); // test try (InputStream inputStream = newStream(file)) { assertEquals(0, inputStream.skip(amountToSkip)); // verify assertArrayEquals(expectedData, IOUtils.toByteArray(inputStream)); } } @Test void testSkipOutOfCurrentBuffer() throws IOException { // setup final Path file = createTestFile(100); final byte[] expectedData = Files.readAllBytes(file); // test try (InputStream inputStream = newStream(file, 10)) { IOUtils.toByteArray(inputStream, 5); assertEquals(6, inputStream.skip(6)); final byte[] data = IOUtils.toByteArray(inputStream); // verify assertArrayEquals(Arrays.copyOfRange(expectedData, 11, expectedData.length), data); } } @Test void testSkipPastEof() throws IOException { // setup final Path file = createTestFile(100); // test try (InputStream inputStream = newStream(file, 10)) { IOUtils.toByteArray(inputStream, 5); assertEquals(95, inputStream.skip(96)); // verify assertArrayEquals(EMPTY_BYTE_ARRAY, IOUtils.toByteArray(inputStream)); } } @Test void testSkipToEndOfCurrentBuffer() throws IOException { // setup final Path file = createTestFile(100); final byte[] expectedData = Files.readAllBytes(file); // test try (InputStream inputStream = newStream(file, 10)) { IOUtils.toByteArray(inputStream, 5); assertEquals(5, inputStream.skip(5)); final byte[] data = IOUtils.toByteArray(inputStream); // verify assertArrayEquals(Arrays.copyOfRange(expectedData, 10, expectedData.length), data); } } @Test void testSkipToEndOfCurrentBufferBuilder() throws IOException { // setup final Path file = createTestFile(100); final byte[] expectedData = Files.readAllBytes(file); // test try (MemoryMappedFileInputStream inputStream = MemoryMappedFileInputStream.builder().setPath(file).setBufferSize(10).get()) { assertEquals(10, inputStream.getBufferSize()); IOUtils.toByteArray(inputStream, 5); assertEquals(5, inputStream.skip(5)); final byte[] data = IOUtils.toByteArray(inputStream); // verify assertArrayEquals(Arrays.copyOfRange(expectedData, 10, expectedData.length), data); } } @Test void testSmallFileBuilder() throws IOException { // setup final Path file = createTestFile(100); final byte[] expectedData = Files.readAllBytes(file); // test try (InputStream inputStream = MemoryMappedFileInputStream.builder().setFile(file.toFile()).get()) { // verify assertArrayEquals(expectedData, IOUtils.toByteArray(inputStream)); } } @Test void testSmallPath() throws IOException { // setup final Path file = createTestFile(100); final byte[] expectedData = Files.readAllBytes(file); // test try (InputStream inputStream = newStream(file)) { // verify assertArrayEquals(expectedData, IOUtils.toByteArray(inputStream)); } } @Test void testSmallPathBuilder() throws IOException { // setup final Path file = createTestFile(100); final byte[] expectedData = Files.readAllBytes(file); // test try (InputStream inputStream = MemoryMappedFileInputStream.builder().setPath(file).get()) { // verify assertArrayEquals(expectedData, IOUtils.toByteArray(inputStream)); } } } ././@LongLink0100644 0000000 0000000 00000000155 14603604450 011636 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/MessageDigestCalculatingInputStreamTest.javacommons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/MessageDigestCalculatingInputStreamT0100644 0000000 0000000 00000007656 14603604450 034103 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.codec.digest.MessageDigestAlgorithms; import org.apache.commons.io.input.MessageDigestCalculatingInputStream.Builder; import org.junit.jupiter.api.Test; /** * Tests {@link MessageDigestCalculatingInputStream}. */ @SuppressWarnings("deprecation") public class MessageDigestCalculatingInputStreamTest { @Test public void testNormalUse() throws Exception { for (int i = 256; i < 8192; i *= 2) { final byte[] buffer = MessageDigestInputStreamTest.generateRandomByteStream(i); final MessageDigest defaultMessageDigest = MessageDigestCalculatingInputStream.getDefaultMessageDigest(); final byte[] defaultExpect = defaultMessageDigest.digest(buffer); // Defaults try (MessageDigestCalculatingInputStream messageDigestInputStream = new MessageDigestCalculatingInputStream(new ByteArrayInputStream(buffer))) { messageDigestInputStream.consume(); assertArrayEquals(defaultExpect, messageDigestInputStream.getMessageDigest().digest()); } try (MessageDigestCalculatingInputStream messageDigestInputStream = MessageDigestCalculatingInputStream.builder() .setInputStream(new ByteArrayInputStream(buffer)).get()) { messageDigestInputStream.consume(); assertArrayEquals(defaultExpect, messageDigestInputStream.getMessageDigest().digest()); } try (MessageDigestCalculatingInputStream messageDigestInputStream = MessageDigestCalculatingInputStream.builder().setByteArray(buffer).get()) { messageDigestInputStream.consume(); assertArrayEquals(defaultExpect, messageDigestInputStream.getMessageDigest().digest()); } // SHA-512 final byte[] sha512Expect = DigestUtils.sha512(buffer); { final Builder builder = MessageDigestCalculatingInputStream.builder(); builder.setMessageDigest(MessageDigestAlgorithms.SHA_512); builder.setInputStream(new ByteArrayInputStream(buffer)); try (MessageDigestCalculatingInputStream messageDigestInputStream = builder.get()) { messageDigestInputStream.consume(); assertArrayEquals(sha512Expect, messageDigestInputStream.getMessageDigest().digest()); } } { final Builder builder = MessageDigestCalculatingInputStream.builder(); builder.setMessageDigest(MessageDigestAlgorithms.SHA_512); builder.setInputStream(new ByteArrayInputStream(buffer)); try (MessageDigestCalculatingInputStream messageDigestInputStream = builder.get()) { messageDigestInputStream.consume(); assertArrayEquals(sha512Expect, messageDigestInputStream.getMessageDigest().digest()); } } } } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/MessageDigestInputStreamTest.java0100644 0000000 0000000 00000005414 14603604450 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.input; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.ByteArrayInputStream; import java.util.Random; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.codec.digest.MessageDigestAlgorithms; import org.junit.jupiter.api.Test; /** * Tests {@link MessageDigestInputStream}. */ public class MessageDigestInputStreamTest { 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 testNoDefault() throws Exception { assertThrows(IllegalStateException.class, () -> MessageDigestInputStream.builder().get()); assertThrows(NullPointerException.class, () -> MessageDigestInputStream.builder().setInputStream(new ByteArrayInputStream(new byte[] { 1 })).get()); } @Test public void testNormalUse() throws Exception { for (int i = 256; i < 8192; i *= 2) { final byte[] buffer = generateRandomByteStream(i); final byte[] expect = DigestUtils.sha512(buffer); try (MessageDigestInputStream messageDigestInputStream = MessageDigestInputStream.builder().setMessageDigest(MessageDigestAlgorithms.SHA_512) .setInputStream(new ByteArrayInputStream(buffer)).get()) { messageDigestInputStream.consume(); assertArrayEquals(expect, messageDigestInputStream.getMessageDigest().digest()); } try (MessageDigestInputStream messageDigestInputStream = MessageDigestInputStream.builder().setByteArray(buffer) .setMessageDigest(DigestUtils.getSha512Digest()).get()) { messageDigestInputStream.consume(); assertArrayEquals(expect, messageDigestInputStream.getMessageDigest().digest()); } } } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/NullInputStreamTest.java0100644 0000000 0000000 00000025165 14603604450 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.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.EOFException; import java.io.IOException; import java.io.InputStream; import org.junit.jupiter.api.Test; import org.junit.platform.commons.util.StringUtils; /** * Tests {@link NullInputStream}. */ public class NullInputStreamTest { 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); } } } /** 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 testEOFException() throws Exception { try (InputStream input = new TestNullInputStream(2, false, true)) { assertEquals(0, input.read(), "Read 1"); assertEquals(1, input.read(), "Read 2"); assertThrows(EOFException.class, () -> input.read()); } } @Test public void testMarkAndReset() throws Exception { int position = 0; final int readLimit = 10; try (InputStream input = new TestNullInputStream(100, true, false)) { assertTrue(input.markSupported(), "Mark Should be Supported"); // No Mark final IOException noMarkException = assertThrows(IOException.class, input::reset); assertEquals("No position has been marked", noMarkException.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 final IOException resetException = assertThrows(IOException.class, input::reset, "Read limit exceeded, expected IOException"); assertEquals("Marked position [" + position + "] is no longer valid - passed the read limit [" + readLimit + "]", resetException.getMessage(), "Read limit IOException message"); } } @Test public void testMarkNotSupported() throws Exception { final InputStream input = new TestNullInputStream(100, false, true); assertFalse(input.markSupported(), "Mark Should NOT be Supported"); final UnsupportedOperationException markException = assertThrows(UnsupportedOperationException.class, () -> input.mark(5)); assertEquals(MARK_RESET_NOT_SUPPORTED, markException.getMessage(), "mark() error message"); final UnsupportedOperationException resetException = assertThrows(UnsupportedOperationException.class, input::reset); assertEquals(MARK_RESET_NOT_SUPPORTED, resetException.getMessage(), "reset() error message"); input.close(); } @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 assertEquals(-1, input.read(), "End of File"); // 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 final int count4 = input.read(bytes); assertEquals(-1, count4, "Read 4 (EOF)"); // 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 testReadByteArrayThrowAtEof() throws Exception { final byte[] bytes = new byte[10]; final InputStream input = new TestNullInputStream(15, true, true); // 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 IOException e1 = assertThrows(EOFException.class, () -> input.read(bytes)); assertTrue(StringUtils.isNotBlank(e1.getMessage())); // Test reading after the end of file final IOException e2 = assertThrows(EOFException.class, () -> input.read(bytes)); assertTrue(StringUtils.isNotBlank(e2.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 testReadThrowAtEof() throws Exception { final int size = 5; final InputStream input = new TestNullInputStream(size, true, true); 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 final IOException e1 = assertThrows(EOFException.class, input::read); assertTrue(StringUtils.isNotBlank(e1.getMessage())); // Test reading after the end of file final IOException e2 = assertThrows(EOFException.class, input::read); assertTrue(StringUtils.isNotBlank(e2.getMessage())); // Close - should reset input.close(); assertEquals(size, input.available(), "Available after close"); } @Test public void testSkip() throws Exception { try (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 assertEquals(-1, input.skip(5), "Skip 3 (EOF)"); // End of file } } @Test public void testSkipThrowAtEof() throws Exception { try (InputStream input = new TestNullInputStream(10, true, true)) { 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 // End of File final IOException e1 = assertThrows(EOFException.class, () -> input.skip(5), "Skip 3 (EOF)"); assertTrue(StringUtils.isNotBlank(e1.getMessage())); final IOException e2 = assertThrows(IOException.class, () -> input.skip(5), "Expected IOException for skipping after end of file"); assertTrue(StringUtils.isNotBlank(e2.getMessage())); } } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/NullReaderTest.java0100644 0000000 0000000 00000017176 14603604450 030503 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 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; /** * Tests {@link NullReader}. */ public class NullReaderTest { 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); } } } // 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 testEOFException() throws Exception { try (Reader reader = new TestNullReader(2, false, true)) { assertEquals(0, reader.read(), "Read 1"); assertEquals(1, reader.read(), "Read 2"); assertThrows(EOFException.class, () -> reader.read()); } } @Test public void testMarkAndReset() throws Exception { int position = 0; final int readLimit = 10; try (Reader reader = new TestNullReader(100, true, false)) { assertTrue(reader.markSupported(), "Mark Should be Supported"); // No Mark final IOException resetException = assertThrows(IOException.class, reader::reset); assertEquals("No position has been marked", resetException.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 final IOException e = assertThrows(IOException.class, reader::reset); assertEquals("Marked position [" + position + "] is no longer valid - passed the read limit [" + readLimit + "]", e.getMessage(), "Read limit IOException message"); } } @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 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 testSkip() throws Exception { try (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 final IOException e = assertThrows(IOException.class, () -> reader.skip(5)); assertEquals("Skip after end of file", e.getMessage(), "Skip after EOF IOException message"); } } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/ObservableInputStreamTest.java0100644 0000000 0000000 00000026175 14603604450 032725 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; 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 final 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 final 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 (ObservableInputStream ois = new ObservableInputStream(BrokenInputStream.INSTANCE)) { assertThrows(IOException.class, ois::read); } } @Test public void testBrokenInputStreamReadBuffer() throws IOException { try (ObservableInputStream ois = new ObservableInputStream(BrokenInputStream.INSTANCE)) { assertThrows(IOException.class, () -> ois.read(new byte[1])); } } @Test public void testBrokenInputStreamReadSubBuffer() throws IOException { try (ObservableInputStream ois = new ObservableInputStream(BrokenInputStream.INSTANCE)) { 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 = MessageDigestInputStreamTest.generateRandomByteStream(IOUtils.DEFAULT_BUFFER_SIZE); final DataViewObserver lko = new DataViewObserver(); try (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 = MessageDigestInputStreamTest.generateRandomByteStream(IOUtils.DEFAULT_BUFFER_SIZE); final DataViewObserver lko = new DataViewObserver(); try (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 = MessageDigestInputStreamTest.generateRandomByteStream(IOUtils.DEFAULT_BUFFER_SIZE); try (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 (ObservableInputStream ois = new ObservableInputStream(NullInputStream.INSTANCE)) { assertTrue(ois.getObservers().isEmpty()); } } @Test public void testGetObservers1() throws IOException { final DataViewObserver observer0 = new DataViewObserver(); try (ObservableInputStream ois = new ObservableInputStream(NullInputStream.INSTANCE, observer0)) { assertEquals(observer0, ois.getObservers().get(0)); } } @Test public void testGetObserversOrder() throws IOException { final DataViewObserver observer0 = new DataViewObserver(); final DataViewObserver observer1 = new DataViewObserver(); try (ObservableInputStream ois = new ObservableInputStream(NullInputStream.INSTANCE, 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 (ObservableInputStream ois = new ObservableInputStream(new ByteArrayInputStream(buffer), lengthObserver, methodCountObserver)) { assertEquals(IOUtils.DEFAULT_BUFFER_SIZE, IOUtils.copy(ois, NullOutputStream.INSTANCE, 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.16.1-src/src/test/java/org/apache/commons/io/input/ProxyInputStreamTest.java0100644 0000000 0000000 00000012745 14603604450 031760 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.assertSame; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Arrays; import org.junit.jupiter.api.Test; /** * Tests {@link ProxyInputStream}. * * @param The actual type tested. */ public class ProxyInputStreamTest { private static final class ProxyInputStreamFixture extends ProxyInputStream { public ProxyInputStreamFixture(final InputStream proxy) { super(proxy); } } @SuppressWarnings({ "resource", "unused" }) // For subclasses protected T createFixture() throws IOException { return (T) new ProxyInputStreamFixture(createProxySource()); } protected InputStream createProxySource() { return CharSequenceInputStream.builder().setCharSequence("abc").get(); } protected void testEos(final T inputStream) { // empty } @Test public void testRead() throws IOException { try (T inputStream = createFixture()) { int found = inputStream.read(); assertEquals('a', found); found = inputStream.read(); assertEquals('b', found); found = inputStream.read(); assertEquals('c', found); found = inputStream.read(); assertEquals(-1, found); testEos(inputStream); } } @Test public void testReadArrayAtMiddleFully() throws IOException { try (T inputStream = createFixture()) { final byte[] dest = new byte[5]; int found = inputStream.read(dest, 2, 3); assertEquals(3, found); assertArrayEquals(new byte[] { 0, 0, 'a', 'b', 'c' }, dest); found = inputStream.read(dest, 2, 3); assertEquals(-1, found); testEos(inputStream); } } @Test public void testReadArrayAtStartFully() throws IOException { try (T inputStream = createFixture()) { final byte[] dest = new byte[5]; int found = inputStream.read(dest, 0, 5); assertEquals(3, found); assertArrayEquals(new byte[] { 'a', 'b', 'c', 0, 0 }, dest); found = inputStream.read(dest, 0, 5); assertEquals(-1, found); testEos(inputStream); } } @Test public void testReadArrayAtStartPartial() throws IOException { try (T inputStream = createFixture()) { final byte[] dest = new byte[5]; int found = inputStream.read(dest, 0, 2); assertEquals(2, found); assertArrayEquals(new byte[] { 'a', 'b', 0, 0, 0 }, dest); Arrays.fill(dest, (byte) 0); found = inputStream.read(dest, 0, 2); assertEquals(1, found); assertArrayEquals(new byte[] { 'c', 0, 0, 0, 0 }, dest); found = inputStream.read(dest, 0, 2); assertEquals(-1, found); testEos(inputStream); } } @Test public void testReadArrayFully() throws IOException { try (T inputStream = createFixture()) { final byte[] dest = new byte[5]; int found = inputStream.read(dest); assertEquals(3, found); assertArrayEquals(new byte[] { 'a', 'b', 'c', 0, 0 }, dest); found = inputStream.read(dest); assertEquals(-1, found); testEos(inputStream); } } @Test public void testReadArrayPartial() throws IOException { try (T inputStream = createFixture()) { final byte[] dest = new byte[2]; int found = inputStream.read(dest); assertEquals(2, found); assertArrayEquals(new byte[] { 'a', 'b' }, dest); Arrays.fill(dest, (byte) 0); found = inputStream.read(dest); assertEquals(1, found); assertArrayEquals(new byte[] { 'c', 0 }, dest); found = inputStream.read(dest); assertEquals(-1, found); testEos(inputStream); } } @Test public void testReadEof() throws Exception { final ByteArrayInputStream proxy = new ByteArrayInputStream(new byte[2]); try (ProxyInputStream inputStream = new ProxyInputStreamFixture(proxy)) { assertSame(proxy, inputStream.unwrap()); int found = inputStream.read(); assertEquals(0, found); found = inputStream.read(); assertEquals(0, found); found = inputStream.read(); assertEquals(-1, found); } } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/ProxyReaderTest.java0100644 0000000 0000000 00000004202 14603604450 030674 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; /** * Tests {@link ProxyReader}. */ public class ProxyReaderTest { /** Custom NullReader implementation. */ private static final 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); } } /** ProxyReader implementation. */ private static final class ProxyReaderImpl extends ProxyReader { ProxyReaderImpl(final Reader proxy) { super(proxy); } } @Test public void testNullCharArray() throws Exception { try (ProxyReader proxy = new ProxyReaderImpl(new CustomNullReader(0))) { proxy.read((char[]) null); proxy.read(null, 0, 0); } } @Test public void testNullCharBuffer() throws Exception { try (ProxyReader proxy = new ProxyReaderImpl(new CustomNullReader(0))) { proxy.read((CharBuffer) null); } } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/QueueInputStreamTest.java0100644 0000000 0000000 00000023543 14603604450 031721 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.assertTimeout; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.time.Duration; import java.util.concurrent.BlockingQueue; import java.util.concurrent.CountDownLatch; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; 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.DisplayName; 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; import com.google.common.base.Stopwatch; /** * Test {@link QueueInputStream}. * * @see QueueOutputStreamTest */ public class QueueInputStreamTest { public static Stream inputData() { // @formatter:off 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))); // @formatter:on } private int defaultBufferSize() { return 8192; } private String readUnbuffered(final InputStream inputStream) throws IOException { return readUnbuffered(inputStream, Integer.MAX_VALUE); } private String readUnbuffered(final InputStream inputStream, final int maxBytes) throws IOException { if (maxBytes == 0) { return ""; } final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); int n = -1; while ((n = inputStream.read()) != -1) { byteArrayOutputStream.write(n); if (byteArrayOutputStream.size() >= maxBytes) { break; } } return byteArrayOutputStream.toString(StandardCharsets.UTF_8.name()); } @ParameterizedTest(name = "inputData={0}") @MethodSource("inputData") public void testBufferedReads(final String inputData) throws IOException { final BlockingQueue queue = new LinkedBlockingQueue<>(); try (BufferedInputStream inputStream = new BufferedInputStream(new QueueInputStream(queue)); final QueueOutputStream outputStream = new QueueOutputStream(queue)) { outputStream.write(inputData.getBytes(StandardCharsets.UTF_8)); final String actualData = IOUtils.toString(inputStream, StandardCharsets.UTF_8); assertEquals(inputData, actualData); } } @ParameterizedTest(name = "inputData={0}") @MethodSource("inputData") public void testBufferedReadWrite(final String inputData) throws IOException { final BlockingQueue queue = new LinkedBlockingQueue<>(); try (BufferedInputStream inputStream = new BufferedInputStream(new QueueInputStream(queue)); final BufferedOutputStream outputStream = new BufferedOutputStream(new QueueOutputStream(queue), defaultBufferSize())) { outputStream.write(inputData.getBytes(StandardCharsets.UTF_8)); outputStream.flush(); final String dataCopy = IOUtils.toString(inputStream, StandardCharsets.UTF_8); assertEquals(inputData, dataCopy); } } @ParameterizedTest(name = "inputData={0}") @MethodSource("inputData") public void testBufferedWrites(final String inputData) throws IOException { final BlockingQueue queue = new LinkedBlockingQueue<>(); try (QueueInputStream inputStream = new QueueInputStream(queue); final BufferedOutputStream outputStream = new BufferedOutputStream(new QueueOutputStream(queue), defaultBufferSize())) { outputStream.write(inputData.getBytes(StandardCharsets.UTF_8)); outputStream.flush(); final String actualData = readUnbuffered(inputStream); assertEquals(inputData, actualData); } } @Test public void testInvalidArguments() { assertThrows(NullPointerException.class, () -> new QueueInputStream(null), "queue is required"); assertThrows(IllegalArgumentException.class, () -> QueueInputStream.builder().setTimeout(Duration.ofMillis(-1)).get(), "waitTime must not be negative"); } @Test public void testResetArguments() throws IOException { try (QueueInputStream queueInputStream = QueueInputStream.builder().setTimeout(null).get()) { assertEquals(Duration.ZERO, queueInputStream.getTimeout()); assertEquals(0, queueInputStream.getBlockingQueue().size()); } try (QueueInputStream queueInputStream = QueueInputStream.builder().setBlockingQueue(null).get()) { assertEquals(Duration.ZERO, queueInputStream.getTimeout()); assertEquals(0, queueInputStream.getBlockingQueue().size()); } } @Test @DisplayName("If read is interrupted while waiting, then exception is thrown") public void testTimeoutInterrupted() throws Exception { try (QueueInputStream inputStream = QueueInputStream.builder().setTimeout(Duration.ofMinutes(2)).get(); final QueueOutputStream outputStream = inputStream.newQueueOutputStream()) { // read in a background thread final AtomicBoolean result = new AtomicBoolean(); final CountDownLatch latch = new CountDownLatch(1); final Thread thread = new Thread(() -> { // when thread is interrupted, verify ... assertThrows(IllegalStateException.class, () -> readUnbuffered(inputStream, 3)); assertTrue(Thread.currentThread().isInterrupted()); result.set(true); latch.countDown(); }); thread.setDaemon(true); thread.start(); // interrupt and check that verification completed thread.interrupt(); latch.await(500, TimeUnit.MILLISECONDS); assertTrue(result.get()); } } @Test @DisplayName("If data is not available in queue, then read will wait until wait time elapses") public void testTimeoutUnavailableData() throws IOException { try (QueueInputStream inputStream = QueueInputStream.builder().setTimeout(Duration.ofMillis(500)).get(); final QueueOutputStream outputStream = inputStream.newQueueOutputStream()) { final Stopwatch stopwatch = Stopwatch.createStarted(); final String actualData = assertTimeout(Duration.ofSeconds(1), () -> readUnbuffered(inputStream, 3)); stopwatch.stop(); assertEquals("", actualData); assertTrue(stopwatch.elapsed(TimeUnit.MILLISECONDS) >= 500, () -> stopwatch.toString()); } } @ParameterizedTest(name = "inputData={0}") @MethodSource("inputData") public void testUnbufferedReadWrite(final String inputData) throws IOException { try (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 testUnbufferedReadWriteWithTimeout(final String inputData) throws IOException { final Duration timeout = Duration.ofMinutes(2); try (QueueInputStream inputStream = QueueInputStream.builder().setTimeout(timeout).get(); final QueueOutputStream outputStream = inputStream.newQueueOutputStream()) { assertEquals(timeout, inputStream.getTimeout()); writeUnbuffered(outputStream, inputData); final String actualData = assertTimeout(Duration.ofSeconds(1), () -> readUnbuffered(inputStream, inputData.length())); assertEquals(inputData, actualData); } } private void writeUnbuffered(final QueueOutputStream outputStream, final String inputData) throws IOException { final byte[] bytes = inputData.getBytes(StandardCharsets.UTF_8); outputStream.write(bytes, 0, bytes.length); } } ././@LongLink0100644 0000000 0000000 00000000145 14603604450 011635 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/RandomAccessFileInputStreamTest.javacommons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/RandomAccessFileInputStreamTest.java0100644 0000000 0000000 00000025611 14603604450 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.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import org.apache.commons.io.RandomAccessFileMode; import org.junit.jupiter.api.Test; public class RandomAccessFileInputStreamTest { private static final String DATA_FILE_NAME = "src/test/resources/org/apache/commons/io/test-file-iso8859-1.bin"; private static final Path DATA_PATH = Paths.get(DATA_FILE_NAME); private static final int DATA_FILE_LEN = 1430; private RandomAccessFile createRandomAccessFile() throws FileNotFoundException { return RandomAccessFileMode.READ_ONLY.create(DATA_FILE_NAME); } @Test public void testAvailable() throws IOException { try (RandomAccessFileInputStream inputStream = new RandomAccessFileInputStream(createRandomAccessFile(), true)) { assertEquals(DATA_FILE_LEN, inputStream.available()); } } @Test public void testAvailableLong() throws IOException { try (RandomAccessFileInputStream inputStream = new RandomAccessFileInputStream(createRandomAccessFile(), true)) { assertEquals(DATA_FILE_LEN, inputStream.availableLong()); } } @SuppressWarnings("resource") // instance variable access @Test public void testBuilderFile() throws IOException { try (RandomAccessFile file = createRandomAccessFile()) { try (RandomAccessFileInputStream inputStream = RandomAccessFileInputStream.builder().setFile(new File(DATA_FILE_NAME)).get()) { assertFalse(inputStream.isCloseOnClose()); assertNotEquals(-1, inputStream.getRandomAccessFile().read()); } file.read(); } } @Test public void testBuilderGet() { // java.lang.IllegalStateException: origin == null assertThrows(IllegalStateException.class, () -> RandomAccessFileInputStream.builder().get()); } @SuppressWarnings("resource") // instance variable access @Test public void testBuilderPath() throws IOException { try (RandomAccessFile file = createRandomAccessFile()) { try (RandomAccessFileInputStream inputStream = RandomAccessFileInputStream.builder().setPath(DATA_PATH).get()) { assertFalse(inputStream.isCloseOnClose()); assertNotEquals(-1, inputStream.getRandomAccessFile().read()); } file.read(); } } @SuppressWarnings("resource") // instance variable access @Test public void testBuilderPathOpenOptions() throws IOException { try (RandomAccessFile file = createRandomAccessFile()) { try (RandomAccessFileInputStream inputStream = RandomAccessFileInputStream.builder().setPath(DATA_PATH).setOpenOptions(StandardOpenOption.READ) .get()) { assertFalse(inputStream.isCloseOnClose()); assertNotEquals(-1, inputStream.getRandomAccessFile().read()); } file.read(); } } @SuppressWarnings("resource") // instance variable access @Test public void testBuilderRandomAccessFile() throws IOException { try (RandomAccessFile file = createRandomAccessFile()) { try (RandomAccessFileInputStream inputStream = RandomAccessFileInputStream.builder().setRandomAccessFile(file).get()) { assertFalse(inputStream.isCloseOnClose()); assertNotEquals(-1, inputStream.getRandomAccessFile().read()); } file.read(); } } @SuppressWarnings("resource") // instance variable access @Test public void testConstructorCloseOnCloseFalse() throws IOException { try (RandomAccessFile file = createRandomAccessFile()) { try (RandomAccessFileInputStream inputStream = new RandomAccessFileInputStream(file, false)) { assertFalse(inputStream.isCloseOnClose()); assertNotEquals(-1, inputStream.getRandomAccessFile().read()); } file.read(); } } @SuppressWarnings("resource") // instance variable access @Test public void testConstructorCloseOnCloseTrue() throws IOException { try (RandomAccessFile file = createRandomAccessFile()) { try (RandomAccessFileInputStream inputStream = new RandomAccessFileInputStream(file, true)) { assertTrue(inputStream.isCloseOnClose()); assertNotEquals(-1, inputStream.getRandomAccessFile().read()); } assertThrows(IOException.class, file::read); } } @SuppressWarnings("resource") // instance variable access @Test public void testConstructorRandomAccessFile() throws IOException { try (RandomAccessFile file = createRandomAccessFile()) { try (RandomAccessFileInputStream inputStream = new RandomAccessFileInputStream(file)) { assertFalse(inputStream.isCloseOnClose()); assertNotEquals(-1, inputStream.getRandomAccessFile().read()); } file.read(); } } @Test public void testConstructorRandomAccessFileNull() { assertThrows(NullPointerException.class, () -> new RandomAccessFileInputStream(null)); } @Test public void testGetters() throws IOException { try (RandomAccessFile file = createRandomAccessFile()) { try (RandomAccessFileInputStream inputStream = new RandomAccessFileInputStream(file, true)) { assertEquals(file, inputStream.getRandomAccessFile()); assertTrue(inputStream.isCloseOnClose()); } } } @Test public void testRead() throws IOException { try (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 testReadByteArray() throws IOException { try (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 (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()); } } @Test public void testSkip() throws IOException { try (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)); } } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/ReadAheadInputStreamTest.java0100644 0000000 0000000 00000006742 14603604450 032435 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.nio.file.StandardOpenOption; 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), // // Tests equal and aligned buffers of wrapped an outer stream. ReadAheadInputStream.builder().setInputStream(new BufferedFileChannelInputStream(inputFile, 8 * 1024)).setBufferSize(8 * 1024).get(), // Tests aligned buffers, wrapped bigger than outer. ReadAheadInputStream.builder().setInputStream(new BufferedFileChannelInputStream(inputFile, 3 * 1024)).setBufferSize(2 * 1024).get(), // Tests aligned buffers, wrapped smaller than outer. ReadAheadInputStream.builder().setInputStream(new BufferedFileChannelInputStream(inputFile, 2 * 1024)).setBufferSize(3 * 1024).get(), // Tests unaligned buffers, wrapped bigger than outer. ReadAheadInputStream.builder().setInputStream(new BufferedFileChannelInputStream(inputFile, 321)).setBufferSize(123).get(), // Tests unaligned buffers, wrapped smaller than outer. ReadAheadInputStream.builder().setInputStream(new BufferedFileChannelInputStream(inputFile, 123)).setBufferSize(321).get(), ReadAheadInputStream.builder().setPath(inputFile).setOpenOptions(StandardOpenOption.READ).get() }; } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/ReaderInputStreamTest.java0100644 0000000 0000000 00000035476 14603604450 032047 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.assertDoesNotThrow; 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.assertTrue; import java.io.CharArrayReader; import java.io.IOException; import java.io.InputStream; import java.io.StringReader; import java.nio.charset.CharacterCodingException; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; import java.nio.charset.CodingErrorAction; import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Random; import java.util.concurrent.TimeUnit; import java.util.stream.Stream; import javax.xml.parsers.DocumentBuilderFactory; import org.apache.commons.io.IOUtils; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Timeout; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.xml.sax.InputSource; import org.xml.sax.SAXException; public class ReaderInputStreamTest { private static final String UTF_16 = StandardCharsets.UTF_16.name(); private static final String UTF_8 = StandardCharsets.UTF_8.name(); 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(); } static Stream charsetData() { // @formatter:off return Stream.of( Arguments.of("Cp930", "\u0391"), Arguments.of("ISO_8859_1", "A"), Arguments.of(UTF_8, "\u0391")); // @formatter:on } private final Random random = new Random(); @Test @Timeout(value = 500, unit = TimeUnit.MILLISECONDS) public void testBufferSmallest() throws IOException { final Charset charset = StandardCharsets.UTF_8; // @formatter:off try (InputStream in = new ReaderInputStream( new StringReader("\uD800"), charset, (int) ReaderInputStream.minBufferSize(charset.newEncoder()))) { in.read(); } try (InputStream in = ReaderInputStream.builder() .setReader(new StringReader("\uD800")) .setCharset(charset) .setBufferSize((int) ReaderInputStream.minBufferSize(charset.newEncoder())) .get()) { in.read(); } // @formatter:on } @Test public void testBufferTooSmall() { assertThrows(IllegalArgumentException.class, () -> new ReaderInputStream(new StringReader("\uD800"), StandardCharsets.UTF_8, -1)); assertThrows(IllegalArgumentException.class, () -> new ReaderInputStream(new StringReader("\uD800"), StandardCharsets.UTF_8, 0)); assertThrows(IllegalArgumentException.class, () -> new ReaderInputStream(new StringReader("\uD800"), StandardCharsets.UTF_8, 1)); } @ParameterizedTest @MethodSource("charsetData") public void testCharsetEncoderFlush(final String charsetName, final String data) throws IOException { final Charset charset = Charset.forName(charsetName); final byte[] expected = data.getBytes(charset); try (InputStream in = new ReaderInputStream(new StringReader(data), charset)) { assertEquals(Arrays.toString(expected), Arrays.toString(IOUtils.toByteArray(in))); } try (InputStream in = ReaderInputStream.builder().setReader(new StringReader(data)).setCharset(charset).get()) { assertEquals(Arrays.toString(expected), Arrays.toString(IOUtils.toByteArray(in))); } } /* * 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)) { IOUtils.toCharArray(stream, charset); } } @Test @Timeout(value = 500, unit = TimeUnit.MILLISECONDS) public void testCodingError() throws IOException { // Encoder which throws on malformed or unmappable input CharsetEncoder encoder = StandardCharsets.UTF_8.newEncoder(); try (final ReaderInputStream in = new ReaderInputStream(new StringReader("\uD800"), encoder)) { // Does not throws an exception because the input is an underflow and not an error assertDoesNotThrow(() -> in.read()); // assertThrows(IllegalStateException.class, () -> in.read()); } encoder = StandardCharsets.UTF_8.newEncoder(); try (final ReaderInputStream in = ReaderInputStream.builder().setReader(new StringReader("\uD800")).setCharsetEncoder(encoder).get()) { // TODO WIP assertDoesNotThrow(() -> in.read()); // assertThrows(IllegalStateException.class, () -> in.read()); } } /** * Tests IO-717 to avoid infinite loops. * * ReaderInputStream does not throw exception with {@link CodingErrorAction#REPORT}. */ @Test @Timeout(value = 500, unit = TimeUnit.MILLISECONDS) public void testCodingErrorAction() throws IOException { final Charset charset = StandardCharsets.UTF_8; final CharsetEncoder encoder = charset.newEncoder().onMalformedInput(CodingErrorAction.REPORT); try (InputStream in = new ReaderInputStream(new StringReader("\uD800aa"), encoder, (int) ReaderInputStream.minBufferSize(encoder))) { assertThrows(CharacterCodingException.class, in::read); } try (InputStream in = ReaderInputStream.builder().setReader(new StringReader("\uD800aa")).setCharsetEncoder(encoder) .setBufferSize((int) ReaderInputStream.minBufferSize(charset.newEncoder())).get()) { assertThrows(CharacterCodingException.class, in::read); } } @Test @Timeout(value = 500, unit = TimeUnit.MILLISECONDS) public void testConstructNullCharset() throws IOException { final Charset charset = Charset.defaultCharset(); final Charset encoder = null; try (ReaderInputStream in = new ReaderInputStream(new StringReader("ABC"), encoder, (int) ReaderInputStream.minBufferSize(charset.newEncoder()))) { IOUtils.toByteArray(in); assertEquals(Charset.defaultCharset(), in.getCharsetEncoder().charset()); } } @Test @Timeout(value = 500, unit = TimeUnit.MILLISECONDS) public void testConstructNullCharsetEncoder() throws IOException { final Charset charset = Charset.defaultCharset(); final CharsetEncoder encoder = null; try (ReaderInputStream in = new ReaderInputStream(new StringReader("ABC"), encoder, (int) ReaderInputStream.minBufferSize(charset.newEncoder()))) { IOUtils.toByteArray(in); assertEquals(Charset.defaultCharset(), in.getCharsetEncoder().charset()); } } @Test @Timeout(value = 500, unit = TimeUnit.MILLISECONDS) public void testConstructNullCharsetNameEncoder() throws IOException { final Charset charset = Charset.defaultCharset(); final String charsetName = null; try (ReaderInputStream in = new ReaderInputStream(new StringReader("ABC"), charsetName, (int) ReaderInputStream.minBufferSize(charset.newEncoder()))) { IOUtils.toByteArray(in); assertEquals(Charset.defaultCharset(), in.getCharsetEncoder().charset()); } try (ReaderInputStream in = ReaderInputStream.builder().setReader(new StringReader("ABC")).setCharset(charsetName) .setBufferSize((int) ReaderInputStream.minBufferSize(charset.newEncoder())).get()) { IOUtils.toByteArray(in); assertEquals(Charset.defaultCharset(), in.getCharsetEncoder().charset()); } } @Test public void testIo803SAXException() throws IOException { final StringReader reader = new StringReader(""); try (final ReaderInputStream inputStream = ReaderInputStream.builder().setCharset(StandardCharsets.UTF_8).setReader(reader).get()) { final InputSource inputSource = new InputSource(inputStream); assertThrows(SAXException.class, () -> DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(inputSource)); } } @Test public void testIo803StringReaderSanityCheck() { final StringReader reader = new StringReader(""); final InputSource inputSource = new InputSource(reader); assertThrows(SAXException.class, () -> DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(inputSource)); } @Test public void testLargeUTF8WithBufferedRead() throws IOException { testWithBufferedRead(LARGE_TEST_STRING, UTF_8); } @Test public void testLargeUTF8WithSingleByteRead() throws IOException { testWithSingleByteRead(LARGE_TEST_STRING, UTF_8); } @Test public void testReadEofTwice() throws IOException { try (ReaderInputStream reader = ReaderInputStream.builder().setCharset(StandardCharsets.UTF_8).setReader(new StringReader("123")).get()) { assertEquals('1', reader.read()); assertEquals('2', reader.read()); assertEquals('3', reader.read()); assertEquals(-1, reader.read()); assertEquals(-1, reader.read()); } } @SuppressWarnings("deprecation") @Test public void testReadZero() throws Exception { final String inStr = "test"; try (ReaderInputStream inputStream = new ReaderInputStream(new StringReader(inStr))) { testReadZero(inStr, inputStream); } try (ReaderInputStream inputStream = ReaderInputStream.builder().setReader(new StringReader(inStr)).get()) { testReadZero(inStr, inputStream); } } private void testReadZero(final String inStr, final ReaderInputStream inputStream) throws IOException { 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 (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)); } } @Test public void testResetCharset() { assertNotNull(ReaderInputStream.builder().setReader(new StringReader("\uD800")).setCharset((Charset) null).getCharset()); } @Test public void testResetCharsetEncoder() { assertNotNull(ReaderInputStream.builder().setReader(new StringReader("\uD800")).setCharsetEncoder(null).getCharsetEncoder()); } @Test public void testResetCharsetName() { assertNotNull(ReaderInputStream.builder().setReader(new StringReader("\uD800")).setCharset((String) null).getCharset()); } @Test public void testUTF16WithSingleByteRead() throws IOException { testWithSingleByteRead(TEST_STRING, UTF_16); } @Test public void testUTF8WithBufferedRead() throws IOException { testWithBufferedRead(TEST_STRING, UTF_8); } @Test public void testUTF8WithSingleByteRead() throws IOException { testWithSingleByteRead(TEST_STRING, UTF_8); } private void testWithBufferedRead(final byte[] expected, final ReaderInputStream in) throws IOException { 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--; } } } private void testWithBufferedRead(final String testString, final String charsetName) throws IOException { final byte[] expected = testString.getBytes(charsetName); try (ReaderInputStream in = new ReaderInputStream(new StringReader(testString), charsetName)) { testWithBufferedRead(expected, in); } try (ReaderInputStream in = ReaderInputStream.builder().setReader(new StringReader(testString)).setCharset(charsetName).get()) { testWithBufferedRead(expected, in); } } private void testWithSingleByteRead(final String testString, final String charsetName) throws IOException { final byte[] bytes = testString.getBytes(charsetName); try (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()); } } } ././@LongLink0100644 0000000 0000000 00000000157 14603604450 011640 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/ReversedLinesFileReaderTestParamBlockSize.javacommons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/ReversedLinesFileReaderTestParamBloc0100644 0000000 0000000 00000033170 14603604450 033774 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.nio.charset.StandardCharsets; 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 = StandardCharsets.UTF_8.name(); private static final String ISO_8859_1 = StandardCharsets.ISO_8859_1.name(); // "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"; // Strings are escaped in constants to avoid java source encoding issues (source file enc is UTF-8): // 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"; static void assertEqualsAndNoLineBreaks(final String expected, final String actual) { assertEqualsAndNoLineBreaks(null, expected, actual); } 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); } // 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; 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); } } @AfterEach public void closeReader() { try { if (reversedLinesFileReader != null) { reversedLinesFileReader.close(); } } catch (final Exception e) { // ignore } } @ParameterizedTest(name = "BlockSize={0}") @MethodSource("blockSizes") public void testEmptyFile(final int blockSize) throws URISyntaxException, IOException { final File testFileEmpty = TestResources.getFile("/test-file-empty.bin"); try (ReversedLinesFileReader reader = new ReversedLinesFileReader(testFileEmpty, blockSize, UTF_8)) { assertNull(reader.readLine()); } try (ReversedLinesFileReader reader = ReversedLinesFileReader.builder().setFile(testFileEmpty).setBufferSize(blockSize).setCharset(UTF_8).get()) { assertNull(reader.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 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 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 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 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 testUnsupportedEncodingBig5(final int testParamBlockSize) throws URISyntaxException { final File testFileEncodingBig5 = TestResources.getFile("/test-file-empty.bin"); assertThrows(UnsupportedEncodingException.class, () -> new ReversedLinesFileReader(testFileEncodingBig5, testParamBlockSize, "Big5").close()); } @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, StandardCharsets.UTF_16.name()).close()); } @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, StandardCharsets.UTF_16BE.name()); 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, StandardCharsets.UTF_16LE.name()); 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 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 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 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 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 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()); } } ././@LongLink0100644 0000000 0000000 00000000152 14603604450 011633 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/ReversedLinesFileReaderTestParamFile.javacommons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/ReversedLinesFileReaderTestParamFile0100644 0000000 0000000 00000015645 14603604450 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.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 { private static final String UTF_16BE = StandardCharsets.ISO_8859_1.name(); private static final String UTF_16LE = StandardCharsets.UTF_16LE.name(); private static final String UTF_8 = StandardCharsets.UTF_8.name(); private static final String ISO_8859_1 = StandardCharsets.ISO_8859_1.name(); 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 // @formatter:off 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))); // @formatter:on } private void testDataIntegrityWithBufferedReader(final Path filePath, final FileSystem fileSystem, final Charset charset, final ReversedLinesFileReader reversedLinesFileReader) throws IOException { 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(); } } @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 constructor. final Charset charset = charsetName != null ? Charset.forName(charsetName) : null; try (ReversedLinesFileReader reversedLinesFileReader = blockSize == null ? new ReversedLinesFileReader(filePath, charset) : new ReversedLinesFileReader(filePath, blockSize, charset)) { testDataIntegrityWithBufferedReader(filePath, fileSystem, charset, reversedLinesFileReader); } // @formatter:off try (ReversedLinesFileReader reversedLinesFileReader = ReversedLinesFileReader.builder() .setPath(filePath) .setBufferSize(blockSize) .setCharset(charset) .get()) { // @formatter:on testDataIntegrityWithBufferedReader(filePath, fileSystem, charset, reversedLinesFileReader); } } } ././@LongLink0100644 0000000 0000000 00000000147 14603604450 011637 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/ReversedLinesFileReaderTestSimple.javacommons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/ReversedLinesFileReaderTestSimple.ja0100644 0000000 0000000 00000011061 14603604450 033751 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.nio.charset.StandardCharsets; 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, StandardCharsets.ISO_8859_1.name())) { 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, StandardCharsets.ISO_8859_1.name())) { 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, StandardCharsets.ISO_8859_1.name())) { 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 testUnsupportedEncodingBig5() throws URISyntaxException { final File testFileEncodingBig5 = TestResources.getFile("/test-file-empty.bin"); assertThrows(UnsupportedEncodingException.class, () -> new ReversedLinesFileReader(testFileEncodingBig5, IOUtils.DEFAULT_BUFFER_SIZE, "Big5").close()); } @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, StandardCharsets.UTF_16.name()).close()); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/SequenceReaderTest.java0100644 0000000 0000000 00000022404 14603604450 031327 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; 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 class CustomReader extends Reader { boolean closed; protected void checkOpen() throws IOException { if (closed) { throw new IOException("emptyReader already closed"); } } @Override public void close() throws IOException { closed = true; } public boolean isClosed() { return closed; } @Override public int read(final char[] cbuf, final int off, final int len) throws IOException { checkOpen(); close(); return EOF; } } 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 testAutoClose() throws IOException { try (Reader reader = new SequenceReader(new CharSequenceReader("FooBar"))) { checkRead(reader, "Foo"); reader.close(); checkReadEof(reader); } } @Test public void testClose() throws IOException { final Reader reader = new SequenceReader(new CharSequenceReader("FooBar")); checkRead(reader, "Foo"); reader.close(); checkReadEof(reader); } @Test public void testCloseReaders() throws IOException { final CustomReader reader0 = new CustomReader(); final CustomReader reader1 = new CustomReader() { private final char[] content = {'A'}; private int position; @Override public int read(final char[] cbuf, final int off, final int len) throws IOException { checkOpen(); if (off < 0) { throw new IndexOutOfBoundsException("off is negative"); } if (len < 0) { throw new IndexOutOfBoundsException("len is negative"); } if (len > cbuf.length - off) { throw new IndexOutOfBoundsException("len is greater than cbuf.length - off"); } if (position > 0) { return EOF; } cbuf[off] = content[0]; position++; return 1; } }; try (SequenceReader sequenceReader = new SequenceReader(reader1, reader0)) { assertEquals('A', sequenceReader.read()); assertEquals(EOF, sequenceReader.read()); } finally { assertTrue(reader1.isClosed()); assertTrue(reader0.isClosed()); } assertTrue(reader1.isClosed()); assertTrue(reader0.isClosed()); } @Test public void testMarkSupported() throws Exception { try (Reader reader = new SequenceReader()) { assertFalse(reader.markSupported()); } } @Test public void testRead() throws IOException { try (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 (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 (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 testReadClosedReader() throws IOException { @SuppressWarnings("resource") final Reader reader = new SequenceReader(new CharSequenceReader("FooBar")); reader.close(); checkReadEof(reader); } @Test public void testReadCollection() throws IOException { final Collection readers = new ArrayList<>(); readers.add(new StringReader("F")); readers.add(new StringReader("B")); try (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 (Reader reader = new SequenceReader(iterable)) { assertEquals('F', reader.read()); assertEquals('B', reader.read()); checkReadEof(reader); } } @Test public void testReadLength0Readers() throws IOException { try (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 (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 (Reader reader = new SequenceReader(readers)) { assertEquals('F', reader.read()); assertEquals('B', reader.read()); checkReadEof(reader); } } @Test public void testSkip() throws IOException { try (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.16.1-src/src/test/java/org/apache/commons/io/input/SwappedDataInputStreamTest.java0100644 0000000 0000000 00000010516 14603604450 033026 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.16.1-src/src/test/java/org/apache/commons/io/input/TaggedInputStreamTest.java0100644 0000000 0000000 00000010150 14603604450 032016 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 java.io.InputStream; import java.util.UUID; import org.apache.commons.io.TaggedIOException; import org.junit.jupiter.api.Test; /** * Tests {@link TaggedInputStream}. */ public class TaggedInputStreamTest { @Test public void testBrokenStream() { final IOException exception = new IOException("test exception"); final TaggedInputStream stream = new TaggedInputStream(new BrokenInputStream(exception)); // Test the available() method final IOException exceptionAvailable = assertThrows(IOException.class, stream::available); assertTrue(stream.isCauseOf(exceptionAvailable)); final IOException exceptionAvailableCause = assertThrows(IOException.class, () -> stream.throwIfCauseOf(exceptionAvailable)); assertEquals(exception, exceptionAvailableCause); // Test the read() method final IOException exceptionRead = assertThrows(IOException.class, stream::read); assertTrue(stream.isCauseOf(exceptionRead)); final IOException exceptionReadCause = assertThrows(IOException.class, () -> stream.throwIfCauseOf(exceptionRead)); assertEquals(exception, exceptionReadCause); // Test the close() method final IOException exceptionClose = assertThrows(IOException.class, stream::close); assertTrue(stream.isCauseOf(exceptionClose)); final IOException exceptionCloseCause = assertThrows(IOException.class, () -> stream.throwIfCauseOf(exceptionClose)); assertEquals(exception, exceptionCloseCause); } @Test public void testEmptyStream() throws IOException { try (InputStream stream = new TaggedInputStream(ClosedInputStream.INSTANCE)) { assertEquals(0, stream.available()); assertEquals(-1, stream.read()); assertEquals(-1, stream.read(new byte[1])); assertEquals(-1, stream.read(new byte[1], 0, 1)); } } @Test public void testNormalStream() throws IOException { try (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()); } } @Test public void testOtherException() throws Exception { final IOException exception = new IOException("test exception"); try (TaggedInputStream stream = new TaggedInputStream(ClosedInputStream.INSTANCE)) { assertFalse(stream.isCauseOf(exception)); assertFalse(stream.isCauseOf(new TaggedIOException(exception, UUID.randomUUID()))); stream.throwIfCauseOf(exception); stream.throwIfCauseOf(new TaggedIOException(exception, UUID.randomUUID())); } } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/TaggedReaderTest.java0100644 0000000 0000000 00000007725 14603604450 030763 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.Reader; import java.io.StringReader; import java.util.UUID; import org.apache.commons.io.TaggedIOException; import org.junit.jupiter.api.Test; /** * Tests {@link TaggedReader}. */ public class TaggedReaderTest { @Test public void testBrokenReader() { final IOException exception = new IOException("test exception"); final TaggedReader reader = new TaggedReader(new BrokenReader(exception)); // Test the ready() method final IOException readyException = assertThrows(IOException.class, reader::ready); assertTrue(reader.isCauseOf(readyException)); final IOException rethrownReadyException = assertThrows(IOException.class, () -> reader.throwIfCauseOf(readyException)); assertEquals(exception, rethrownReadyException); // Test the read() method final IOException readException = assertThrows(IOException.class, reader::read); assertTrue(reader.isCauseOf(readException)); final IOException rethrownReadException = assertThrows(IOException.class, () -> reader.throwIfCauseOf(readException)); assertEquals(exception, rethrownReadException); // Test the close() method final IOException closeException = assertThrows(IOException.class, reader::close); assertTrue(reader.isCauseOf(closeException)); final IOException rethrownCloseException = assertThrows(IOException.class, () -> reader.throwIfCauseOf(closeException)); assertEquals(exception, rethrownCloseException); } @Test public void testEmptyReader() throws IOException { try (Reader reader = new TaggedReader(ClosedReader.INSTANCE)) { 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 (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 testOtherException() throws Exception { final IOException exception = new IOException("test exception"); try (TaggedReader reader = new TaggedReader(ClosedReader.INSTANCE)) { 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.16.1-src/src/test/java/org/apache/commons/io/input/TailerTest.java0100644 0000000 0000000 00000073033 14603604450 027660 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.nio.file.attribute.FileTime; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.io.RandomAccessFileMode; import org.apache.commons.io.TestResources; import org.apache.commons.io.test.TestUtils; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; /** * Test for {@link Tailer}. */ public class TailerTest { private static final class NonStandardTailable implements Tailer.Tailable { private final File file; public NonStandardTailable(final File file) { this.file = file; } @Override public Tailer.RandomAccessResourceBridge getRandomAccess(final String mode) throws FileNotFoundException { return new Tailer.RandomAccessResourceBridge() { private final RandomAccessFile randomAccessFile = new RandomAccessFile(file, mode); @Override public void close() throws IOException { randomAccessFile.close(); } @Override public long getPointer() throws IOException { return randomAccessFile.getFilePointer(); } @Override public int read(final byte[] b) throws IOException { return randomAccessFile.read(b); } @Override public void seek(final long position) throws IOException { randomAccessFile.seek(position); } }; } @Override public boolean isNewer(final FileTime fileTime) throws IOException { return FileUtils.isFileNewer(file, fileTime); } @Override public FileTime lastModifiedFileTime() throws IOException { return FileUtils.lastModifiedFileTime(file); } @Override public long size() { return file.length(); } } /** * Test {@link TailerListener} implementation. */ private static final 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<>()); private final CountDownLatch latch; volatile Exception exception; volatile int notFound; volatile int rotated; volatile int initialized; volatile int reachedEndOfFile; public TestTailerListener() { latch = new CountDownLatch(1); } public TestTailerListener(final int expectedLines) { latch = new CountDownLatch(expectedLines); } public boolean awaitExpectedLines(final long timeout, final TimeUnit timeUnit) throws InterruptedException { return latch.await(timeout, timeUnit); } public void clear() { lines.clear(); } @Override public void endOfFileReached() { reachedEndOfFile++; // 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. } public List getLines() { return lines; } @Override public void handle(final Exception e) { exception = e; } @Override public void handle(final String line) { lines.add(line); latch.countDown(); } @Override public void init(final Tailer tailer) { initialized++; // not atomic, but OK because only updated here. } } private static final int TEST_BUFFER_SIZE = 1024; private static final int TEST_DELAY_MILLIS = 1500; @TempDir public static File temporaryFolder; protected void createFile(final File file, final long size) throws IOException { assertTrue(file.getParentFile().exists(), () -> "Cannot create file " + file + " as the parent directory does not exist"); try (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 = RandomAccessFileMode.READ_ONLY.create(file); } catch (final FileNotFoundException ignore) { // ignore } TestUtils.sleepQuietly(200L); } } finally { IOUtils.closeQuietly(reader); } // sanity checks assertTrue(file.exists()); assertEquals(size, file.length()); } @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(); try (Tailer 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 testBuilderWithNonStandardTailable() throws Exception { final File file = new File(temporaryFolder, "tailer-create-with-delay-and-from-start-with-reopen-and-buffersize-and-charset.txt"); createFile(file, 0); final TestTailerListener listener = new TestTailerListener(1); try (Tailer tailer = Tailer.builder() .setExecutorService(Executors.newSingleThreadExecutor()) .setTailable(new NonStandardTailable(file)) .setTailerListener(listener) .get()) { assertTrue(tailer.getTailable() instanceof NonStandardTailable); validateTailer(listener, file); } } @Test public void testCreate() throws Exception { final File file = new File(temporaryFolder, "tailer-create.txt"); createFile(file, 0); final TestTailerListener listener = new TestTailerListener(1); try (Tailer tailer = Tailer.create(file, listener)) { validateTailer(listener, file); } } @Test public void testCreateWithDelay() throws Exception { final File file = new File(temporaryFolder, "tailer-create-with-delay.txt"); createFile(file, 0); final TestTailerListener listener = new TestTailerListener(1); try (Tailer tailer = Tailer.create(file, listener, TEST_DELAY_MILLIS)) { validateTailer(listener, file); } } @Test public void testCreateWithDelayAndFromStart() throws Exception { final File file = new File(temporaryFolder, "tailer-create-with-delay-and-from-start.txt"); createFile(file, 0); final TestTailerListener listener = new TestTailerListener(1); try (Tailer tailer = Tailer.create(file, listener, TEST_DELAY_MILLIS, false)) { validateTailer(listener, file); } } @Test public void testCreateWithDelayAndFromStartWithBufferSize() throws Exception { final File file = new File(temporaryFolder, "tailer-create-with-delay-and-from-start-with-buffersize.txt"); createFile(file, 0); final TestTailerListener listener = new TestTailerListener(1); try (Tailer tailer = Tailer.create(file, listener, TEST_DELAY_MILLIS, false, TEST_BUFFER_SIZE)) { validateTailer(listener, file); } } @Test public void testCreateWithDelayAndFromStartWithReopenAndBufferSize() throws Exception { final File file = new File(temporaryFolder, "tailer-create-with-delay-and-from-start-with-reopen-and-buffersize.txt"); createFile(file, 0); final TestTailerListener listener = new TestTailerListener(1); try (Tailer tailer = Tailer.create(file, listener, TEST_DELAY_MILLIS, false, true, TEST_BUFFER_SIZE)) { validateTailer(listener, file); } } @Test public void testCreateWithDelayAndFromStartWithReopenAndBufferSizeAndCharset() throws Exception { final File file = new File(temporaryFolder, "tailer-create-with-delay-and-from-start-with-reopen-and-buffersize-and-charset.txt"); createFile(file, 0); final TestTailerListener listener = new TestTailerListener(1); try (Tailer tailer = Tailer.create(file, StandardCharsets.UTF_8, listener, TEST_DELAY_MILLIS, false, true, TEST_BUFFER_SIZE)) { validateTailer(listener, file); } } @Test public void testCreatorWithDelayAndFromStartWithReopen() throws Exception { final File file = new File(temporaryFolder, "tailer-create-with-delay-and-from-start-with-reopen.txt"); createFile(file, 0); final TestTailerListener listener = new TestTailerListener(1); try (Tailer tailer = Tailer.create(file, listener, TEST_DELAY_MILLIS, false, false)) { validateTailer(listener, file); } } /* * Tests [IO-357][Tailer] InterruptedException while the thread 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 try (Tailer 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 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(); try (Tailer 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 @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 (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(); try (Tailer 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 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; try (Tailer 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 < len; i++) { final String expected = lines.get(i); final String actual = tailerlines.get(i); if (!expected.equals(actual)) { fail("Line: " + i + "\nExp: (" + expected.length() + ") " + expected + "\nAct: (" + actual.length() + ") " + actual); } } } } } @Test public void testSimpleConstructor() throws Exception { final File file = new File(temporaryFolder, "tailer-simple-constructor.txt"); createFile(file, 0); final TestTailerListener listener = new TestTailerListener(1); try (Tailer tailer = new Tailer(file, listener)) { final Thread thread = new Thread(tailer); thread.start(); validateTailer(listener, file); } } @Test public void testSimpleConstructorWithDelay() throws Exception { final File file = new File(temporaryFolder, "tailer-simple-constructor-with-delay.txt"); createFile(file, 0); final TestTailerListener listener = new TestTailerListener(1); try (Tailer tailer = new Tailer(file, listener, TEST_DELAY_MILLIS)) { final Thread thread = new Thread(tailer); thread.start(); validateTailer(listener, file); } } @Test public void testSimpleConstructorWithDelayAndFromStart() throws Exception { final File file = new File(temporaryFolder, "tailer-simple-constructor-with-delay-and-from-start.txt"); createFile(file, 0); final TestTailerListener listener = new TestTailerListener(1); try (Tailer tailer = new Tailer(file, listener, TEST_DELAY_MILLIS, false)) { final Thread thread = new Thread(tailer); thread.start(); validateTailer(listener, file); } } @Test public void testSimpleConstructorWithDelayAndFromStartWithBufferSize() throws Exception { final File file = new File(temporaryFolder, "tailer-simple-constructor-with-delay-and-from-start-with-buffersize.txt"); createFile(file, 0); final TestTailerListener listener = new TestTailerListener(1); try (Tailer tailer = new Tailer(file, listener, TEST_DELAY_MILLIS, false, TEST_BUFFER_SIZE)) { final Thread thread = new Thread(tailer); thread.start(); validateTailer(listener, file); } } @Test public void testSimpleConstructorWithDelayAndFromStartWithReopen() throws Exception { final File file = new File(temporaryFolder, "tailer-simple-constructor-with-delay-and-from-start-with-reopen.txt"); createFile(file, 0); final TestTailerListener listener = new TestTailerListener(1); try (Tailer tailer = new Tailer(file, listener, TEST_DELAY_MILLIS, false, false)) { final Thread thread = new Thread(tailer); thread.start(); validateTailer(listener, file); } } @Test public void testSimpleConstructorWithDelayAndFromStartWithReopenAndBufferSize() throws Exception { final File file = new File(temporaryFolder, "tailer-simple-constructor-with-delay-and-from-start-with-reopen-and-buffersize.txt"); createFile(file, 0); final TestTailerListener listener = new TestTailerListener(1); try (Tailer tailer = new Tailer(file, listener, TEST_DELAY_MILLIS, false, true, TEST_BUFFER_SIZE)) { final Thread thread = new Thread(tailer); thread.start(); validateTailer(listener, file); } } @Test public void testSimpleConstructorWithDelayAndFromStartWithReopenAndBufferSizeAndCharset() throws Exception { final File file = new File(temporaryFolder, "tailer-simple-constructor-with-delay-and-from-start-with-reopen-and-buffersize-and-charset.txt"); createFile(file, 0); final TestTailerListener listener = new TestTailerListener(1); try (Tailer tailer = new Tailer(file, StandardCharsets.UTF_8, listener, TEST_DELAY_MILLIS, false, true, TEST_BUFFER_SIZE)) { final Thread thread = new Thread(tailer); thread.start(); validateTailer(listener, file); } } @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 try (Tailer tailer = Tailer.create(file, listener, delay, false)) { TestUtils.sleep(idle); } TestUtils.sleep(delay + idle); if (listener.exception != null) { listener.exception.printStackTrace(); } 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 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 try (Tailer tailer = new Tailer(file, listener, delay, false)) { final Executor exec = new ScheduledThreadPoolExecutor(1); exec.execute(tailer); TestUtils.sleep(idle); } 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 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"); try (Tailer 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, StandardCharsets.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 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"); try (Tailer 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"); } } @Test public void testTailerEof() throws Exception { // Create & start the Tailer final long delayMillis = 100; final File file = new File(temporaryFolder, "tailer2-test.txt"); createFile(file, 0); final TestTailerListener listener = new TestTailerListener(); try (Tailer tailer = new Tailer(file, listener, delayMillis, false)) { final Thread thread = new Thread(tailer); thread.start(); // Write some lines to the file writeString(file, "Line"); TestUtils.sleep(delayMillis * 2); List lines = listener.getLines(); assertEquals(0, lines.size(), "1 line count"); writeString(file, " one\n"); TestUtils.sleep(delayMillis * 4); lines = listener.getLines(); assertEquals(1, lines.size(), "1 line count"); assertEquals("Line one", lines.get(0), "1 line 1"); listener.clear(); } } private void validateTailer(final TestTailerListener listener, final File file) throws IOException, InterruptedException { write(file, "foo"); final int timeout = 30; final TimeUnit timeoutUnit = TimeUnit.SECONDS; assertTrue(listener.awaitExpectedLines(timeout, timeoutUnit), () -> String.format("await timed out after %s %s", timeout, timeoutUnit)); assertEquals(listener.getLines(), Arrays.asList("foo"), "lines"); } /** Appends lines to a file */ private void write(final File file, final String... lines) throws IOException { try (Writer writer = Files.newBufferedWriter(file.toPath(), StandardOpenOption.APPEND)) { for (final String line : lines) { writer.write(line + "\n"); } } } /** Appends strings to a file */ private void writeString(final File file, final String... strings) throws IOException { try (Writer writer = Files.newBufferedWriter(file.toPath(), StandardOpenOption.APPEND)) { for (final String string : strings) { writer.write(string); } } } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/TeeInputStreamTest.java0100644 0000000 0000000 00000012572 14603604450 031352 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.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 java.nio.charset.StandardCharsets; 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; /** * Tests {@link TeeInputStream}. */ public class TeeInputStreamTest { private final String ASCII = StandardCharsets.US_ASCII.name(); 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); } /** * 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); assertThrows(IOException.class, closingTis::close); 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); assertThrows(IOException.class, nonClosingTis::close); verify(goodOs, never()).close(); final TeeInputStream closingTis = new TeeInputStream(badIs, goodOs, true); assertThrows(IOException.class, closingTis::close); verify(goodOs).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(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", output.toString(ASCII)); } @Test public void testReadNothing() throws Exception { assertEquals("", output.toString(ASCII)); } @Test public void testReadOneByte() throws Exception { assertEquals('a', tee.read()); assertEquals("a", 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", 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", 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", output.toString(ASCII)); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/TeeReaderTest.java0100644 0000000 0000000 00000013074 14603604450 030277 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.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; /** * Tests {@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); assertThrows(IOException.class, closingTr::close); 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); assertThrows(IOException.class, nonClosingTr::close); verify(goodW, never()).close(); final TeeReader closingTr = new TeeReader(badR, goodW, true); assertThrows(IOException.class, closingTr::close); 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.16.1-src/src/test/java/org/apache/commons/io/input/ThrottledInputStreamTest.java0100644 0000000 0000000 00000005130 14603604450 032576 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.time.Duration; import org.junit.jupiter.api.Test; /** * Tests {@link ThrottledInputStream}. */ public class ThrottledInputStreamTest extends ProxyInputStreamTest { @Override @SuppressWarnings("resource") protected ThrottledInputStream createFixture() throws IOException { return ThrottledInputStream.builder().setInputStream(createProxySource()).get(); } @Test public void testCalSleepTimeMs() { // case 0: initial - no read, no sleep assertEquals(0, ThrottledInputStream.toSleepMillis(0, 10_000, 1_000)); // case 1: no threshold assertEquals(0, ThrottledInputStream.toSleepMillis(Long.MAX_VALUE, 0, 1_000)); assertEquals(0, ThrottledInputStream.toSleepMillis(Long.MAX_VALUE, -1, 1_000)); // case 2: too fast assertEquals(1500, ThrottledInputStream.toSleepMillis(5, 2, 1_000)); assertEquals(500, ThrottledInputStream.toSleepMillis(5, 2, 2_000)); assertEquals(6500, ThrottledInputStream.toSleepMillis(15, 2, 1_000)); // case 3: too slow assertEquals(0, ThrottledInputStream.toSleepMillis(1, 2, 1_000)); assertEquals(0, ThrottledInputStream.toSleepMillis(2, 2, 2_000)); assertEquals(0, ThrottledInputStream.toSleepMillis(1, 2, 1_000)); } @Override protected void testEos(final ThrottledInputStream inputStream) { assertEquals(3, inputStream.getByteCount()); } @Test public void testGet() throws IOException { try (ThrottledInputStream inputStream = createFixture()) { inputStream.read(); assertEquals(Duration.ZERO, inputStream.getTotalSleepDuration()); } } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/TimestampedObserverTest.java0100644 0000000 0000000 00000007270 14603604450 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.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 java.io.ByteArrayInputStream; import java.io.IOException; import java.time.Duration; import java.time.Instant; import org.apache.commons.io.IOUtils; import org.apache.commons.io.ThreadUtils; import org.junit.jupiter.api.Test; /** * Tests {@link TimestampedObserver}. */ public class TimestampedObserverTest { @Test public void test() throws IOException, InterruptedException { final Instant before = Instant.now(); // Some OS' clock granularity may be high. ThreadUtils.sleep(Duration.ofMillis(20)); final TimestampedObserver timestampedObserver = new TimestampedObserver(); assertFalse(timestampedObserver.isClosed()); // Java 8 instant resolution is not great. ThreadUtils.sleep(Duration.ofMillis(20)); // toString() should not blow up before close(). assertNotNull(timestampedObserver.toString()); assertTrue(timestampedObserver.getOpenInstant().isAfter(before)); assertTrue(timestampedObserver.getOpenToNowDuration().toNanos() > 0); assertNull(timestampedObserver.getCloseInstant()); assertFalse(timestampedObserver.isClosed()); final byte[] buffer = MessageDigestInputStreamTest.generateRandomByteStream(IOUtils.DEFAULT_BUFFER_SIZE); try (ObservableInputStream ois = new ObservableInputStream(new ByteArrayInputStream(buffer), timestampedObserver)) { assertTrue(timestampedObserver.getOpenInstant().isAfter(before)); assertTrue(timestampedObserver.getOpenToNowDuration().toNanos() > 0); assertFalse(timestampedObserver.isClosed()); } assertTrue(timestampedObserver.isClosed()); 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 = MessageDigestInputStreamTest .generateRandomByteStream(IOUtils.DEFAULT_BUFFER_SIZE); try (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.16.1-src/src/test/java/org/apache/commons/io/input/UncheckedBufferedReaderTest.java0100644 0000000 0000000 00000017601 14603604450 033116 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.io.UncheckedIOException; import java.nio.CharBuffer; import org.apache.commons.io.IOUtils; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Tests {@link UncheckedFilterReader}. */ public class UncheckedBufferedReaderTest { private UncheckedBufferedReader ucStringReader; private UncheckedBufferedReader ucBrokenReader; private IOException exception = new IOException("test exception"); @SuppressWarnings("resource") @BeforeEach public void beforeEach() { ucStringReader = UncheckedBufferedReader.builder().setReader(new StringReader("01")).get(); exception = new IOException("test exception"); ucBrokenReader = UncheckedBufferedReader.builder().setReader(new BrokenReader(exception)).get(); } @Test public void testBufferSize() { try (UncheckedBufferedReader uncheckedReader = UncheckedBufferedReader.builder().setReader(new StringReader("0123456789")).setBufferSize(2).get()) { assertEquals('0', uncheckedReader.read()); } } @Test public void testClose() { ucStringReader.close(); assertThrows(UncheckedIOException.class, () -> ucBrokenReader.read()); } @Test public void testCloseThrows() { assertEquals(exception, assertThrows(UncheckedIOException.class, () -> ucBrokenReader.close()).getCause()); } @Test public void testMarkReset() { ucStringReader.mark(10); final int c = ucStringReader.read(); ucStringReader.reset(); assertEquals(c, ucStringReader.read()); } @Test public void testMarkThrows() { try (UncheckedBufferedReader closedReader = UncheckedBufferedReader.builder().setReader(ClosedReader.INSTANCE).get()) { closedReader.close(); assertThrows(UncheckedIOException.class, () -> closedReader.mark(1)); } } @Test public void testRead() { final Reader reader = ucStringReader; try (UncheckedBufferedReader uncheckedReader = UncheckedBufferedReader.builder().setReader(reader).get()) { assertEquals('0', uncheckedReader.read()); assertEquals('1', uncheckedReader.read()); assertEquals(IOUtils.EOF, uncheckedReader.read()); assertEquals(IOUtils.EOF, uncheckedReader.read()); } } @Test public void testReadCharArray() { final Reader reader = ucStringReader; try (UncheckedBufferedReader uncheckedReader = UncheckedBufferedReader.builder().setReader(reader).get()) { final char[] array = new char[1]; assertEquals(1, uncheckedReader.read(array)); assertEquals('0', array[0]); array[0] = 0; assertEquals(1, uncheckedReader.read(array)); assertEquals('1', array[0]); array[0] = 0; assertEquals(IOUtils.EOF, uncheckedReader.read(array)); assertEquals(0, array[0]); assertEquals(IOUtils.EOF, uncheckedReader.read(array)); assertEquals(0, array[0]); } } @Test public void testReadCharArrayIndexed() { final Reader reader = ucStringReader; try (UncheckedBufferedReader uncheckedReader = UncheckedBufferedReader.builder().setReader(reader).get()) { final char[] array = new char[1]; assertEquals(1, uncheckedReader.read(array, 0, 1)); assertEquals('0', array[0]); array[0] = 0; assertEquals(1, uncheckedReader.read(array, 0, 1)); assertEquals('1', array[0]); array[0] = 0; assertEquals(IOUtils.EOF, uncheckedReader.read(array, 0, 1)); assertEquals(0, array[0]); assertEquals(IOUtils.EOF, uncheckedReader.read(array, 0, 1)); assertEquals(0, array[0]); } } @Test public void testReadCharArrayIndexedThrows() { assertEquals(exception, assertThrows(UncheckedIOException.class, () -> ucBrokenReader.read(new char[1], 0, 1)).getCause()); } @Test public void testReadCharArrayThrows() { assertEquals(exception, assertThrows(UncheckedIOException.class, () -> ucBrokenReader.read(new char[1])).getCause()); } @Test public void testReadCharBuffer() { final Reader reader = ucStringReader; try (UncheckedBufferedReader uncheckedReader = UncheckedBufferedReader.builder().setReader(reader).get()) { final CharBuffer buffer = CharBuffer.wrap(new char[1]); assertEquals(1, uncheckedReader.read(buffer)); buffer.flip(); assertEquals('0', buffer.charAt(0)); buffer.put(0, (char) 0); assertEquals(1, uncheckedReader.read(buffer)); buffer.flip(); assertEquals('1', buffer.charAt(0)); buffer.put(0, (char) 0); assertEquals(IOUtils.EOF, uncheckedReader.read(buffer)); buffer.flip(); assertEquals(0, buffer.length()); assertEquals(0, uncheckedReader.read(buffer)); buffer.flip(); assertEquals(0, buffer.length()); } } @Test public void testReadCharBufferThrows() { assertEquals(exception, assertThrows(UncheckedIOException.class, () -> ucBrokenReader.read(CharBuffer.wrap(new char[1]))).getCause()); } @Test public void testReadLine() { final Reader reader = ucStringReader; try (UncheckedBufferedReader uncheckedReader = UncheckedBufferedReader.builder().setReader(reader).get()) { assertEquals("01", uncheckedReader.readLine()); assertEquals(IOUtils.EOF, uncheckedReader.read()); assertEquals(IOUtils.EOF, uncheckedReader.read()); } } @Test public void testReadLineThrows() { assertEquals(exception, assertThrows(UncheckedIOException.class, () -> ucBrokenReader.readLine()).getCause()); } @Test public void testReadThrows() { assertEquals(exception, assertThrows(UncheckedIOException.class, () -> ucBrokenReader.read()).getCause()); } @Test public void testReady() { assertTrue(ucStringReader.ready()); } @Test public void testReadyThrows() { assertEquals(exception, assertThrows(UncheckedIOException.class, () -> ucBrokenReader.ready()).getCause()); } @Test public void testResetThrows() { try (UncheckedBufferedReader closedReader = UncheckedBufferedReader.builder().setReader(ClosedReader.INSTANCE).get()) { closedReader.close(); assertThrows(UncheckedIOException.class, () -> ucBrokenReader.reset()); } } @Test public void testSkip() { assertEquals(1, ucStringReader.skip(1)); } @Test public void testSkipThrows() { assertEquals(exception, assertThrows(UncheckedIOException.class, () -> ucBrokenReader.skip(1)).getCause()); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/UncheckedFilterInputStreamTest.java0100644 0000000 0000000 00000013127 14603604450 033671 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.io.UncheckedIOException; import org.apache.commons.io.IOUtils; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Tests {@link UncheckedFilterInputStream}. */ public class UncheckedFilterInputStreamTest { private UncheckedFilterInputStream stringInputStream; private UncheckedFilterInputStream brokenInputStream; private IOException exception = new IOException("test exception"); @SuppressWarnings("resource") @BeforeEach public void beforeEach() { stringInputStream = UncheckedFilterInputStream.builder() .setInputStream(new BufferedInputStream(CharSequenceInputStream.builder().setCharSequence("01").get())).get(); exception = new IOException("test exception"); brokenInputStream = UncheckedFilterInputStream.builder().setInputStream(new BrokenInputStream(exception)).get(); } @Test public void testClose() { stringInputStream.close(); assertThrows(UncheckedIOException.class, () -> brokenInputStream.read()); } @Test public void testCloseThrows() { assertEquals(exception, assertThrows(UncheckedIOException.class, () -> brokenInputStream.close()).getCause()); } @Test public void testMarkReset() { stringInputStream.mark(10); final int c = stringInputStream.read(); stringInputStream.reset(); assertEquals(c, stringInputStream.read()); } @Test public void testRead() { final InputStream inputStream = stringInputStream; try (UncheckedFilterInputStream uncheckedReader = UncheckedFilterInputStream.builder().setInputStream(inputStream).get()) { assertEquals('0', uncheckedReader.read()); assertEquals('1', uncheckedReader.read()); assertEquals(IOUtils.EOF, uncheckedReader.read()); assertEquals(IOUtils.EOF, uncheckedReader.read()); } } @Test public void testReadByteArray() { final InputStream inputStream = stringInputStream; try (UncheckedFilterInputStream uncheckedReader = UncheckedFilterInputStream.builder().setInputStream(inputStream).get()) { final byte[] array = new byte[1]; assertEquals(1, uncheckedReader.read(array)); assertEquals('0', array[0]); array[0] = 0; assertEquals(1, uncheckedReader.read(array)); assertEquals('1', array[0]); array[0] = 0; assertEquals(IOUtils.EOF, uncheckedReader.read(array)); assertEquals(0, array[0]); assertEquals(IOUtils.EOF, uncheckedReader.read(array)); assertEquals(0, array[0]); } } @Test public void testReadByteArrayIndexed() { final InputStream inputStream = stringInputStream; try (UncheckedFilterInputStream uncheckedReader = UncheckedFilterInputStream.builder().setInputStream(inputStream).get()) { final byte[] array = new byte[1]; assertEquals(1, uncheckedReader.read(array, 0, 1)); assertEquals('0', array[0]); array[0] = 0; assertEquals(1, uncheckedReader.read(array, 0, 1)); assertEquals('1', array[0]); array[0] = 0; assertEquals(IOUtils.EOF, uncheckedReader.read(array, 0, 1)); assertEquals(0, array[0]); assertEquals(IOUtils.EOF, uncheckedReader.read(array, 0, 1)); assertEquals(0, array[0]); } } @Test public void testReadByteArrayIndexedThrows() { assertEquals(exception, assertThrows(UncheckedIOException.class, () -> brokenInputStream.read(new byte[1], 0, 1)).getCause()); } @Test public void testReadByteArrayThrows() { assertEquals(exception, assertThrows(UncheckedIOException.class, () -> brokenInputStream.read(new byte[1])).getCause()); } @Test public void testReadThrows() { assertEquals(exception, assertThrows(UncheckedIOException.class, () -> brokenInputStream.read()).getCause()); } @Test public void testResetThrows() { try (UncheckedFilterInputStream closedReader = UncheckedFilterInputStream.builder().setInputStream(ClosedInputStream.INSTANCE).get()) { closedReader.close(); assertThrows(UncheckedIOException.class, () -> brokenInputStream.reset()); } } @Test public void testSkip() { assertEquals(1, stringInputStream.skip(1)); } @Test public void testSkipThrows() { assertEquals(exception, assertThrows(UncheckedIOException.class, () -> brokenInputStream.skip(1)).getCause()); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/UncheckedFilterReaderTest.java0100644 0000000 0000000 00000016006 14603604450 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.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 java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.io.UncheckedIOException; import java.nio.CharBuffer; import org.apache.commons.io.IOUtils; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Tests {@link UncheckedFilterReader}. */ public class UncheckedFilterReaderTest { private UncheckedFilterReader ucStringReader; private UncheckedFilterReader ucBrokenReader; private IOException exception = new IOException("test exception"); @SuppressWarnings("resource") @BeforeEach public void beforeEach() { ucStringReader = UncheckedFilterReader.builder().setReader(new StringReader("01")).get(); exception = new IOException("test exception"); ucBrokenReader = UncheckedFilterReader.builder().setReader(new BrokenReader(exception)).get(); } @Test public void testClose() { ucStringReader.close(); assertThrows(UncheckedIOException.class, () -> ucBrokenReader.read()); } @Test public void testCloseThrows() { assertEquals(exception, assertThrows(UncheckedIOException.class, () -> ucBrokenReader.close()).getCause()); } @Test public void testMarkReset() { ucStringReader.mark(10); final int c = ucStringReader.read(); ucStringReader.reset(); assertEquals(c, ucStringReader.read()); } @Test public void testMarkThrows() { try (UncheckedFilterReader closedReader = UncheckedFilterReader.builder().setReader(ClosedReader.INSTANCE).get()) { closedReader.close(); assertThrows(UncheckedIOException.class, () -> closedReader.mark(1)); } } @Test public void testRead() { final Reader reader = ucStringReader; try (UncheckedFilterReader uncheckedReader = UncheckedFilterReader.builder().setReader(reader).get()) { assertEquals('0', uncheckedReader.read()); assertEquals('1', uncheckedReader.read()); assertEquals(IOUtils.EOF, uncheckedReader.read()); assertEquals(IOUtils.EOF, uncheckedReader.read()); } } @Test public void testReadCharArray() { final Reader reader = ucStringReader; try (UncheckedFilterReader uncheckedReader = UncheckedFilterReader.builder().setReader(reader).get()) { final char[] array = new char[1]; assertEquals(1, uncheckedReader.read(array)); assertEquals('0', array[0]); array[0] = 0; assertEquals(1, uncheckedReader.read(array)); assertEquals('1', array[0]); array[0] = 0; assertEquals(IOUtils.EOF, uncheckedReader.read(array)); assertEquals(0, array[0]); assertEquals(IOUtils.EOF, uncheckedReader.read(array)); assertEquals(0, array[0]); } } @Test public void testReadCharArrayIndexed() { final Reader reader = ucStringReader; try (UncheckedFilterReader uncheckedReader = UncheckedFilterReader.builder().setReader(reader).get()) { final char[] array = new char[1]; assertEquals(1, uncheckedReader.read(array, 0, 1)); assertEquals('0', array[0]); array[0] = 0; assertEquals(1, uncheckedReader.read(array, 0, 1)); assertEquals('1', array[0]); array[0] = 0; assertEquals(IOUtils.EOF, uncheckedReader.read(array, 0, 1)); assertEquals(0, array[0]); assertEquals(IOUtils.EOF, uncheckedReader.read(array, 0, 1)); assertEquals(0, array[0]); } } @Test public void testReadCharArrayIndexedThrows() { assertEquals(exception, assertThrows(UncheckedIOException.class, () -> ucBrokenReader.read(new char[1], 0, 1)).getCause()); } @Test public void testReadCharArrayThrows() { assertEquals(exception, assertThrows(UncheckedIOException.class, () -> ucBrokenReader.read(new char[1])).getCause()); } @Test public void testReadCharBuffer() { final Reader reader = ucStringReader; try (UncheckedFilterReader uncheckedReader = UncheckedFilterReader.builder().setReader(reader).get()) { final CharBuffer buffer = CharBuffer.wrap(new char[1]); assertEquals(1, uncheckedReader.read(buffer)); buffer.flip(); assertEquals('0', buffer.charAt(0)); buffer.put(0, (char) 0); assertEquals(1, uncheckedReader.read(buffer)); buffer.flip(); assertEquals('1', buffer.charAt(0)); buffer.put(0, (char) 0); assertEquals(IOUtils.EOF, uncheckedReader.read(buffer)); buffer.flip(); assertEquals(0, buffer.length()); assertEquals(0, uncheckedReader.read(buffer)); buffer.flip(); assertEquals(0, buffer.length()); } } @Test public void testReadCharBufferThrows() { assertEquals(exception, assertThrows(UncheckedIOException.class, () -> ucBrokenReader.read(CharBuffer.wrap(new char[1]))).getCause()); } @Test public void testReadThrows() { assertEquals(exception, assertThrows(UncheckedIOException.class, () -> ucBrokenReader.read()).getCause()); } @Test public void testReady() { assertTrue(ucStringReader.ready()); } @Test public void testReadyThrows() { assertEquals(exception, assertThrows(UncheckedIOException.class, () -> ucBrokenReader.ready()).getCause()); } @Test public void testResetThrows() { try (UncheckedFilterReader closedReader = UncheckedFilterReader.builder().setReader(ClosedReader.INSTANCE).get()) { closedReader.close(); assertThrows(UncheckedIOException.class, () -> ucBrokenReader.reset()); } } @Test public void testSkip() { assertEquals(1, ucStringReader.skip(1)); } @Test public void testSkipThrows() { assertEquals(exception, assertThrows(UncheckedIOException.class, () -> ucBrokenReader.skip(1)).getCause()); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/UnixLineEndingInputStreamTest.java0100644 0000000 0000000 00000005235 14603604450 033513 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 { private String roundtrip(final String msg) throws IOException { return roundtrip(msg, true); } private String roundtrip(final String msg, final boolean ensure) throws IOException { try (final ByteArrayInputStream baos = new ByteArrayInputStream(msg.getBytes(StandardCharsets.UTF_8)); final UnixLineEndingInputStream lf = new UnixLineEndingInputStream(baos, ensure)) { final byte[] buf = new byte[100]; return new String(buf, 0, lf.read(buf), StandardCharsets.UTF_8); } } @Test public void testCrAtEnd() throws Exception { assertEquals("a\n", roundtrip("a\r")); } @Test public void testCrOnlyEnsureAtEof() throws Exception { assertEquals("a\nb\n", roundtrip("a\rb")); } @Test public void testCrOnlyNotAtEof() throws Exception { assertEquals("a\nb", roundtrip("a\rb", false)); } @Test public void testInTheMiddleOfTheLine() throws Exception { assertEquals("a\nbc\n", roundtrip("a\r\nbc")); } @Test public void testMultipleBlankLines() throws Exception { assertEquals("a\n\nbc\n", roundtrip("a\r\n\r\nbc")); } @Test public void testRetainLineFeed() throws Exception { assertEquals("a\n\n", roundtrip("a\r\n\r\n", false)); assertEquals("a", roundtrip("a", false)); } @Test public void testSimpleString() throws Exception { assertEquals("abc\n", roundtrip("abc")); } @Test public void testTwoLinesAtEnd() throws Exception { assertEquals("a\n\n", roundtrip("a\r\n\r\n")); } } ././@LongLink0100644 0000000 0000000 00000000153 14603604450 011634 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/UnsynchronizedBufferedInputStreamTest.javacommons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/UnsynchronizedBufferedInputStreamTes0100644 0000000 0000000 00000034365 14603604450 034222 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import org.apache.commons.io.IOUtils; import org.apache.commons.io.input.UnsynchronizedBufferedInputStream.Builder; import org.apache.commons.lang3.StringUtils; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Tests {@link UnsynchronizedBufferedInputStream}. *

* Provenance: Apache Harmony and modified. *

*/ public class UnsynchronizedBufferedInputStreamTest { private static final int BUFFER_SIZE = 4096; public static final String DATA = StringUtils.repeat("This is a test.", 500); Path fileName; private UnsynchronizedBufferedInputStream is; private InputStream isFile; byte[] ibuf = new byte[BUFFER_SIZE]; private Builder builder() { return new UnsynchronizedBufferedInputStream.Builder(); } /** * Sets up the fixture, for example, open a network connection. This method is called before a test is executed. * * @throws IOException Thrown on test failure. */ @BeforeEach protected void setUp() throws IOException { fileName = Files.createTempFile(getClass().getSimpleName(), ".tst"); Files.write(fileName, DATA.getBytes(StandardCharsets.UTF_8)); isFile = Files.newInputStream(fileName); is = builder().setInputStream(isFile).get(); } /** * Tears down the fixture, for example, close a network connection. This method is called after a test is executed. * * @throws IOException Thrown on test failure. */ @AfterEach protected void tearDown() throws IOException { IOUtils.closeQuietly(is); Files.deleteIfExists(fileName); } /** * Tests {@link UnsynchronizedBufferedInputStream#available()}. * * @throws IOException Thrown on test failure. */ @Test public void test_available() throws IOException { assertEquals(DATA.length(), is.available(), "Returned incorrect number of available bytes"); // Test that a closed stream throws an IOE for available() final UnsynchronizedBufferedInputStream bis = builder() .setInputStream(new ByteArrayInputStream(new byte[] { 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd' })).get(); final int available = bis.available(); bis.close(); assertTrue(available != 0); assertThrows(IOException.class, () -> bis.available(), "Expected test to throw IOE."); } /** * Tests {@link UnsynchronizedBufferedInputStream#close()}. * * @throws IOException Thrown on test failure. */ @Test public void test_close() throws IOException { builder().setInputStream(isFile).get().close(); try (InputStream in = new InputStream() { Object lock = new Object(); @Override public void close() { synchronized (lock) { lock.notifyAll(); } } @Override public int read() { return 1; } @Override public int read(final byte[] buf, final int offset, final int length) { synchronized (lock) { try { lock.wait(3000); } catch (final InterruptedException e) { // Ignore } } return 1; } }) { final UnsynchronizedBufferedInputStream bufin = builder().setInputStream(in).get(); final Thread thread = new Thread(() -> { try { Thread.sleep(1000); bufin.close(); } catch (final Exception e) { // Ignored } }); thread.start(); assertThrows(IOException.class, () -> bufin.read(new byte[100], 0, 99), "Should throw IOException"); } } /* * Tests {@link UnsynchronizedBufferedInputStream#Builder()}. */ @Test public void test_ConstructorLjava_io_InputStream() { assertThrows(NullPointerException.class, () -> builder().setInputStream(null).get()); } /* * Tests {@link UnsynchronizedBufferedInputStream#Builder()}. */ @Test public void test_ConstructorLjava_io_InputStreamI() throws IOException { assertThrows(NullPointerException.class, () -> builder().setInputStream(null).setBufferSize(1).get()); // Test for method UnsynchronizedBufferedInputStream(InputStream, int) // Create buffer with exact size of file is = builder().setInputStream(isFile).setBufferSize(DATA.length()).get(); // Ensure buffer gets filled by evaluating one read is.read(); // Close underlying FileInputStream, all but 1 buffered bytes should // still be available. isFile.close(); // Read the remaining buffered characters, no IOException should // occur. is.skip(DATA.length() - 2); is.read(); // is.read should now throw an exception because it will have to be filled. assertThrows(IOException.class, () -> is.read()); assertThrows(NullPointerException.class, () -> builder().setInputStream(null).setBufferSize(100).get()); assertThrows(NullPointerException.class, () -> builder().setInputStream(null)); } /** * Tests {@link UnsynchronizedBufferedInputStream#mark(int)}. * * @throws IOException Thrown on test failure. */ @Test public void test_markI() throws IOException { final byte[] buf1 = new byte[100]; final byte[] buf2 = new byte[100]; is.skip(3000); is.mark(1000); is.read(buf1, 0, buf1.length); is.reset(); is.read(buf2, 0, buf2.length); is.reset(); assertTrue(new String(buf1, 0, buf1.length).equals(new String(buf2, 0, buf2.length)), "Failed to mark correct position"); byte[] bytes = new byte[256]; for (int i = 0; i < 256; i++) { bytes[i] = (byte) i; } InputStream in = builder().setInputStream(new ByteArrayInputStream(bytes)).setBufferSize(12).get(); in.skip(6); in.mark(14); in.read(new byte[14], 0, 14); in.reset(); assertTrue(in.read() == 6 && in.read() == 7, "Wrong bytes"); in = builder().setInputStream(new ByteArrayInputStream(bytes)).setBufferSize(12).get(); in.skip(6); in.mark(8); in.skip(7); in.reset(); assertTrue(in.read() == 6 && in.read() == 7, "Wrong bytes 2"); UnsynchronizedBufferedInputStream buf = builder().setInputStream(new ByteArrayInputStream(new byte[] { 0, 1, 2, 3, 4 })).setBufferSize(2).get(); buf.mark(3); bytes = new byte[3]; int result = buf.read(bytes); assertEquals(3, result); assertEquals(0, bytes[0], "Assert 0:"); assertEquals(1, bytes[1], "Assert 1:"); assertEquals(2, bytes[2], "Assert 2:"); assertEquals(3, buf.read(), "Assert 3:"); buf = builder().setInputStream(new ByteArrayInputStream(new byte[] { 0, 1, 2, 3, 4 })).setBufferSize(2).get(); buf.mark(3); bytes = new byte[4]; result = buf.read(bytes); assertEquals(4, result); assertEquals(0, bytes[0], "Assert 4:"); assertEquals(1, bytes[1], "Assert 5:"); assertEquals(2, bytes[2], "Assert 6:"); assertEquals(3, bytes[3], "Assert 7:"); assertEquals(4, buf.read(), "Assert 8:"); assertEquals(-1, buf.read(), "Assert 9:"); buf = builder().setInputStream(new ByteArrayInputStream(new byte[] { 0, 1, 2, 3, 4 })).setBufferSize(2).get(); buf.mark(Integer.MAX_VALUE); buf.read(); buf.close(); } /** * Tests {@link UnsynchronizedBufferedInputStream#markSupported()}. */ @Test public void test_markSupported() { assertTrue(is.markSupported(), "markSupported returned incorrect value"); } /** * Tests {@link UnsynchronizedBufferedInputStream#read()}. * * @throws IOException Thrown on test failure. */ @Test public void test_read() throws IOException { final InputStreamReader isr = new InputStreamReader(is); final int c = isr.read(); assertEquals(DATA.charAt(0), c, "read returned incorrect char"); final byte[] bytes = new byte[256]; for (int i = 0; i < 256; i++) { bytes[i] = (byte) i; } final InputStream in = builder().setInputStream(new ByteArrayInputStream(bytes)).setBufferSize(12).get(); assertEquals(0, in.read(), "Wrong initial byte"); // Fill the buffer final byte[] buf = new byte[14]; in.read(buf, 0, 14); // Read greater than the buffer assertTrue(new String(buf, 0, 14).equals(new String(bytes, 1, 14)), "Wrong block read data"); assertEquals(15, in.read(), "Wrong bytes"); // Check next byte } /** * Tests {@link UnsynchronizedBufferedInputStream#read(byte[], int, int)}. * * @throws IOException Thrown on test failure. */ @Test public void test_read$BII() throws IOException { final byte[] buf1 = new byte[100]; is.skip(3000); is.mark(1000); is.read(buf1, 0, buf1.length); assertTrue(new String(buf1, 0, buf1.length).equals(DATA.substring(3000, 3100)), "Failed to read correct data"); try (UnsynchronizedBufferedInputStream bufin = builder().setInputStream(new InputStream() { int size = 2, pos = 0; byte[] contents = new byte[size]; @Override public int available() { return size - pos; } @Override public int read() throws IOException { if (pos >= size) { throw new IOException("Read past end of data"); } return contents[pos++]; } @Override public int read(final byte[] buf, final int off, final int len) throws IOException { if (pos >= size) { throw new IOException("Read past end of data"); } int toRead = len; if (toRead > available()) { toRead = available(); } System.arraycopy(contents, pos, buf, off, toRead); pos += toRead; return toRead; } }).get()) { bufin.read(); final int result = bufin.read(new byte[2], 0, 2); assertEquals(1, result, () -> "Incorrect result: " + result); } } /** * Tests {@link UnsynchronizedBufferedInputStream#reset()}. * * @throws IOException Thrown on test failure. */ @Test public void test_reset() throws IOException { final byte[] buf1 = new byte[10]; final byte[] buf2 = new byte[10]; is.mark(2000); is.read(buf1, 0, 10); is.reset(); is.read(buf2, 0, 10); is.reset(); assertTrue(new String(buf1, 0, buf1.length).equals(new String(buf2, 0, buf2.length)), "Reset failed"); final UnsynchronizedBufferedInputStream bIn = builder().setInputStream(new ByteArrayInputStream("1234567890".getBytes())).get(); bIn.mark(10); for (int i = 0; i < 11; i++) { bIn.read(); } bIn.reset(); } /** * Tests {@link UnsynchronizedBufferedInputStream#reset()}. * * @throws IOException Thrown on test failure. */ @Test public void test_reset_scenario1() throws IOException { final byte[] input = "12345678900".getBytes(); final UnsynchronizedBufferedInputStream bufin = builder().setInputStream(new ByteArrayInputStream(input)).get(); bufin.read(); bufin.mark(5); bufin.skip(5); bufin.reset(); } /** * Tests {@link UnsynchronizedBufferedInputStream#reset()}. * * @throws IOException Thrown on test failure. */ @Test public void test_reset_scenario2() throws IOException { final byte[] input = "12345678900".getBytes(); final UnsynchronizedBufferedInputStream bufin = builder().setInputStream(new ByteArrayInputStream(input)).get(); bufin.mark(5); bufin.skip(6); bufin.reset(); } /** * Tests {@link UnsynchronizedBufferedInputStream#skip(long)}. * * @throws IOException Thrown on test failure. */ @Test public void test_skip_NullInputStream() throws IOException { assertThrows(NullPointerException.class, () -> builder().setInputStream(null).setBufferSize(5).get()); } /** * Tests {@link UnsynchronizedBufferedInputStream#skip(long)}. * * @throws IOException Thrown on test failure. */ @Test public void test_skipJ() throws IOException { final byte[] buf1 = new byte[10]; is.mark(2000); is.skip(1000); is.read(buf1, 0, buf1.length); is.reset(); assertTrue(new String(buf1, 0, buf1.length).equals(DATA.substring(1000, 1010)), "Failed to skip to correct position"); } } ././@LongLink0100644 0000000 0000000 00000000154 14603604450 011635 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/UnsynchronizedByteArrayInputStreamTest.javacommons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/UnsynchronizedByteArrayInputStreamTe0100644 0000000 0000000 00000033156 14603604450 034214 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 static org.junit.jupiter.api.Assertions.fail; 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 { private UnsynchronizedByteArrayInputStream newStream(final byte[] buffer) { try { return UnsynchronizedByteArrayInputStream.builder().setByteArray(buffer).get(); } catch (final IOException e) { fail("Should never happen because no conversion is needed.", e); return null; } } private UnsynchronizedByteArrayInputStream newStream(final byte[] buffer, final int offset) { try { return UnsynchronizedByteArrayInputStream.builder().setByteArray(buffer).setOffset(offset).get(); } catch (final IOException e) { fail("Should never happen because no conversion is needed.", e); return null; } } private UnsynchronizedByteArrayInputStream newStream(final byte[] buffer, final int offset, final int length) { try { return UnsynchronizedByteArrayInputStream.builder().setByteArray(buffer).setOffset(offset).setLength(length).get(); } catch (final IOException e) { fail("Should never happen because no conversion is needed.", e); return null; } } @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]; try (UnsynchronizedByteArrayInputStream is = newStream(empty)) { assertEquals(empty.length, is.available()); } try (UnsynchronizedByteArrayInputStream is = newStream(one)) { assertEquals(one.length, is.available()); } try (UnsynchronizedByteArrayInputStream is = newStream(some)) { assertEquals(some.length, is.available()); } } @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 = newStream(empty, 0); assertEquals(empty.length, is.available()); is = newStream(empty, 1); assertEquals(0, is.available()); is = newStream(one, 0); assertEquals(one.length, is.available()); is = newStream(one, 1); assertEquals(0, is.available()); is = newStream(one, 2); assertEquals(0, is.available()); is = newStream(some, 0); assertEquals(some.length, is.available()); is = newStream(some, 1); assertEquals(some.length - 1, is.available()); is = newStream(some, 10); assertEquals(some.length - 10, is.available()); is = newStream(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 = newStream(empty, 0); assertEquals(empty.length, is.available()); is = newStream(empty, 1); assertEquals(0, is.available()); is = newStream(empty, 0, 1); assertEquals(0, is.available()); is = newStream(empty, 1, 1); assertEquals(0, is.available()); is = newStream(one, 0); assertEquals(one.length, is.available()); is = newStream(one, 1); assertEquals(one.length - 1, is.available()); is = newStream(one, 2); assertEquals(0, is.available()); is = newStream(one, 0, 1); assertEquals(1, is.available()); is = newStream(one, 1, 1); assertEquals(0, is.available()); is = newStream(one, 0, 2); assertEquals(1, is.available()); is = newStream(one, 2, 1); assertEquals(0, is.available()); is = newStream(one, 2, 2); assertEquals(0, is.available()); is = newStream(some, 0); assertEquals(some.length, is.available()); is = newStream(some, 1); assertEquals(some.length - 1, is.available()); is = newStream(some, 10); assertEquals(some.length - 10, is.available()); is = newStream(some, some.length); assertEquals(0, is.available()); is = newStream(some, some.length, some.length); assertEquals(0, is.available()); is = newStream(some, some.length - 1, some.length); assertEquals(1, is.available()); is = newStream(some, 0, 7); assertEquals(7, is.available()); is = newStream(some, 7, 7); assertEquals(7, is.available()); is = newStream(some, 0, some.length * 2); assertEquals(some.length, is.available()); is = newStream(some, some.length - 1, 7); assertEquals(1, is.available()); } @Test public void testInvalidConstructor2OffsetUnder() { assertThrows(IllegalArgumentException.class, () -> { newStream(IOUtils.EMPTY_BYTE_ARRAY, -1); }); } @Test public void testInvalidConstructor3LengthUnder() { assertThrows(IllegalArgumentException.class, () -> { newStream(IOUtils.EMPTY_BYTE_ARRAY, 0, -1); }); } @Test public void testInvalidConstructor3OffsetUnder() { assertThrows(IllegalArgumentException.class, () -> { newStream(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 = newStream(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 = newStream(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 = newStream(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 = newStream(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 = newStream(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 = newStream(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]; UnsynchronizedByteArrayInputStream is = newStream(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 = newStream(new byte[] { (byte) 0xa, (byte) 0xb, (byte) 0xc }); read = is.read(buf); assertEquals(0, read); buf = new byte[10]; is = newStream(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 = newStream(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]; UnsynchronizedByteArrayInputStream is = newStream(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 = newStream(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 = newStream(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 = newStream(new byte[] { (byte) 0xa, (byte) 0xb, (byte) 0xc }); read = is.read(buf, 0, 0); assertEquals(0, read); buf = new byte[10]; is = newStream(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() { UnsynchronizedByteArrayInputStream is = newStream(IOUtils.EMPTY_BYTE_ARRAY); assertEquals(END_OF_STREAM, is.read()); is = newStream(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() { UnsynchronizedByteArrayInputStream is = newStream(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 = newStream(new byte[] { (byte) 0xa, (byte) 0xb, (byte) 0xc }); assertEquals(3, is.available()); is.skip(0); assertEquals(3, is.available()); assertEquals(0xa, is.read()); is = newStream(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 = newStream(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 = newStream(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 00000000151 14603604450 011632 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/UnsynchronizedFilterInputStreamTest.javacommons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/UnsynchronizedFilterInputStreamTest.0100644 0000000 0000000 00000012542 14603604450 034160 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Tests {@link UnsynchronizedFilterInputStream}. *

* Provenance: Apache Harmony and modified. *

*/ public class UnsynchronizedFilterInputStreamTest { public static final String DATA = StringUtils.repeat("This is a test.", 500); private Path fileName; private InputStream is; byte[] ibuf = new byte[4096]; /** * Sets up the fixture, for example, open a network connection. This method is called before a test is executed. * * @throws IOException Thrown on test failure. */ @SuppressWarnings("resource") // See @AfterEach tearDown() method @BeforeEach protected void setUp() throws IOException { fileName = Files.createTempFile(getClass().getSimpleName(), ".tst"); Files.write(fileName, DATA.getBytes(StandardCharsets.UTF_8)); is = UnsynchronizedFilterInputStream.builder().setInputStream(Files.newInputStream(fileName)).get(); } /** * Tears down the fixture, for example, close a network connection. This method is called after a test is executed. * * @throws IOException Thrown on test failure. */ @AfterEach protected void tearDown() throws IOException { IOUtils.closeQuietly(is); Files.deleteIfExists(fileName); } /** * Tests java.io.FilterInputStream#available() * * @throws IOException Thrown on test failure. */ @Test public void test_available() throws IOException { assertEquals(DATA.length(), is.available(), "Returned incorrect number of available bytes"); } /** * Tests java.io.FilterInputStream#close() * * @throws IOException Thrown on test failure. */ @Test public void test_close() throws IOException { is.close(); assertThrows(IOException.class, () -> is.read(), "Able to read from closed stream"); } /** * Tests java.io.FilterInputStream#mark(int) */ @Test public void test_markI() { assertTrue(true, "Mark not supported by parent InputStream"); } /** * Tests java.io.FilterInputStream#markSupported() */ @Test public void test_markSupported() { assertTrue(!is.markSupported(), "markSupported returned true"); } /** * Tests java.io.FilterInputStream#read() * * @throws IOException Thrown on test failure. */ @Test public void test_read() throws IOException { final int c = is.read(); assertEquals(DATA.charAt(0), c, "read returned incorrect char"); } /** * Tests java.io.FilterInputStream#read(byte[]) * * @throws IOException Thrown on test failure. */ @Test public void test_read$B() throws IOException { final byte[] buf1 = new byte[100]; assertEquals(buf1.length, is.read(buf1)); assertTrue(new String(buf1, 0, buf1.length, StandardCharsets.UTF_8).equals(DATA.substring(0, 100)), "Failed to read correct data"); } /** * Tests java.io.FilterInputStream#read(byte[], int, int) * * @throws IOException Thrown on test failure. */ @Test public void test_read$BII() throws IOException { final byte[] buf1 = new byte[100]; is.skip(3000); is.mark(1000); is.read(buf1, 0, buf1.length); assertTrue(new String(buf1, 0, buf1.length, StandardCharsets.UTF_8).equals(DATA.substring(3000, 3100)), "Failed to read correct data"); } /** * Tests java.io.FilterInputStream#reset() */ @Test public void test_reset() { assertThrows(IOException.class, () -> is.reset(), "should throw IOException"); } /** * Tests java.io.FilterInputStream#skip(long) * * @throws IOException Thrown on test failure. */ @Test public void test_skipJ() throws IOException { final byte[] buf1 = new byte[10]; is.skip(1000); is.read(buf1, 0, buf1.length); assertTrue(new String(buf1, 0, buf1.length, StandardCharsets.UTF_8).equals(DATA.substring(1000, 1010)), "Failed to skip to correct position"); } } ././@LongLink0100644 0000000 0000000 00000000146 14603604450 011636 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/WindowsLineEndingInputStreamTest.javacommons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/WindowsLineEndingInputStreamTest.jav0100644 0000000 0000000 00000005154 14603604450 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.assertEquals; import java.io.IOException; import java.nio.charset.StandardCharsets; import org.junit.jupiter.api.Test; public class WindowsLineEndingInputStreamTest { private String roundtrip(final String msg) throws IOException { return roundtrip(msg, true); } private String roundtrip(final String msg, final boolean ensure) throws IOException { try (WindowsLineEndingInputStream lf = new WindowsLineEndingInputStream( CharSequenceInputStream.builder().setCharSequence(msg).setCharset(StandardCharsets.UTF_8).get(), ensure)) { final byte[] buf = new byte[100]; final int read = lf.read(buf); return new String(buf, 0, read, StandardCharsets.UTF_8); } } @Test public void testInTheMiddleOfTheLine() throws Exception { assertEquals("a\r\nbc\r\n", roundtrip("a\r\nbc")); } @Test public void testLinuxLineFeeds() throws Exception { final String roundtrip = roundtrip("ab\nc", false); assertEquals("ab\r\nc", roundtrip); } @Test public void testMalformed() throws Exception { assertEquals("a\rbc", roundtrip("a\rbc", false)); } @Test public void testMultipleBlankLines() throws Exception { assertEquals("a\r\n\r\nbc\r\n", roundtrip("a\r\n\r\nbc")); } @Test public void testRetainLineFeed() throws Exception { assertEquals("a\r\n\r\n", roundtrip("a\r\n\r\n", false)); assertEquals("a", roundtrip("a", false)); } @Test public void testSimpleString() throws Exception { assertEquals("abc\r\n", roundtrip("abc")); } @Test public void testTwoLinesAtEnd() throws Exception { assertEquals("a\r\n\r\n", roundtrip("a\r\n\r\n")); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/XmlStreamReaderTest.java0100644 0000000 0000000 00000073453 14603604450 031505 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.Charset; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.text.MessageFormat; import java.util.HashMap; import java.util.Locale; import java.util.Map; import org.apache.commons.io.CharsetsTest; import org.apache.commons.io.IOUtils; import org.apache.commons.io.function.IOFunction; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import org.junitpioneer.jupiter.DefaultLocale; /** * Tests {@link XmlStreamReader}. */ public class XmlStreamReaderTest { private static final String ISO_8859_1 = StandardCharsets.ISO_8859_1.name(); private static final String US_ASCII = StandardCharsets.US_ASCII.name(); private static final String UTF_16 = StandardCharsets.UTF_16.name(); private static final String UTF_16LE = StandardCharsets.UTF_16LE.name(); private static final String UTF_16BE = StandardCharsets.UTF_16BE.name(); private static final String UTF_32 = "UTF-32"; private static final String UTF_32LE = "UTF-32LE"; private static final String UTF_32BE = "UTF-32BE"; private static final String UTF_8 = StandardCharsets.UTF_8.name(); private static final String XML7 = "xml-prolog-encoding-no-version"; private static final String XML6 = "xml-prolog-encoding-new-line"; 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"; 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_NEW_LINES = new MessageFormat( "\n{2}"); private static final MessageFormat XML_EXTERNAL_PARSED_ENTITY_NO_VERSION = 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); XMLs.put(XML6, XML_WITH_PROLOG_AND_ENCODING_NEW_LINES); XMLs.put(XML7, XML_EXTERNAL_PARSED_ENTITY_NO_VERSION); } /** * 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}); } /** * @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 (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()); } private void parseCharset(final String hdr, final String enc, final IOFunction factory) throws Exception { try (final InputStream stream = new ByteArrayInputStream(hdr.getBytes(StandardCharsets.UTF_8))) { try (final XmlStreamReader xml = factory.apply(stream)) { assertEquals(enc.toUpperCase(Locale.ROOT), xml.getEncoding(), enc); } } } public void testAlternateDefaultEncoding(final String contentType, final String bomEnc, final String streamEnc, final String prologEnc, final String alternateEnc) throws Exception { try (InputStream is = getXmlInputStream(bomEnc, prologEnc == null ? XML1 : XML3, streamEnc, prologEnc); XmlStreamReader xmlReader = new XmlStreamReader(is, contentType, false, alternateEnc)) { testAlternateDefaultEncoding(streamEnc, alternateEnc, xmlReader); } try (InputStream is = getXmlInputStream(bomEnc, prologEnc == null ? XML1 : XML3, streamEnc, prologEnc); // @formatter:off XmlStreamReader xmlReader = XmlStreamReader.builder() .setInputStream(is) .setHttpContentType(contentType) .setLenient(false) .setCharset(alternateEnc) .get()) { // @formatter:on testAlternateDefaultEncoding(streamEnc, alternateEnc, xmlReader); } } private void testAlternateDefaultEncoding(final String streamEnc, final String alternateEnc, final XmlStreamReader xmlReader) { assertEquals(xmlReader.getDefaultEncoding(), 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); } } @Test protected void testConstructorFileInput() throws IOException { try (XmlStreamReader reader = new XmlStreamReader(new File("pom.xml"))) { // do nothing } try (XmlStreamReader reader = XmlStreamReader.builder().setFile("pom.xml").get()) { // do nothing } } @Test protected void testConstructorFileInputNull() { assertThrows(NullPointerException.class, () -> new XmlStreamReader((File) null)); } @Test protected void testConstructorFileInputOpenOptions() throws IOException { try (XmlStreamReader reader = new XmlStreamReader(new File("pom.xml"))) { // do nothing } try (XmlStreamReader reader = XmlStreamReader.builder().setFile("pom.xml").setOpenOptions(StandardOpenOption.READ).get()) { // do nothing } } @Test protected void testConstructorInputStreamInput() throws IOException { final Path path = Paths.get("pom.xml"); try (XmlStreamReader reader = new XmlStreamReader(Files.newInputStream(path))) { // do nothing } try (@SuppressWarnings("resource") XmlStreamReader reader = XmlStreamReader.builder().setInputStream(Files.newInputStream(path)).get()) { // do nothing } } @Test protected void testConstructorInputStreamInputNull() { assertThrows(NullPointerException.class, () -> new XmlStreamReader((InputStream) null)); } @Test protected void testConstructorPathInput() throws IOException { try (XmlStreamReader reader = new XmlStreamReader(Paths.get("pom.xml"))) { // do nothing } try (XmlStreamReader reader = XmlStreamReader.builder().setPath("pom.xml").get()) { // do nothing } } @Test protected void testConstructorPathInputNull() { assertThrows(NullPointerException.class, () -> new XmlStreamReader((Path) null)); } @Test protected void testConstructorURLConnectionInput() throws IOException { try (XmlStreamReader reader = new XmlStreamReader(new URL("https://www.apache.org/").openConnection(), UTF_8)) { // do nothing } } @Test protected void testConstructorURLConnectionInputNull() { assertThrows(NullPointerException.class, () -> new XmlStreamReader((URLConnection) null, US_ASCII)); } @Test protected void testConstructorURLInput() throws IOException { try (XmlStreamReader reader = new XmlStreamReader(new URL("https://www.apache.org/"))) { // do nothing } } @Test protected void testConstructorURLInputNull() { assertThrows(NullPointerException.class, () -> new XmlStreamReader((URL) null)); } // XML Stream generator @Test public void testEncodingAttributeXML() throws Exception { try (InputStream is = new ByteArrayInputStream(ENCODING_ATTRIBUTE_XML.getBytes(StandardCharsets.UTF_8)); XmlStreamReader xmlReader = new XmlStreamReader(is, "", true)) { assertEquals(xmlReader.getEncoding(), UTF_8); } try (InputStream is = new ByteArrayInputStream(ENCODING_ATTRIBUTE_XML.getBytes(StandardCharsets.UTF_8)); // @formatter:off XmlStreamReader xmlReader = XmlStreamReader.builder() .setInputStream(is) .setHttpContentType("") .setLenient(true) .get()) { // @formatter:on assertEquals(xmlReader.getEncoding(), 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); } @Test public void testHttpContent() throws Exception { final String encoding = UTF_8; final String xml = getXML("no-bom", XML3, encoding, encoding); try (XmlStreamReader xmlReader = new XmlStreamReader(CharSequenceInputStream.builder().setCharSequence(xml).setCharset(encoding).get())) { assertEquals(xmlReader.getEncoding(), encoding, "Check encoding"); assertEquals(xml, IOUtils.toString(xmlReader), "Check content"); } } protected void testHttpInvalid(final String cT, final String bomEnc, final String streamEnc, final String prologEnc) throws Exception { try (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("Illegal encoding,")); } } } protected void testHttpLenient(final String cT, final String bomEnc, final String streamEnc, final String prologEnc, final String shouldBe) throws Exception { try (InputStream is = getXmlInputStream(bomEnc, prologEnc == null ? XML2 : XML3, streamEnc, prologEnc); XmlStreamReader xmlReader = new XmlStreamReader(is, cT, true)) { assertEquals(xmlReader.getEncoding(), shouldBe); } } public void testHttpValid(final String cT, final String bomEnc, final String streamEnc, final String prologEnc) throws Exception { try (InputStream is = getXmlInputStream(bomEnc, prologEnc == null ? XML1 : XML3, streamEnc, prologEnc); 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); } } } @ParameterizedTest(name = "{0}") @MethodSource(CharsetsTest.AVAIL_CHARSETS) public void testIO_815(final String csName) throws Exception { final MessageFormat fmt = new MessageFormat("\ntext"); final IOFunction factoryCtor = XmlStreamReader::new; final IOFunction factoryBuilder = stream -> XmlStreamReader.builder().setInputStream(stream).get(); parseCharset(fmt.format(new Object[] { csName }), csName, factoryCtor); parseCharset(fmt.format(new Object[] { csName }), csName, factoryBuilder); for (final String alias : Charset.forName(csName).aliases()) { parseCharset(fmt.format(new Object[] { alias }), alias, factoryCtor); parseCharset(fmt.format(new Object[] { alias }), alias, factoryBuilder); } } // Turkish language has specific rules to convert dotted and dotless i character. @Test @DefaultLocale(language = "tr") public void testLowerCaseEncodingWithTurkishLocale_IO_557() throws Exception { final String[] encodings = { "iso8859-1", "us-ascii", "utf-8" }; // lower-case for (final String encoding : encodings) { final String xml = getXML("no-bom", XML3, encoding, encoding); try (ByteArrayInputStream is = new ByteArrayInputStream(xml.getBytes(encoding)); XmlStreamReader xmlReader = new XmlStreamReader(is)) { assertTrue(encoding.equalsIgnoreCase(xmlReader.getEncoding()), "Check encoding : " + encoding); assertEquals(xml, IOUtils.toString(xmlReader), "Check content"); } } } @SuppressWarnings("resource") 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 = XmlStreamReader.builder().setInputStream(is).setLenient(false).get(); 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("Illegal encoding,")); } if (xmlReader != null) { xmlReader.close(); } } @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 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); } protected void testRawBomValid(final String encoding) throws Exception { try (InputStream is = getXmlInputStream(encoding + "-bom", XML3, encoding, encoding); 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); } } } @Test public void testRawContent() throws Exception { final String encoding = UTF_8; final String xml = getXML("no-bom", XML3, encoding, encoding); try (XmlStreamReader xmlReader = new XmlStreamReader(CharSequenceInputStream.builder().setCharSequence(xml).setCharset(encoding).get())) { assertEquals(xmlReader.getEncoding(), encoding, "Check encoding"); assertEquals(xml, IOUtils.toString(xmlReader), "Check content"); } } @Test public void testRawNoBomCp1047() throws Exception { testRawNoBomValid("CP1047"); } protected void testRawNoBomInvalid(final String encoding) throws Exception { try (final InputStream is = getXmlInputStream("no-bom", XML3, encoding, encoding)) { final XmlStreamReader xmlStreamReader = new XmlStreamReader(is, false); final IOException ex = assertThrows(IOException.class, xmlStreamReader::close); assertTrue(ex.getMessage().contains("Invalid encoding,")); } } @Test public void testRawNoBomIso8859_1() throws Exception { testRawNoBomValid(ISO_8859_1); } @Test public void testRawNoBomUsAscii() throws Exception { testRawNoBomValid(US_ASCII); } @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 testRawNoBomUtf8() throws Exception { testRawNoBomValid(UTF_8); } 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(); is = getXmlInputStream("no-bom", XML6, encoding, encoding); xmlReader = new XmlStreamReader(is); assertEquals(xmlReader.getEncoding(), encoding); xmlReader.close(); is = getXmlInputStream("no-bom", XML7, encoding, encoding); xmlReader = new XmlStreamReader(is); assertEquals(xmlReader.getEncoding(), encoding); xmlReader.close(); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/XmlStreamReaderUtilitiesTest.java0100644 0000000 0000000 00000046326 14603604450 033400 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.IOException; import org.junit.jupiter.api.Test; /** * Test the Encoding Utilities part of {@link XmlStreamReader}. */ public class XmlStreamReaderUtilitiesTest { /** Mock {@link XmlStreamReader} implementation */ private static final class MockXmlStreamReader extends XmlStreamReader { MockXmlStreamReader(final String defaultEncoding) throws IOException { super(CharSequenceInputStream.builder().setCharSequence("").get(), null, true, defaultEncoding); } } 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 = "Illegal 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"; protected String calculateHttpEncoding(final String httpContentType, final String bomEnc, final String xmlGuessEnc, final String xmlEnc, final boolean lenient, final String defaultEncoding) throws IOException { try (MockXmlStreamReader mock = new MockXmlStreamReader(defaultEncoding)) { return mock.calculateHttpEncoding(bomEnc, xmlGuessEnc, xmlEnc, lenient, httpContentType); } } protected String calculateRawEncoding(final String bomEnc, final String xmlGuessEnc, final String xmlEnc, final String defaultEncoding) throws IOException { try (MockXmlStreamReader mock = new MockXmlStreamReader(defaultEncoding)) { return mock.calculateRawEncoding(bomEnc, xmlGuessEnc, xmlEnc); } } @SuppressWarnings("boxing") private void checkAppXml(final boolean expected, final String mime) { assertEquals(expected, XmlStreamReader.isAppXml(mime), "Mime=[" + mime + "]"); } private void checkContentTypeEncoding(final String expected, final String httpContentType) { assertEquals(expected, XmlStreamReader.getContentTypeEncoding(httpContentType), "ContentTypeEncoding=[" + httpContentType + "]"); } private void checkContentTypeMime(final String expected, final String httpContentType) { assertEquals(expected, XmlStreamReader.getContentTypeMime(httpContentType), "ContentTypeMime=[" + httpContentType + "]"); } 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()); } 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("Illegal 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); } } 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()); } 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("Illegal 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); } } @SuppressWarnings("boxing") private void checkTextXml(final boolean expected, final String mime) { assertEquals(expected, XmlStreamReader.isTextXml(mime), "Mime=[" + mime + "]"); } @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"); } @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"); } @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); } @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"); } 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 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"); } @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\""); } @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"); } @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"); } } ././@LongLink0100644 0000000 0000000 00000000152 14603604450 011633 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/buffer/CircularBufferInputStreamTest.javacommons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/buffer/CircularBufferInputStreamTest0100644 0000000 0000000 00000010136 14603604450 034056 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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. /** * 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; } @Test public void testIO683() throws IOException { final byte[] buffer = {0, 1, -2, -2, -1, 4}; try (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"); } } @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"); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/buffer/CircularByteBufferTest.java0100644 0000000 0000000 00000006161 14603604450 033431 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import org.junit.jupiter.api.Test; /** * Tests {@link CircularByteBuffer}. */ public class CircularByteBufferTest { @Test public void testAddInvalidOffset() { final CircularByteBuffer cbb = new CircularByteBuffer(); assertThrows(IllegalArgumentException.class, () -> cbb.add(new byte[] { 1, 2, 3 }, -1, 3)); } @Test public void testAddNegativeLength() { final CircularByteBuffer cbb = new CircularByteBuffer(); final byte[] targetBuffer = { 1, 2, 3 }; assertThrows(IllegalArgumentException.class, () -> cbb.add(targetBuffer, 0, -1)); } @Test public void testAddNullBuffer() { final CircularByteBuffer cbb = new CircularByteBuffer(); assertThrows(NullPointerException.class, () -> cbb.add(null, 0, 3)); } /** * Tests for add function with 3 arguments of type byte[], int and int. */ @Test public void testAddValidData() { final CircularByteBuffer cbb = new CircularByteBuffer(); final int length = 3; cbb.add(new byte[] { 3, 6, 9 }, 0, length); assertEquals(length, cbb.getCurrentNumberOfBytes()); } @Test public void testPeekWithExcessiveLength() { assertFalse(new CircularByteBuffer().peek(new byte[] { 1, 3, 5, 7, 9 }, 0, 6)); } @Test public void testPeekWithInvalidOffset() { final CircularByteBuffer cbb = new CircularByteBuffer(); final IllegalArgumentException e = assertThrows(IllegalArgumentException.class, () -> cbb.peek(new byte[] { 2, 4, 6, 8, 10 }, -1, 5)); assertEquals("Illegal offset: -1", e.getMessage()); } @Test public void testPeekWithNegativeLength() { final CircularByteBuffer cbb = new CircularByteBuffer(); final IllegalArgumentException e = assertThrows(IllegalArgumentException.class, () -> cbb.peek(new byte[] { 1, 4, 3 }, 0, -1)); assertEquals("Illegal length: -1", e.getMessage()); } // Tests for peek function @Test public void testPeekWithValidArguments() { assertFalse(new CircularByteBuffer().peek(new byte[] { 5, 10, 15, 20, 25 }, 0, 5)); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/compatibility/XmlStreamReader.java0100644 0000000 0000000 00000074033 14603604450 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.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.charset.StandardCharsets; 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 = StandardCharsets.UTF_8.name(); private static final String US_ASCII = StandardCharsets.US_ASCII.name(); private static final String UTF_16BE = StandardCharsets.UTF_16BE.name(); private static final String UTF_16LE = StandardCharsets.UTF_16LE.name(); private static final String UTF_16 = StandardCharsets.UTF_16.name(); 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 static final Pattern CHARSET_PATTERN = Pattern .compile("charset=[\"']?([.[^; \"']]*)[\"']?"); public static final Pattern ENCODING_PATTERN = Pattern.compile( "<\\?xml.*encoding[\\s]*=[\\s]*((?:\".[^\"]*\")|(?:'.[^']*'))", Pattern.MULTILINE); private static final MessageFormat RAW_EX_1 = new MessageFormat( "Illegal encoding, BOM [{0}] XML guess [{1}] XML prolog [{2}] encoding mismatch"); private static final MessageFormat RAW_EX_2 = new MessageFormat( "Illegal encoding, BOM [{0}] XML guess [{1}] XML prolog [{2}] unknown BOM"); private static final MessageFormat HTTP_EX_1 = new MessageFormat( "Illegal 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( "Illegal 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( "Illegal encoding, CT-MIME [{0}] CT-Enc [{1}] BOM [{2}] XML guess [{3}] XML prolog [{4}], Illegal MIME"); // 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 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 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; } /** * 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; } // 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 StringBuilder prolog = new StringBuilder(); 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")); } /** * 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; } private Reader reader; private 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. */ @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 specification. */ 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 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 specification. */ public XmlStreamReader(final InputStream inputStream, final String httpContentType, final boolean lenient) throws IOException, XmlStreamReaderException { 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 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 specification. */ 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 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 { // TODO URLConnection leak. 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 || 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); } } } // 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; } // 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); } } 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); } } else { throw new XmlStreamReaderException(RAW_EX_2.format(new Object[] { bomEnc, xmlGuessEnc, xmlEnc }), bomEnc, xmlGuessEnc, xmlEnc, is); } encoding = bomEnc; } return encoding; } /** * 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 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 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); } } 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); } /** * Returns the charset encoding of the XmlStreamReader. * * @return charset encoding. */ public String getEncoding() { return encoding; } private void prepareReader(final InputStream inputStream, final String encoding) throws IOException { reader = new InputStreamReader(inputStream, encoding); this.encoding = encoding; } @Override public int read(final char[] buf, final int offset, final int len) throws IOException { return reader.read(buf, offset, len); } } ././@LongLink0100644 0000000 0000000 00000000154 14603604450 011635 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/compatibility/XmlStreamReaderException.javacommons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/compatibility/XmlStreamReaderExcepti0100644 0000000 0000000 00000006410 14603604450 034105 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 14603604450 011640 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/compatibility/XmlStreamReaderUtilitiesCompatibilityTest.javacommons-io-2.16.1-src/src/test/java/org/apache/commons/io/input/compatibility/XmlStreamReaderUtiliti0100644 0000000 0000000 00000004733 14603604450 034135 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.IOException; import org.apache.commons.io.input.CharSequenceInputStream; import org.apache.commons.io.input.XmlStreamReaderUtilitiesTest; /** * Test compatibility of the original XmlStreamReader (before all the refactoring). */ public class XmlStreamReaderUtilitiesCompatibilityTest extends XmlStreamReaderUtilitiesTest { /** Mock {@link XmlStreamReader} implementation */ private static final class MockXmlStreamReader extends XmlStreamReader { MockXmlStreamReader(final String defaultEncoding) throws IOException { super(CharSequenceInputStream.builder().setCharSequence("").get(), null, true, defaultEncoding); } } @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 (MockXmlStreamReader mock = new MockXmlStreamReader(defaultEncoding)) { return mock.calculateHttpEncoding( XmlStreamReader.getContentTypeMime(httpContentType), XmlStreamReader.getContentTypeEncoding(httpContentType), bomEnc, xmlGuessEnc, xmlEnc, null, lenient); } } @Override protected String calculateRawEncoding(final String bomEnc, final String xmlGuessEnc, final String xmlEnc, final String defaultEncoding) throws IOException { try (MockXmlStreamReader mock = new MockXmlStreamReader(defaultEncoding)) { return mock.calculateRawEncoding(bomEnc, xmlGuessEnc, xmlEnc, null); } } } ././@LongLink0100644 0000000 0000000 00000000155 14603604450 011636 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/jmh/IOUtilsContentEqualsInputStreamsBenchmark.javacommons-io-2.16.1-src/src/test/java/org/apache/commons/io/jmh/IOUtilsContentEqualsInputStreamsBenchm0100644 0000000 0000000 00000023735 14603604450 034035 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 14603604450 011631 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/jmh/IOUtilsContentEqualsReadersBenchmark.javacommons-io-2.16.1-src/src/test/java/org/apache/commons/io/jmh/IOUtilsContentEqualsReadersBenchmark.j0100644 0000000 0000000 00000024745 14603604450 033714 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.16.1-src/src/test/java/org/apache/commons/io/jmh/PathUtilsContentEqualsBenchmark.java0100644 0000000 0000000 00000011342 14603604450 033450 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 java.io.IOException; import java.io.RandomAccessFile; import java.io.UncheckedIOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; import java.util.Arrays; import java.util.concurrent.TimeUnit; import org.apache.commons.io.RandomAccessFileMode; import org.apache.commons.io.RandomAccessFiles; import org.apache.commons.io.file.PathUtils; 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 PathUtils#fileContentEquals(Path, Path)}. * *
 * Benchmark                                                                Mode  Cnt    Score   Error  Units
 * PathUtilsContentEqualsBenchmark.testCurrent_fileContentEquals            avgt    5    4.538 ▒  1.010  ms/op
 * PathUtilsContentEqualsBenchmark.testCurrent_fileContentEquals_Blackhole  avgt    5  110.627 ▒ 30.317  ms/op
 * PathUtilsContentEqualsBenchmark.testProposal_contentEquals               avgt    5    1.812 ▒  0.634  ms/op
 * PathUtilsContentEqualsBenchmark.testProposal_contentEquals_Blackhole     avgt    5   43.521 ▒  6.762  ms/op
 * 
*/ @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.MILLISECONDS) @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 PathUtilsContentEqualsBenchmark { private static final Path bigFile1; private static final Path bigFile2; static { // Set up test fixtures try { bigFile1 = Files.createTempFile(PathUtilsContentEqualsBenchmark.class.getSimpleName(), "-1.bin"); bigFile2 = Files.createTempFile(PathUtilsContentEqualsBenchmark.class.getSimpleName(), "-2.bin"); final int newLength = 1_000_000; final byte[] bytes1 = new byte[newLength]; Arrays.fill(bytes1, (byte) 1); Files.write(bigFile1, bytes1); Files.copy(bigFile1, bigFile2, StandardCopyOption.REPLACE_EXISTING); } catch (final IOException e) { throw new UncheckedIOException(e); } } public static boolean newFileContentEquals(final Path path1, final Path path2) throws IOException { try (RandomAccessFile raf1 = RandomAccessFileMode.READ_ONLY.create(path1); RandomAccessFile raf2 = RandomAccessFileMode.READ_ONLY.create(path2)) { return RandomAccessFiles.contentEquals(raf1, raf2); } } @Benchmark public boolean[] testCurrent_fileContentEquals() throws IOException { final boolean[] res = new boolean[1]; res[0] = PathUtils.fileContentEquals(bigFile1, bigFile2); return res; } @Benchmark public void testCurrent_fileContentEquals_Blackhole(final Blackhole blackhole) throws IOException { for (int i = 0; i < 5; i++) { for (int j = 0; j < 5; j++) { blackhole.consume(PathUtils.fileContentEquals(bigFile1, bigFile2)); } } } @Benchmark public boolean[] testProposal_contentEquals() throws IOException { final boolean[] res = new boolean[1]; res[0] = newFileContentEquals(bigFile1, bigFile2); return res; } @Benchmark public void testProposal_contentEquals_Blackhole(final Blackhole blackhole) throws IOException { for (int i = 0; i < 5; i++) { for (int j = 0; j < 5; j++) { blackhole.consume(newFileContentEquals(bigFile1, bigFile2)); } } } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/monitor/AbstractMonitorTest.java0100644 0000000 0000000 00000014143 14603604450 032100 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 AbstractMonitorTest { /** 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; /** * 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"); } /** * 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); } } @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); } /** * 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.16.1-src/src/test/java/org/apache/commons/io/monitor/CollectionFileListener.java0100644 0000000 0000000 00000012056 14603604450 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.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; } /** * Clear file collections. */ public void clear() { createdFiles.clear(); changedFiles.clear(); deletedFiles.clear(); createdDirectories.clear(); changedDirectories.clear(); deletedDirectories.clear(); } /** * Gets the set of changed directories. * * @return Directories which have changed */ public Collection getChangedDirectories() { return changedDirectories; } /** * Gets the set of changed files. * * @return Files which have changed */ public Collection getChangedFiles() { return changedFiles; } /** * Gets the set of created directories. * * @return Directories which have been created */ public Collection getCreatedDirectories() { return createdDirectories; } /** * Gets the set of created files. * * @return Files which have been created */ public Collection getCreatedFiles() { return createdFiles; } /** * Gets the set of deleted directories. * * @return Directories which been deleted */ public Collection getDeletedDirectories() { return deletedDirectories; } /** * Gets the set of deleted files. * * @return Files which been deleted */ public Collection getDeletedFiles() { return deletedFiles; } /** * Directory changed Event. * * @param directory The directory changed */ @Override public void onDirectoryChange(final File directory) { changedDirectories.add(directory); } /** * Directory created Event. * * @param directory The directory created */ @Override public void onDirectoryCreate(final File directory) { createdDirectories.add(directory); } /** * Directory deleted Event. * * @param directory The directory deleted */ @Override public void onDirectoryDelete(final File directory) { deletedDirectories.add(directory); } /** * File changed Event. * * @param file The file changed */ @Override public void onFileChange(final File file) { changedFiles.add(file); } /** * File created Event. * * @param file The file created */ @Override public void onFileCreate(final File file) { createdFiles.add(file); } /** * File deleted Event. * * @param file The file deleted */ @Override public void onFileDelete(final File file) { deletedFiles.add(file); } /** * File system observer started checking event. * * @param observer The file system observer */ @Override public void onStart(final FileAlterationObserver observer) { if (clearOnStart) { clear(); } } /** * File system observer finished checking event. * * @param observer The file system observer */ @Override public void onStop(final FileAlterationObserver observer) { // noop } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/monitor/FileAlterationMonitorTest.java0100644 0000000 0000000 00000020123 14603604450 033232 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.io.File; import java.time.Duration; 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.ThreadUtils; import org.apache.commons.io.test.TestUtils; import org.junit.jupiter.api.Test; /** * {@link FileAlterationMonitor} Test Case. */ public class FileAlterationMonitorTest extends AbstractMonitorTest { /** * Constructs a new test case. */ public FileAlterationMonitorTest() { listener = new CollectionFileListener(false); } /** * 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 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 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 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 default constructor. */ @Test public void testDefaultConstructor() { final FileAlterationMonitor monitor = new FileAlterationMonitor(); assertEquals(10000, monitor.getInterval(), "Interval"); } /** * 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 and start again assertThrows(IllegalStateException.class, () -> monitor.start()); // 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 and stop again assertThrows(IllegalStateException.class, () -> monitor.stop()); } /** * 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()); ThreadUtils.sleep(Duration.ofMillis(10)); // wait until the watcher thread enters Thread.sleep() monitor.stop(100); createdThreads.forEach(thread -> assertFalse(thread.isAlive(), "The FileAlterationMonitor did not stop the threads it created.")); } /** * 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(); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/monitor/FileAlterationObserverTest.java0100644 0000000 0000000 00000041370 14603604450 033401 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 FileAlterationObserverTest extends AbstractMonitorTest { /** * Constructs a new instance. */ public FileAlterationObserverTest() { listener = new CollectionFileListener(true); } /** * Call {@link FileAlterationObserver#checkAndNotify()}. */ protected void checkAndNotify() { observer.checkAndNotify(); } /** * 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 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() 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() 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() 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"); } /** * Test toString(). */ @Test public void testToString() { final File file = new File("/foo"); FileAlterationObserver observer = new FileAlterationObserver(file); assertEquals("FileAlterationObserver[file='" + file.getPath() + "', true, 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()); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/monitor/FileEntryTest.java0100644 0000000 0000000 00000003727 14603604450 030674 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 org.apache.commons.io.FileUtils; import org.apache.commons.lang3.SerializationUtils; import org.junit.jupiter.api.Test; /** * Tests {@link FileEntry}. */ public class FileEntryTest { @Test public void testSerializable() { final FileEntry fe = new FileEntry(FileUtils.current()); assertEquals(fe.getChildren(), SerializationUtils.roundtrip(fe).getChildren()); assertEquals(fe.getClass(), SerializationUtils.roundtrip(fe).getClass()); assertEquals(fe.getFile(), SerializationUtils.roundtrip(fe).getFile()); assertEquals(fe.getLastModified(), SerializationUtils.roundtrip(fe).getLastModified()); assertEquals(fe.getLastModifiedFileTime(), SerializationUtils.roundtrip(fe).getLastModifiedFileTime()); assertEquals(fe.getLength(), SerializationUtils.roundtrip(fe).getLength()); assertEquals(fe.getLevel(), SerializationUtils.roundtrip(fe).getLevel()); assertEquals(fe.getName(), SerializationUtils.roundtrip(fe).getName()); assertEquals(fe.getParent(), SerializationUtils.roundtrip(fe).getParent()); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/monitor/SerializableFileTimeTest.java0100644 0000000 0000000 00000003652 14603604450 033015 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 java.io.IOException; import java.nio.file.Files; import java.nio.file.attribute.FileTime; import org.apache.commons.io.file.PathUtils; import org.apache.commons.lang3.SerializationUtils; import org.junit.jupiter.api.Test; /** * Tests {@link SerializableFileTime}. */ public class SerializableFileTimeTest { @Test public void testSerializable() throws IOException { final SerializableFileTime expected = new SerializableFileTime(Files.getLastModifiedTime(PathUtils.current())); final SerializableFileTime actual = SerializationUtils.roundtrip(expected); assertEquals(expected, actual); final FileTime expectedFt = expected.unwrap(); assertEquals(expectedFt, actual.unwrap()); assertEquals(0, actual.compareTo(expectedFt)); assertEquals(expectedFt.hashCode(), actual.hashCode()); assertEquals(expectedFt.toInstant(), actual.toInstant()); assertEquals(expectedFt.toMillis(), actual.toMillis()); assertEquals(expectedFt.toString(), actual.toString()); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/output/AppendableOutputStreamTest.java0100644 0000000 0000000 00000003122 14603604450 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.output; import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Tests {@link AppendableOutputStream}. */ public class AppendableOutputStreamTest { private AppendableOutputStream out; @BeforeEach public void setUp() { out = new AppendableOutputStream<>(new StringBuilder()); } @Test public void testWriteInt() throws Exception { out.write('F'); assertEquals("F", out.getAppendable().toString()); } @Test public void testWriteStringBuilder() throws Exception { final String testData = "ABCD"; out.write(testData.getBytes()); assertEquals(testData, out.getAppendable().toString()); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/output/AppendableWriterTest.java0100644 0000000 0000000 00000005013 14603604450 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.output; import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Tests {@link AppendableWriter}. */ public class AppendableWriterTest { private AppendableWriter out; @BeforeEach public void setUp() { out = new AppendableWriter<>(new StringBuilder()); } @SuppressWarnings("resource") @Test public void testAppendChar() throws Exception { out.append('F'); assertEquals("F", out.getAppendable().toString()); } @SuppressWarnings("resource") @Test public void testAppendCharSequence() throws Exception { final String testData = "ABCD"; out.append(testData); out.append(null); assertEquals(testData + "null", out.getAppendable().toString()); } @SuppressWarnings("resource") @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 testWriteChars() throws Exception { final String testData = "ABCD"; out.write(testData.toCharArray()); assertEquals(testData, out.getAppendable().toString()); } @Test public void testWriteInt() throws Exception { out.write('F'); assertEquals("F", out.getAppendable().toString()); } @Test public void testWriteString() throws Exception { final String testData = "ABCD"; out.write(testData); assertEquals(testData, out.getAppendable().toString()); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/output/BrokenOutputStreamTest.java0100644 0000000 0000000 00000010571 14603604450 032454 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.IOException; import java.io.OutputStream; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; /** * Tests {@link BrokenOutputStream}. */ public class BrokenOutputStreamTest { private static BrokenOutputStream createBrokenOutputStream(final Throwable exception) { if (exception instanceof IOException) { return new BrokenOutputStream((IOException) exception); } return new BrokenOutputStream(exception); } @ParameterizedTest @MethodSource("org.apache.commons.io.BrokenTestFactories#parameters") public void testClose(final Class clazz) throws Exception { final Throwable exception = clazz.newInstance(); @SuppressWarnings("resource") final BrokenOutputStream stream = createBrokenOutputStream(exception); assertEquals(exception, assertThrows(clazz, () -> stream.close())); } @ParameterizedTest @MethodSource("org.apache.commons.io.BrokenTestFactories#parameters") public void testFlush(final Class clazz) throws Exception { final Throwable exception = clazz.newInstance(); @SuppressWarnings("resource") final BrokenOutputStream stream = createBrokenOutputStream(exception); assertEquals(exception, assertThrows(clazz, () -> stream.flush())); } @Test public void testInstance() { assertNotNull(BrokenOutputStream.INSTANCE); } @Test public void testTryWithResources() { final IOException thrown = assertThrows(IOException.class, () -> { try (OutputStream newStream = new BrokenOutputStream()) { newStream.write(1); } }); assertEquals("Broken output stream", thrown.getMessage()); final Throwable[] suppressed = thrown.getSuppressed(); assertEquals(1, suppressed.length); assertEquals(IOException.class, suppressed[0].getClass()); assertEquals("Broken output stream", suppressed[0].getMessage()); } @ParameterizedTest @MethodSource("org.apache.commons.io.BrokenTestFactories#parameters") public void testWriteByteArray(final Class clazz) throws Exception { final Throwable exception = clazz.newInstance(); @SuppressWarnings("resource") final BrokenOutputStream stream = createBrokenOutputStream(exception); assertEquals(exception, assertThrows(clazz, () -> stream.write(new byte[1]))); } @ParameterizedTest @MethodSource("org.apache.commons.io.BrokenTestFactories#parameters") public void testWriteByteArrayIndexed(final Class clazz) throws Exception { final Throwable exception = clazz.newInstance(); @SuppressWarnings("resource") final BrokenOutputStream stream = createBrokenOutputStream(exception); assertEquals(exception, assertThrows(clazz, () -> stream.write(new byte[1], 0, 1))); } @ParameterizedTest @MethodSource("org.apache.commons.io.BrokenTestFactories#parameters") public void testWriteInt(final Class clazz) throws Exception { final Throwable exception = clazz.newInstance(); @SuppressWarnings("resource") final BrokenOutputStream stream = createBrokenOutputStream(exception); assertEquals(exception, assertThrows(clazz, () -> stream.write(1))); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/output/BrokenWriterTest.java0100644 0000000 0000000 00000014753 14603604450 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.output; 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.IOException; import java.io.Writer; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; /** * Tests {@link BrokenWriter}. */ public class BrokenWriterTest { private static BrokenWriter createBrokenWriter(final Throwable exception) { if (exception instanceof IOException) { return new BrokenWriter((IOException) exception); } return new BrokenWriter(exception); } @ParameterizedTest @MethodSource("org.apache.commons.io.BrokenTestFactories#parameters") public void testAppendChar(final Class clazz) throws Exception { final Throwable exception = clazz.newInstance(); @SuppressWarnings("resource") final BrokenWriter brokenWriter = createBrokenWriter(exception); assertEquals(exception, assertThrows(clazz, () -> brokenWriter.append('1'))); } @ParameterizedTest @MethodSource("org.apache.commons.io.BrokenTestFactories#parameters") public void testAppendCharSequence(final Class clazz) throws Exception { final Throwable exception = clazz.newInstance(); @SuppressWarnings("resource") final BrokenWriter brokenWriter = createBrokenWriter(exception); assertEquals(exception, assertThrows(clazz, () -> brokenWriter.append("01"))); } @ParameterizedTest @MethodSource("org.apache.commons.io.BrokenTestFactories#parameters") public void testAppendCharSequenceIndexed(final Class clazz) throws Exception { final Throwable exception = clazz.newInstance(); @SuppressWarnings("resource") final BrokenWriter brokenWriter = createBrokenWriter(exception); assertEquals(exception, assertThrows(clazz, () -> brokenWriter.append("01", 0, 1))); } @ParameterizedTest @MethodSource("org.apache.commons.io.BrokenTestFactories#parameters") public void testClose(final Class clazz) throws Exception { final Throwable exception = clazz.newInstance(); @SuppressWarnings("resource") final BrokenWriter brokenWriter = createBrokenWriter(exception); assertEquals(exception, assertThrows(clazz, () -> brokenWriter.close())); } @ParameterizedTest @MethodSource("org.apache.commons.io.BrokenTestFactories#parameters") public void testFlush(final Class clazz) throws Exception { final Throwable exception = clazz.newInstance(); @SuppressWarnings("resource") final BrokenWriter brokenWriter = createBrokenWriter(exception); assertEquals(exception, assertThrows(clazz, () -> brokenWriter.flush())); } @Test public void testInstance() { assertNotNull(BrokenWriter.INSTANCE); } @Test public void testTryWithResources() { final IOException thrown = assertThrows(IOException.class, () -> { try (Writer newWriter = new BrokenWriter()) { newWriter.write(1); } }); assertEquals("Broken writer", thrown.getMessage()); final Throwable[] suppressed = thrown.getSuppressed(); assertEquals(1, suppressed.length); assertEquals(IOException.class, suppressed[0].getClass()); assertEquals("Broken writer", suppressed[0].getMessage()); } @ParameterizedTest @MethodSource("org.apache.commons.io.BrokenTestFactories#parameters") public void testWriteCharArray(final Class clazz) throws Exception { final Throwable exception = clazz.newInstance(); @SuppressWarnings("resource") final BrokenWriter brokenWriter = createBrokenWriter(exception); assertEquals(exception, assertThrows(clazz, () -> brokenWriter.write(new char[1]))); } @ParameterizedTest @MethodSource("org.apache.commons.io.BrokenTestFactories#parameters") public void testWriteCharArrayIndexed(final Class clazz) throws Exception { final Throwable exception = clazz.newInstance(); @SuppressWarnings("resource") final BrokenWriter brokenWriter = createBrokenWriter(exception); assertEquals(exception, assertThrows(clazz, () -> brokenWriter.write(new char[1], 0, 1))); } @ParameterizedTest @MethodSource("org.apache.commons.io.BrokenTestFactories#parameters") public void testWriteInt(final Class clazz) throws Exception { final Throwable exception = clazz.newInstance(); @SuppressWarnings("resource") final BrokenWriter brokenWriter = createBrokenWriter(exception); assertEquals(exception, assertThrows(clazz, () -> brokenWriter.write(1))); } @ParameterizedTest @MethodSource("org.apache.commons.io.BrokenTestFactories#parameters") public void testWriteString(final Class clazz) throws Exception { final Throwable exception = clazz.newInstance(); @SuppressWarnings("resource") final BrokenWriter brokenWriter = createBrokenWriter(exception); assertEquals(exception, assertThrows(clazz, () -> brokenWriter.write("01"))); } @ParameterizedTest @MethodSource("org.apache.commons.io.BrokenTestFactories#parameters") public void testWriteStringIndexed(final Class clazz) throws Exception { final Throwable exception = clazz.newInstance(); @SuppressWarnings("resource") final BrokenWriter brokenWriter = createBrokenWriter(exception); assertEquals(exception, assertThrows(clazz, () -> brokenWriter.write("01", 0, 1))); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/output/ByteArrayOutputStreamTest.java0100644 0000000 0000000 00000037511 14603604450 033141 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; /** * Tests the alternative ByteArrayOutputStream implementations. */ public class ByteArrayOutputStreamTest { private interface BAOSFactory { T newInstance(); T newInstance(final int size); } private static final class ByteArrayOutputStreamFactory implements BAOSFactory { @Override public ByteArrayOutputStream newInstance() { return new ByteArrayOutputStream(); } @Override public ByteArrayOutputStream newInstance(final int size) { return new ByteArrayOutputStream(size); } } private static final class UnsynchronizedByteArrayOutputStreamFactory implements BAOSFactory { @Override public UnsynchronizedByteArrayOutputStream newInstance() { return new UnsynchronizedByteArrayOutputStream(); } @Override public UnsynchronizedByteArrayOutputStream newInstance(final int size) { return new UnsynchronizedByteArrayOutputStream(size); } } private static final byte[] DATA; static { DATA = new byte[64]; for (byte i = 0; i < 64; i++) { DATA[i] = i; } } private static Stream baosFactories() { return Stream.of(Arguments.of(ByteArrayOutputStream.class.getSimpleName(), new ByteArrayOutputStreamFactory()), Arguments.of(UnsynchronizedByteArrayOutputStream.class.getSimpleName(), new UnsynchronizedByteArrayOutputStreamFactory())); } 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 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)); } 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 testInvalidParameterizedConstruction(final String baosName, final BAOSFactory baosFactory) { assertThrows(IllegalArgumentException.class, () -> baosFactory.newInstance(-1)); } @ParameterizedTest(name = "[{index}] {0}") @MethodSource("baosFactories") public void testInvalidWriteLenUnder(final String baosName, final BAOSFactory baosFactory) throws IOException { try (AbstractByteArrayOutputStream baout = baosFactory.newInstance()) { assertThrows(IndexOutOfBoundsException.class, () -> baout.write(new byte[1], 0, -1)); } } @ParameterizedTest(name = "[{index}] {0}") @MethodSource("baosFactories") public void testInvalidWriteOffsetAndLenOver(final String baosName, final BAOSFactory baosFactory) throws IOException { try (AbstractByteArrayOutputStream baout = baosFactory.newInstance()) { assertThrows(IndexOutOfBoundsException.class, () -> baout.write(new byte[1], 0, 2)); } } @ParameterizedTest(name = "[{index}] {0}") @MethodSource("baosFactories") public void testInvalidWriteOffsetAndLenUnder(final String baosName, final BAOSFactory baosFactory) throws IOException { try (AbstractByteArrayOutputStream baout = baosFactory.newInstance()) { assertThrows(IndexOutOfBoundsException.class, () -> baout.write(new byte[1], 1, -2)); } } @ParameterizedTest(name = "[{index}] {0}") @MethodSource("baosFactories") public void testInvalidWriteOffsetOver(final String baosName, final BAOSFactory baosFactory) throws IOException { try (AbstractByteArrayOutputStream baout = baosFactory.newInstance()) { assertThrows(IndexOutOfBoundsException.class, () -> baout.write(IOUtils.EMPTY_BYTE_ARRAY, 1, 0)); } } @ParameterizedTest(name = "[{index}] {0}") @MethodSource("baosFactories") public void testInvalidWriteOffsetUnder(final String baosName, final BAOSFactory baosFactory) throws IOException { try (AbstractByteArrayOutputStream baout = baosFactory.newInstance()) { assertThrows(IndexOutOfBoundsException.class, () -> baout.write(null, -1, 0)); } } @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 (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 (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 (AbstractByteArrayOutputStream baos1 = baosFactory.newInstance(); final AbstractByteArrayOutputStream baos2 = baosFactory.newInstance()) { assertSame(baos1.toByteArray(), baos2.toByteArray()); } } } } @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 (ByteArrayInputStream bain = new ByteArrayInputStream(data)) { assertEquals(data.length, bain.available()); try (InputStream buffered = toBufferedInputStreamFunction.apply(bain)) { assertEquals(data.length, buffered.available()); assertArrayEquals(data, IOUtils.toByteArray(buffered)); } } } @ParameterizedTest(name = "[{index}] {0}") @MethodSource("toBufferedInputStreamFunctionFactories") public void testToBufferedInputStreamEmpty(final String baosName, final IOFunction toBufferedInputStreamFunction) throws IOException { try (ByteArrayInputStream bain = new ByteArrayInputStream(IOUtils.EMPTY_BYTE_ARRAY)) { assertEquals(0, bain.available()); try (InputStream buffered = toBufferedInputStreamFunction.apply(bain)) { assertEquals(0, buffered.available()); } } } @ParameterizedTest(name = "[{index}] {0}") @MethodSource("baosFactories") public void testToInputStream(final String baosName, final BAOSFactory baosFactory) throws IOException { try (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 (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 (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 testToInputStreamEmpty(final String baosName, final BAOSFactory baosFactory) throws IOException { try (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("baosFactories") public void testToInputStreamWithReset(final String baosName, final BAOSFactory baosFactory) throws IOException { // Make sure reset() do not destroy InputStream returned from toInputStream() try (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 (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 (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 testWriteZero(final String baosName, final BAOSFactory baosFactory) throws IOException { try (AbstractByteArrayOutputStream baout = baosFactory.newInstance()) { baout.write(IOUtils.EMPTY_BYTE_ARRAY, 0, 0); assertTrue(true, "Dummy"); } } 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; } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/output/ChunkedOutputStreamTest.java0100644 0000000 0000000 00000011423 14603604450 032612 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.assertThrows; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.concurrent.atomic.AtomicInteger; import org.apache.commons.io.IOUtils; import org.apache.commons.io.file.TempFile; import org.apache.commons.lang3.ArrayFill; import org.junit.jupiter.api.Test; /** * Tests {@link ChunkedOutputStream}. */ public class ChunkedOutputStreamTest { 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); } }; } /** * Tests the default chunk size with a ByteArrayOutputStream. * * @throws IOException */ @Test public void testBuildSetByteArrayOutputStream() throws IOException { final AtomicInteger numWrites = new AtomicInteger(); try (ByteArrayOutputStream baos = newByteArrayOutputStream(numWrites); final ChunkedOutputStream chunked = ChunkedOutputStream.builder().setOutputStream(baos).get()) { chunked.write(new byte[IOUtils.DEFAULT_BUFFER_SIZE + 1]); assertEquals(2, numWrites.get()); } assertThrows(IllegalStateException.class, () -> ChunkedOutputStream.builder().get()); } /** * Tests the default chunk size with a Path. * * @throws IOException */ @Test public void testBuildSetPath() throws IOException { try (TempFile tempFile = TempFile.create("test-", ".txt")) { final byte[] fill = ArrayFill.fill(new byte[IOUtils.DEFAULT_BUFFER_SIZE + 1], (byte) 'a'); final Path tempPath = tempFile.get(); try (ChunkedOutputStream chunked = ChunkedOutputStream.builder().setPath(tempPath).get()) { chunked.write(fill); } assertArrayEquals(fill, Files.readAllBytes(tempPath)); } } @Test public void testDefaultConstructor() throws IOException { final AtomicInteger numWrites = new AtomicInteger(); try (ByteArrayOutputStream baos = newByteArrayOutputStream(numWrites); final ChunkedOutputStream chunked = new ChunkedOutputStream(baos)) { chunked.write(new byte[IOUtils.DEFAULT_BUFFER_SIZE + 1]); assertEquals(2, numWrites.get()); } } @Test public void testNegativeChunkSize() throws IOException { assertThrows(IllegalArgumentException.class, () -> new ChunkedOutputStream(new ByteArrayOutputStream(), -1)); // Builder resets invalid input to the default. try (ChunkedOutputStream os = ChunkedOutputStream.builder().setOutputStream(new ByteArrayOutputStream()).setBufferSize(-1).get()) { assertEquals(IOUtils.DEFAULT_BUFFER_SIZE, os.getChunkSize()); } } @Test public void testWriteFourChunks() throws Exception { final AtomicInteger numWrites = new AtomicInteger(); try (ByteArrayOutputStream baos = newByteArrayOutputStream(numWrites); final ChunkedOutputStream chunked = new ChunkedOutputStream(baos, 10)) { chunked.write("0123456789012345678901234567891".getBytes()); assertEquals(4, numWrites.get()); } } @Test public void testZeroChunkSize() throws IOException { assertThrows(IllegalArgumentException.class, () -> new ChunkedOutputStream(new ByteArrayOutputStream(), 0)); // Builder resets invalid input to the default. try (ChunkedOutputStream os = ChunkedOutputStream.builder().setOutputStream(new ByteArrayOutputStream()).setBufferSize(0).get()) { assertEquals(IOUtils.DEFAULT_BUFFER_SIZE, os.getChunkSize()); } } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/output/ChunkedWriterTest.java0100644 0000000 0000000 00000005526 14603604450 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 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.apache.commons.io.IOUtils; import org.junit.jupiter.api.Test; /** * Tests {@link ChunkedWriter}. */ public class ChunkedWriterTest { @SuppressWarnings("resource") // closed by caller. 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 testNegative_chunkSize_not_permitted() { assertThrows(IllegalArgumentException.class, () -> new ChunkedWriter(new OutputStreamWriter(new ByteArrayOutputStream()), 0)); } @Test public void testWrite_four_chunks() throws Exception { final AtomicInteger numWrites = new AtomicInteger(); try (OutputStreamWriter osw = getOutputStreamWriter(numWrites)) { try (ChunkedWriter chunked = new ChunkedWriter(osw, 10)) { chunked.write("0123456789012345678901234567891".toCharArray()); chunked.flush(); assertEquals(4, numWrites.get()); } } } @Test public void testWrite_two_chunks_default_constructor() throws Exception { final AtomicInteger numWrites = new AtomicInteger(); try (OutputStreamWriter osw = getOutputStreamWriter(numWrites)) { try (ChunkedWriter chunked = new ChunkedWriter(osw)) { chunked.write(new char[IOUtils.DEFAULT_BUFFER_SIZE + 1]); chunked.flush(); assertEquals(2, numWrites.get()); } } } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/output/CloseShieldOutputStreamTest.java0100644 0000000 0000000 00000003713 14603604450 033432 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; /** * Tests {@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.16.1-src/src/test/java/org/apache/commons/io/output/CloseShieldWriterTest.java0100644 0000000 0000000 00000003577 14603604450 032242 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; /** * Tests {@link CloseShieldWriter}. */ public class CloseShieldWriterTest { private StringBuilderWriter original; private Writer shielded; @SuppressWarnings("resource") @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.16.1-src/src/test/java/org/apache/commons/io/output/ClosedOutputStreamTest.java0100644 0000000 0000000 00000005030 14603604450 032437 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.assertThrows; import java.io.IOException; import org.junit.jupiter.api.Test; /** * Tests {@link ClosedOutputStream}. */ public class ClosedOutputStreamTest { /** * Test the {@code flush()} method. */ @Test public void testFlush() throws IOException { try (ClosedOutputStream cos = new ClosedOutputStream()) { assertThrows(IOException.class, cos::flush); } } @Test public void testSingleton() throws IOException { try (@SuppressWarnings("deprecation") ClosedOutputStream cos = ClosedOutputStream.CLOSED_OUTPUT_STREAM) { assertThrows(IOException.class, cos::flush); } try (ClosedOutputStream cos = ClosedOutputStream.INSTANCE) { assertThrows(IOException.class, cos::flush); } } /** * Test the {@code write(b)} method. */ @Test public void testWrite() throws IOException { try (ClosedOutputStream cos = new ClosedOutputStream()) { assertThrows(IOException.class, () -> cos.write('x')); } } @Test public void testWriteArray() throws IOException { try (ClosedOutputStream cos = new ClosedOutputStream()) { assertThrows(IOException.class, () -> cos.write(new byte[0])); assertThrows(IOException.class, () -> cos.write(new byte[10])); } } @Test public void testWriteArrayIndex() throws IOException { try (ClosedOutputStream cos = new ClosedOutputStream()) { assertThrows(IOException.class, () -> cos.write(new byte[0], 0, 0)); assertThrows(IOException.class, () -> cos.write(new byte[10], 0, 1)); } } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/output/ClosedWriterTest.java0100644 0000000 0000000 00000003042 14603604450 031240 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.assertThrows; import java.io.IOException; import org.junit.jupiter.api.Test; /** * Tests {@link ClosedWriter}. */ public class ClosedWriterTest { /** * Test the {@code flush()} method. */ @Test public void testFlush() throws IOException { try (ClosedWriter cw = new ClosedWriter()) { assertThrows(IOException.class, () -> cw.flush()); } } /** * Test the {@code write(cbuf, off, len)} method. */ @Test public void testWrite() throws IOException { try (ClosedWriter cw = new ClosedWriter()) { assertThrows(IOException.class, () -> cw.write(new char[0], 0, 0)); } } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/output/CountingOutputStreamTest.java0100644 0000000 0000000 00000007443 14603604450 033026 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.ByteArrayOutputStream; import java.io.IOException; import org.apache.commons.io.IOUtils; import org.apache.commons.io.input.NullInputStream; import org.junit.jupiter.api.Test; /** * Tests {@link CountingOutputStream}. */ public class CountingOutputStreamTest { 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"); } } @Test public void testCounting() throws IOException { final ByteArrayOutputStream baos = new ByteArrayOutputStream(); try (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.INSTANCE); // Test integer methods IOUtils.copyLarge(mock, cos); assertThrows(ArithmeticException.class, () -> cos.getCount()); assertThrows(ArithmeticException.class, () -> cos.resetCount()); mock.close(); // Test long methods IOUtils.copyLarge(mock, cos); assertEquals(size, cos.getByteCount(), "getByteCount()"); assertEquals(size, cos.resetByteCount(), "resetByteCount()"); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/output/DeferredFileOutputStreamTest.java0100644 0000000 0000000 00000043256 14603604450 033562 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.File; 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.apache.commons.io.file.AbstractTempDirTest; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; /** * Tests {@code DeferredFileOutputStream}. */ public class DeferredFileOutputStreamTest extends AbstractTempDirTest { 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) throws IOException { final File testFile = Files.createTempFile(tempDirPath, "testAboveThreshold", "dat").toFile(); try (DeferredFileOutputStream dfos = DeferredFileOutputStream.builder() .setThreshold(testBytes.length - 5) .setBufferSize(initialBufferSize) .setOutputFile(testFile) .get()) { dfos.write(testBytes, 0, testBytes.length); dfos.close(); assertFalse(dfos.isInMemory()); assertNull(dfos.getData()); assertEquals(testFile.length(), dfos.getByteCount()); verifyResultFile(testFile); } } /** * 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 = Files.createTempFile(tempDirPath, "testAboveThreshold", "dat").toFile(); try (DeferredFileOutputStream dfos = DeferredFileOutputStream.builder() .setThreshold(testBytes.length - 5) .setBufferSize(initialBufferSize) .setOutputFile(testFile) .get()) { dfos.write(testBytes, 0, testBytes.length); dfos.close(); assertFalse(dfos.isInMemory()); assertEquals(testFile.length(), dfos.getByteCount()); 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) throws IOException { try (DeferredFileOutputStream dfos = DeferredFileOutputStream.builder() // @formatter:off .setThreshold(testBytes.length) .setBufferSize(initialBufferSize) .get()) { // @formatter:on dfos.write(testBytes, 0, testBytes.length); dfos.close(); assertTrue(dfos.isInMemory()); assertEquals(testBytes.length, dfos.getByteCount()); 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. * @throws IOException */ @ParameterizedTest(name = "initialBufferSize = {0}") @MethodSource("data") public void testBelowThreshold(final int initialBufferSize) throws IOException { try (DeferredFileOutputStream dfos = DeferredFileOutputStream.builder() // @formatter:off .setThreshold(testBytes.length + 42) .setBufferSize(initialBufferSize) .get()) { // @formatter:on dfos.write(testBytes, 0, testBytes.length); dfos.close(); assertTrue(dfos.isInMemory()); assertEquals(testBytes.length, dfos.getByteCount()); 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 { // @formatter:off try (DeferredFileOutputStream dfos = DeferredFileOutputStream.builder() .setThreshold(testBytes.length + 42) .setBufferSize(initialBufferSize) .get()) { // @formatter:on dfos.write(testBytes, 0, testBytes.length); dfos.close(); assertTrue(dfos.isInMemory()); assertEquals(testBytes.length, dfos.getByteCount()); try (InputStream is = dfos.toInputStream()) { assertArrayEquals(testBytes, IOUtils.toByteArray(is)); } } } /** * Tests specifying a temporary file and the threshold is reached. */ @ParameterizedTest(name = "initialBufferSize = {0}") @MethodSource("data") public void testTempFileAboveThreshold(final int initialBufferSize) throws IOException { final String prefix = "commons-io-test"; final String suffix = ".out"; // @formatter:off try (DeferredFileOutputStream dfos = DeferredFileOutputStream.builder() .setThreshold(testBytes.length - 5) .setBufferSize(initialBufferSize) .setPrefix(prefix) .setSuffix(suffix) .setDirectory(tempDirFile) .setDirectory(tempDirPath.toFile()) .get()) { // @formatter:on assertNull(dfos.getFile(), "Check File is null-A"); assertNull(dfos.getPath(), "Check Path is null-A"); dfos.write(testBytes, 0, testBytes.length); dfos.close(); assertFalse(dfos.isInMemory()); assertEquals(testBytes.length, dfos.getByteCount()); 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(tempDirPath, dfos.getPath().getParent(), "Check dir"); verifyResultFile(dfos.getFile()); } } /** * Tests specifying a temporary file and the threshold is reached. * @throws IOException */ @ParameterizedTest(name = "initialBufferSize = {0}") @MethodSource("data") public void testTempFileAboveThresholdPrefixOnly(final int initialBufferSize) throws IOException { final String prefix = "commons-io-test"; final String suffix = null; try (final DeferredFileOutputStream dfos = DeferredFileOutputStream.builder() // @formatter:off .setThreshold(testBytes.length - 5) .setBufferSize(initialBufferSize) .setPrefix(prefix) .setSuffix(suffix) .setDirectory((Path) null) .get()) { // @formatter:on try { assertNull(dfos.getFile(), "Check File is null-A"); assertNull(dfos.getPath(), "Check Path is null-A"); dfos.write(testBytes, 0, testBytes.length); dfos.close(); assertFalse(dfos.isInMemory()); assertNull(dfos.getData()); assertEquals(testBytes.length, dfos.getByteCount()); 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()); } finally { // Delete the temporary file. dfos.getFile().delete(); } } } /** * Tests specifying a temporary file and the threshold not reached. * @throws IOException */ @ParameterizedTest(name = "initialBufferSize = {0}") @MethodSource("data") public void testTempFileBelowThreshold(final int initialBufferSize) throws IOException { final String prefix = "commons-io-test"; final String suffix = ".out"; try (final DeferredFileOutputStream dfos = new DeferredFileOutputStream(testBytes.length + 42, initialBufferSize, prefix, suffix, tempDirFile)) { assertNull(dfos.getFile(), "Check File is null-A"); assertNull(dfos.getPath(), "Check Path is null-A"); dfos.write(testBytes, 0, testBytes.length); dfos.close(); assertTrue(dfos.isInMemory()); assertEquals(testBytes.length, dfos.getByteCount()); assertNull(dfos.getFile(), "Check file is null-B"); } } /** * Tests 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"; assertThrows(NullPointerException.class, () -> new DeferredFileOutputStream(testBytes.length - 5, prefix, suffix, tempDirFile)); } /** * Tests the case where the threshold is negative, and therefore the data is always written to disk. The actual data * written to disk is verified, as is the file itself. */ @ParameterizedTest(name = "initialBufferSize = {0}") @MethodSource("data") public void testThresholdNegative(final int initialBufferSize) throws IOException { final File testFile = Files.createTempFile(tempDirPath, "testThresholdNegative", "dat").toFile(); try (DeferredFileOutputStream dfos = DeferredFileOutputStream.builder() .setThreshold(-1) .setBufferSize(initialBufferSize) .setOutputFile(testFile) .get()) { dfos.write(testBytes, 0, testBytes.length); dfos.close(); assertFalse(dfos.isInMemory()); assertNull(dfos.getData()); assertEquals(testFile.length(), dfos.getByteCount()); verifyResultFile(testFile); } } /** * 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. * @throws IOException */ @ParameterizedTest(name = "initialBufferSize = {0}") @MethodSource("data") public void testThresholdReached(final int initialBufferSize) throws IOException { final File testFile = Files.createTempFile(tempDirPath, "testThresholdReached", "dat").toFile(); try (final DeferredFileOutputStream dfos = DeferredFileOutputStream.builder() // @formatter:off .setThreshold(testBytes.length /2) .setBufferSize(initialBufferSize) .setOutputFile(testFile) .get()) { // @formatter:on final int chunkSize = testBytes.length / 3; dfos.write(testBytes, 0, chunkSize); dfos.write(testBytes, chunkSize, chunkSize); dfos.write(testBytes, chunkSize * 2, testBytes.length - chunkSize * 2); dfos.close(); assertFalse(dfos.isInMemory()); assertNull(dfos.getData()); assertEquals(testBytes.length, dfos.getByteCount()); verifyResultFile(testFile); } } /** * Tests whether writeTo() properly writes large content. */ @ParameterizedTest(name = "initialBufferSize = {0}") @MethodSource("data") public void testWriteToLarge(final int initialBufferSize) throws IOException { final File testFile = Files.createTempFile(tempDirPath, "testWriteToFile", "dat").toFile(); try (ByteArrayOutputStream baos = new ByteArrayOutputStream(initialBufferSize); DeferredFileOutputStream dfos = DeferredFileOutputStream.builder().setThreshold(testBytes.length / 2).setOutputFile(testFile).get()) { dfos.write(testBytes); assertTrue(testFile.exists()); assertFalse(dfos.isInMemory()); assertEquals(testBytes.length, dfos.getByteCount()); assertThrows(IOException.class, () -> dfos.writeTo(baos)); dfos.close(); dfos.writeTo(baos); final byte[] copiedBytes = baos.toByteArray(); assertArrayEquals(testBytes, copiedBytes); verifyResultFile(testFile); } } /** * Tests whether writeTo() properly writes large content. */ @ParameterizedTest(name = "initialBufferSize = {0}") @MethodSource("data") public void testWriteToLargeCtor(final int initialBufferSize) throws IOException { final File testFile = Files.createTempFile(tempDirPath, "testWriteToFile", "dat").toFile(); try (ByteArrayOutputStream baos = new ByteArrayOutputStream(initialBufferSize); DeferredFileOutputStream dfos = new DeferredFileOutputStream(testBytes.length / 2, testFile)) { dfos.write(testBytes); assertTrue(testFile.exists()); assertFalse(dfos.isInMemory()); assertThrows(IOException.class, () -> dfos.writeTo(baos)); assertEquals(testBytes.length, dfos.getByteCount()); dfos.close(); dfos.writeTo(baos); final byte[] copiedBytes = baos.toByteArray(); assertArrayEquals(testBytes, copiedBytes); verifyResultFile(testFile); } } /** * Tests whether writeTo() properly writes small content. * @throws IOException */ @ParameterizedTest(name = "initialBufferSize = {0}") @MethodSource("data") public void testWriteToSmall(final int initialBufferSize) throws IOException { final File testFile = Files.createTempFile(tempDirPath, "testWriteToMem", "dat").toFile(); try (ByteArrayOutputStream baos = new ByteArrayOutputStream(initialBufferSize); final DeferredFileOutputStream dfos = new DeferredFileOutputStream(testBytes.length * 2, initialBufferSize, testFile)) { dfos.write(testBytes); assertTrue(dfos.isInMemory()); assertThrows(IOException.class, () -> dfos.writeTo(baos)); assertEquals(testBytes.length, dfos.getByteCount()); dfos.close(); dfos.writeTo(baos); final byte[] copiedBytes = baos.toByteArray(); assertArrayEquals(testBytes, copiedBytes); } } /** * 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) throws IOException { 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)); } } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/output/FileWriterWithEncodingTest.java0100644 0000000 0000000 00000026425 14603604450 033223 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.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 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.charset.StandardCharsets; 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 {@link FileWriterWithEncoding}. */ 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); } 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 testConstructor_File_directory() { assertThrows(IOException.class, () -> { try (Writer writer = new FileWriterWithEncoding(temporaryFolder, defaultEncoding)) { // empty } }); assertFalse(file1.exists()); assertThrows(IOException.class, () -> { try (Writer writer = FileWriterWithEncoding.builder().setFile(temporaryFolder).setCharset(defaultEncoding).get()) { // empty } }); assertFalse(file1.exists()); } @Test public void testConstructor_File_encoding_badEncoding() { assertThrows(IOException.class, () -> { try (Writer writer = new FileWriterWithEncoding(file1, "BAD-ENCODE")) { // empty } }); assertFalse(file1.exists()); } @Test public void testConstructor_File_existingFile_withContent() throws Exception { try (FileWriter fw1 = new FileWriter(file1);) { fw1.write(textContent); fw1.write(65); } assertEquals(1025, file1.length()); try (FileWriterWithEncoding fw1 = new FileWriterWithEncoding(file1, defaultEncoding)) { fw1.write("ABcd"); } assertEquals(4, file1.length()); try (FileWriterWithEncoding fw1 = FileWriterWithEncoding.builder().setFile(file1).setCharset(defaultEncoding).get()) { fw1.write("ABcd"); } assertEquals(4, file1.length()); } @Test public void testConstructor_File_nullFile() { assertThrows(NullPointerException.class, () -> { try (Writer writer = new FileWriterWithEncoding((File) null, defaultEncoding)) { // empty } }); assertFalse(file1.exists()); } @Test public void testConstructor_fileName_nullFile() { assertThrows(NullPointerException.class, () -> { try (Writer writer = new FileWriterWithEncoding((String) null, defaultEncoding)) { // empty } }); assertFalse(file1.exists()); } @Test public void testConstructorAppend_File_existingFile_withContent() throws Exception { try (FileWriter fw1 = new FileWriter(file1)) { fw1.write("ABcd"); } assertEquals(4, file1.length()); try (FileWriterWithEncoding fw1 = new FileWriterWithEncoding(file1, defaultEncoding, true)) { fw1.write("XyZ"); } assertEquals(7, file1.length()); // @formatter:off try (FileWriterWithEncoding fw1 = FileWriterWithEncoding.builder() .setFile(file1) .setCharset(defaultEncoding) .setAppend(true) .get()) { fw1.write("XyZ"); } // @formatter:on assertEquals(10, file1.length()); } @Test public void testDifferentEncoding() throws Exception { if (Charset.isSupported(StandardCharsets.UTF_16BE.name())) { 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(StandardCharsets.UTF_16LE.name())) { 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()); } } @Test public void testSameEncoding_Charset_constructor() throws Exception { try (FileWriterWithEncoding writer = new FileWriterWithEncoding(file2, Charset.defaultCharset())) { successfulRun(writer); } // @formatter:off try (FileWriterWithEncoding writer = FileWriterWithEncoding.builder() .setFile(file2) .setCharset(Charset.defaultCharset()) .get()) { successfulRun(writer); } // @formatter:on } @Test public void testSameEncoding_CharsetEncoder_constructor() throws Exception { try (FileWriterWithEncoding writer = new FileWriterWithEncoding(file2, Charset.defaultCharset().newEncoder())) { successfulRun(writer); } // @formatter:off try (FileWriterWithEncoding writer = FileWriterWithEncoding.builder() .setFile(file2) .setCharsetEncoder(Charset.defaultCharset().newEncoder()) .get()) { successfulRun(writer); } // @formatter:on } @Test public void testSameEncoding_null_Charset_constructor() throws Exception { try (FileWriterWithEncoding writer = new FileWriterWithEncoding(file2, (Charset) null)) { successfulRun(writer); } } @Test public void testSameEncoding_null_CharsetEncoder_constructor() throws Exception { try (FileWriterWithEncoding writer = new FileWriterWithEncoding(file2.getPath(), (CharsetEncoder) null)) { successfulRun(writer); } try (FileWriterWithEncoding writer = FileWriterWithEncoding.builder().setFile(file2.getPath()).get()) { successfulRun(writer); } try (FileWriterWithEncoding writer = FileWriterWithEncoding.builder().setFile(file2.getPath()).setCharsetEncoder(null).get()) { successfulRun(writer); } } @Test public void testSameEncoding_null_CharsetName_constructor() throws Exception { try (FileWriterWithEncoding writer = new FileWriterWithEncoding(file2.getPath(), (String) null)) { successfulRun(writer); } } @Test public void testSameEncoding_string_Charset_constructor() throws Exception { try (FileWriterWithEncoding writer = new FileWriterWithEncoding(file2.getPath(), Charset.defaultCharset())) { successfulRun(writer); } // @formatter:off try (FileWriterWithEncoding writer = FileWriterWithEncoding.builder() .setFile(file2.getPath()) .setCharset(Charset.defaultCharset()) .get()) { successfulRun(writer); } // @formatter:on } @Test public void testSameEncoding_string_CharsetEncoder_constructor() throws Exception { try (FileWriterWithEncoding writer = new FileWriterWithEncoding(file2.getPath(), Charset.defaultCharset().newEncoder())) { successfulRun(writer); } } @Test public void testSameEncoding_string_constructor() throws Exception { try (FileWriterWithEncoding writer = new FileWriterWithEncoding(file2, defaultEncoding)) { successfulRun(writer); } } @Test public void testSameEncoding_string_string_constructor() throws Exception { try (FileWriterWithEncoding writer = new FileWriterWithEncoding(file2.getPath(), defaultEncoding)) { successfulRun(writer); } // @formatter:off try (FileWriterWithEncoding writer = FileWriterWithEncoding.builder() .setFile(file2.getPath()) .setCharset(defaultEncoding) .get()) { successfulRun(writer); } // @formatter:on } 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(); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/output/LockableFileWriterTest.java0100644 0000000 0000000 00000016773 14603604450 032362 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.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.File; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.charset.UnsupportedCharsetException; import org.apache.commons.io.FileUtils; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; /** * Tests {@link LockableFileWriter}. *

* 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 = FileUtils.getTempDirectory(); lockFile = new File(lockDir, file.getName() + ".lck"); altLockDir = temporaryFolder; altLockFile = new File(altLockDir, file.getName() + ".lck"); } @Test public void testAlternateLockDir() throws IOException { // open a valid lockable writer try (LockableFileWriter lfw1 = new LockableFileWriter(file, StandardCharsets.UTF_8, true, altLockDir.getAbsolutePath())) { testAlternateLockDir(lfw1); } assertTrue(file.exists()); assertFalse(altLockFile.exists()); // // open a valid lockable writer // @formatter:off try (LockableFileWriter lfw1 = LockableFileWriter.builder() .setFile(file) .setCharset(StandardCharsets.UTF_8) .setAppend(true) .setLockDirectory(altLockDir) .get()) { // @formatter:on testAlternateLockDir(lfw1); } assertTrue(file.exists()); assertFalse(altLockFile.exists()); } private void testAlternateLockDir(final LockableFileWriter lfw1) { assertNotNull(lfw1); 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()); } } @Test public void testConstructor_File_directory() { assertThrows(IOException.class, () -> new LockableFileWriter(temporaryFolder)); assertFalse(file.exists()); assertFalse(lockFile.exists()); // again assertFalse(file.exists()); assertFalse(lockFile.exists()); } @Test public void testConstructor_File_encoding_badEncoding() { assertThrows(UnsupportedCharsetException.class, () -> new LockableFileWriter(file, "BAD-ENCODE")); assertFalse(file.exists()); assertFalse(lockFile.exists()); // again assertFalse(file.exists()); assertFalse(lockFile.exists()); // assertThrows(UnsupportedCharsetException.class, () -> LockableFileWriter.builder().setFile(file).setCharset("BAD-ENCODE").get()); assertFalse(file.exists()); assertFalse(lockFile.exists()); // again assertFalse(file.exists()); assertFalse(lockFile.exists()); } @Test public void testConstructor_File_nullFile() { assertThrows(NullPointerException.class, () -> new LockableFileWriter((File) null)); assertFalse(file.exists()); assertFalse(lockFile.exists()); // again assertFalse(file.exists()); assertFalse(lockFile.exists()); // assertThrows(IllegalStateException.class, () -> LockableFileWriter.builder().get()); assertFalse(file.exists()); assertFalse(lockFile.exists()); // again assertFalse(file.exists()); assertFalse(lockFile.exists()); } @Test public void testConstructor_fileName_nullFile() { assertThrows(NullPointerException.class, () -> new LockableFileWriter((String) null)); assertFalse(file.exists()); assertFalse(lockFile.exists()); // again assertFalse(file.exists()); assertFalse(lockFile.exists()); } @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 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()); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/output/NullAppendableTest.java0100644 0000000 0000000 00000002417 14603604450 031525 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; /** * Tests {@link NullAppendable}. */ 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.16.1-src/src/test/java/org/apache/commons/io/output/NullOutputStreamTest.java0100644 0000000 0000000 00000003173 14603604450 032146 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; /** * Tests {@link NullOutputStream}. */ 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 (NullOutputStream nos = NullOutputStream.INSTANCE) { process(nos); } } @Test public void testSingleton() throws IOException { try (NullOutputStream nos = NullOutputStream.INSTANCE) { process(nos); } } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/output/NullPrintStreamTest.java0100644 0000000 0000000 00000003171 14603604450 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; /** * Tests {@link NullPrintStream}. */ 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 (NullPrintStream nos = new NullPrintStream()) { process(nos); } } @Test public void testNullSingleton() throws IOException { try (NullPrintStream nos = NullPrintStream.INSTANCE) { process(nos); } } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/output/NullWriterTest.java0100644 0000000 0000000 00000002537 14603604450 030751 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 (NullWriter writer = NullWriter.INSTANCE) { 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.16.1-src/src/test/java/org/apache/commons/io/output/ProxyCollectionWriterTest.java0100644 0000000 0000000 00000046754 14603604450 033205 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; /** * Tests {@link ProxyCollectionWriter}. */ public class ProxyCollectionWriterTest { @Test public void testArrayIOExceptionOnAppendChar1() throws IOException { final Writer badW = BrokenWriter.INSTANCE; 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 = BrokenWriter.INSTANCE; 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 = BrokenWriter.INSTANCE; 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 = BrokenWriter.INSTANCE; 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 = BrokenWriter.INSTANCE; 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 = BrokenWriter.INSTANCE; 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 = BrokenWriter.INSTANCE; 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 = BrokenWriter.INSTANCE; 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 = BrokenWriter.INSTANCE; 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 = BrokenWriter.INSTANCE; 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 = BrokenWriter.INSTANCE; 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 = BrokenWriter.INSTANCE; 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 = BrokenWriter.INSTANCE; 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 = BrokenWriter.INSTANCE; 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 = BrokenWriter.INSTANCE; 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 = BrokenWriter.INSTANCE; 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 = BrokenWriter.INSTANCE; 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 = BrokenWriter.INSTANCE; 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 = BrokenWriter.INSTANCE; 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 = BrokenWriter.INSTANCE; 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 = BrokenWriter.INSTANCE; 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 (ProxyCollectionWriter teeWriter = new ProxyCollectionWriter((Writer[]) null)) { // Call any method, should not throw teeWriter.append('a'); teeWriter.flush(); } try (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 { try (StringBuilderWriter sbw1 = new StringBuilderWriter(); StringBuilderWriter sbw2 = new StringBuilderWriter(); StringBuilderWriter expected = new StringBuilderWriter(); 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.16.1-src/src/test/java/org/apache/commons/io/output/ProxyOutputStreamTest.java0100644 0000000 0000000 00000003570 14603604450 032356 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; /** * Tests {@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.16.1-src/src/test/java/org/apache/commons/io/output/ProxyWriterTest.java0100644 0000000 0000000 00000023473 14603604450 031162 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 testAppendChar() throws Exception { try (StringBuilderWriter writer = new StringBuilderWriter(); final ProxyWriter proxy = new ProxyWriter(writer)) { proxy.append('c'); assertEquals("c", writer.toString()); } } @Test public void testAppendCharSequence() throws Exception { try (StringBuilderWriter writer = new StringBuilderWriter(); final ProxyWriter proxy = new ProxyWriter(writer)) { proxy.append("ABC"); assertEquals("ABC", writer.toString()); } } @Test public void testAppendCharSequence_with_offset() throws Exception { try (StringBuilderWriter writer = new StringBuilderWriter(); final ProxyWriter proxy = new ProxyWriter(writer)) { proxy.append("ABC", 1, 3); proxy.flush(); assertEquals("BC", writer.toString()); } } @Test public void testExceptions_in_append_char() throws IOException { try (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 testExceptions_in_append_charSequence() throws IOException { try (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 testExceptions_in_append_charSequence_offset() throws IOException { try (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 testExceptions_in_close() { assertThrows(UnsupportedEncodingException.class, () -> { try (OutputStreamWriter osw = new OutputStreamWriter(new ByteArrayOutputStream()) { @Override public void close() throws IOException { throw new UnsupportedEncodingException("Bah"); } }) { try (ProxyWriter proxy = new ProxyWriter(osw)) { // noop } } }); } @Test public void testExceptions_in_flush() throws IOException { try (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 testExceptions_in_write_char_array() throws IOException { try (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 testExceptions_in_write_int() throws IOException { try (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 testExceptions_in_write_offset_char_array() throws IOException { try (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 testExceptions_in_write_string() throws IOException { try (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 testExceptions_in_write_string_offset() throws IOException { try (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 testNullCharArray() throws Exception { try (ProxyWriter proxy = new ProxyWriter(NullWriter.INSTANCE)) { proxy.write((char[]) null); proxy.write((char[]) null, 0, 0); } } @Test public void testNullCharSequence() throws Exception { try (ProxyWriter proxy = new ProxyWriter(NullWriter.INSTANCE)) { proxy.append(null); } } @Test public void testNullString() throws Exception { try (ProxyWriter proxy = new ProxyWriter(NullWriter.INSTANCE)) { proxy.write((String) null); proxy.write((String) null, 0, 0); } } @Test public void testWriteCharArray() throws Exception { try (StringBuilderWriter writer = new StringBuilderWriter(); final ProxyWriter proxy = new ProxyWriter(writer)) { proxy.write(new char[] { 'A', 'B', 'C' }); assertEquals("ABC", writer.toString()); } } @Test public void testWriteCharArrayPartial() throws Exception { try (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 testWriteInt() throws Exception { try (StringBuilderWriter writer = new StringBuilderWriter(); final ProxyWriter proxy = new ProxyWriter(writer)) { proxy.write(65); assertEquals("A", writer.toString()); } } @Test public void testWriteString() throws Exception { try (StringBuilderWriter writer = new StringBuilderWriter(); final ProxyWriter proxy = new ProxyWriter(writer)) { proxy.write("ABC"); assertEquals("ABC", writer.toString()); } } @Test public void testWriteStringPartial() throws Exception { try (StringBuilderWriter writer = new StringBuilderWriter(); final ProxyWriter proxy = new ProxyWriter(writer)) { proxy.write("ABC", 1, 2); assertEquals("BC", writer.toString()); } } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/output/QueueOutputStreamTest.java0100644 0000000 0000000 00000011416 14603604450 032317 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 testWriteInterrupted() throws Exception { try (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 testWriteString() throws Exception { try (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 testWriteStringMultiThread() throws Exception { try (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.16.1-src/src/test/java/org/apache/commons/io/output/StringBuilderWriterTest.java0100644 0000000 0000000 00000011433 14603604450 032607 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 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 testAppendChar() throws IOException { try (Writer writer = new StringBuilderWriter()) { writer.append('F').append('o').append('o'); assertEquals("Foo", writer.toString()); } } @Test public void testAppendCharSequence() throws IOException { try (Writer writer = new StringBuilderWriter()) { writer.append("Foo").append("Bar"); assertEquals("FooBar", writer.toString()); } } @Test public void testAppendCharSequencePortion() throws IOException { try (Writer writer = new StringBuilderWriter()) { writer.append("FooBar", 3, 6).append(new StringBuffer("FooBar"), 0, 3); assertEquals("BarFoo", writer.toString()); } } @Test public void testAppendConstructCapacity() throws IOException { try (Writer writer = new StringBuilderWriter(100)) { writer.append("Foo"); assertEquals("Foo", writer.toString()); } } @Test public void testAppendConstructNull() throws IOException { try (Writer writer = new StringBuilderWriter(null)) { writer.append("Foo"); assertEquals("Foo", writer.toString()); } } @Test public void testAppendConstructStringBuilder() { final StringBuilder builder = new StringBuilder("Foo"); try (StringBuilderWriter writer = new StringBuilderWriter(builder)) { writer.append("Bar"); assertEquals("FooBar", writer.toString()); assertSame(builder, writer.getBuilder()); } } @Test public void testClose() throws IOException { try (Writer writer = new StringBuilderWriter()) { writer.append("Foo"); writer.close(); writer.append("Bar"); assertEquals("FooBar", writer.toString()); } } @Test public void testWriteChar() throws IOException { try (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 (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 (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 (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 (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.16.1-src/src/test/java/org/apache/commons/io/output/TaggedOutputStreamTest.java0100644 0000000 0000000 00000010457 14603604450 032432 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; /** * Tests {@link TaggedOutputStream}. */ public class TaggedOutputStreamTest { @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 testNormalStream() { try (ByteArrayOutputStream buffer = new ByteArrayOutputStream()) { try (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 testOtherException() throws Exception { final IOException exception = new IOException("test exception"); try (TaggedOutputStream stream = new TaggedOutputStream(ClosedOutputStream.INSTANCE)) { 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.16.1-src/src/test/java/org/apache/commons/io/output/TaggedWriterTest.java0100644 0000000 0000000 00000007714 14603604450 031234 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; /** * Tests {@link TaggedWriter}. */ public class TaggedWriterTest { @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 testNormalWriter() throws IOException { try (StringBuilderWriter buffer = new StringBuilderWriter()) { try (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)); } } @Test public void testOtherException() throws Exception { final IOException exception = new IOException("test exception"); try (TaggedWriter writer = new TaggedWriter(ClosedWriter.INSTANCE)) { assertFalse(writer.isCauseOf(exception)); assertFalse(writer.isCauseOf(new TaggedIOException(exception, UUID.randomUUID()))); writer.throwIfCauseOf(exception); writer.throwIfCauseOf(new TaggedIOException(exception, UUID.randomUUID())); } } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/output/TeeOutputStreamTest.java0100644 0000000 0000000 00000010621 14603604450 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.assertThrows; 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 * Tests {@link TeeOutputStream}. */ public class TeeOutputStreamTest { 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"); } } /** * 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); assertThrows(IOException.class, tos::close); verify(goodOs).close(); } /** * 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); assertThrows(IOException.class, tos::close); 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 (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(); } } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/output/TeeWriterTest.java0100644 0000000 0000000 00000037131 14603604450 030552 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.junit.jupiter.api.Assertions.assertTrue; 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; /** * Tests {@link TeeWriter}. */ @SuppressWarnings("resource") // not necessary to close these resources public class TeeWriterTest { @Test public void testArrayIOExceptionOnAppendChar1() { final Writer badW = BrokenWriter.INSTANCE; final StringWriter goodW = mock(StringWriter.class); final ProxyCollectionWriter tw = new ProxyCollectionWriter(badW, goodW, null); final char data = 'A'; final IOExceptionList e = assertThrows(IOExceptionList.class, () -> tw.append(data)); verify(goodW).append(data); assertEquals(1, e.getCauseList().size()); assertEquals(0, e.getCause(0, IOIndexedException.class).getIndex()); } @Test public void testArrayIOExceptionOnAppendChar2() { final Writer badW = BrokenWriter.INSTANCE; final StringWriter goodW = mock(StringWriter.class); final ProxyCollectionWriter tw = new ProxyCollectionWriter(goodW, badW, null); final char data = 'A'; final IOExceptionList e = assertThrows(IOExceptionList.class, () -> tw.append(data)); verify(goodW).append(data); assertEquals(1, e.getCauseList().size()); assertEquals(1, e.getCause(0, IOIndexedException.class).getIndex()); } @Test public void testArrayIOExceptionOnAppendCharSequence1() { final Writer badW = BrokenWriter.INSTANCE; final StringWriter goodW = mock(StringWriter.class); final TeeWriter tw = new TeeWriter(badW, goodW, null); final String data = "A"; final IOExceptionList e = assertThrows(IOExceptionList.class, () -> tw.append(data)); verify(goodW).append(data); assertEquals(1, e.getCauseList().size()); assertEquals(0, e.getCause(0, IOIndexedException.class).getIndex()); } @Test public void testArrayIOExceptionOnAppendCharSequence2() { final Writer badW = BrokenWriter.INSTANCE; final StringWriter goodW = mock(StringWriter.class); final TeeWriter tw = new TeeWriter(goodW, badW, null); final String data = "A"; final IOExceptionList e = assertThrows(IOExceptionList.class, () -> tw.append(data)); verify(goodW).append(data); assertEquals(1, e.getCauseList().size()); assertEquals(1, e.getCause(0, IOIndexedException.class).getIndex()); } @Test public void testArrayIOExceptionOnAppendCharSequenceIntInt1() { final Writer badW = BrokenWriter.INSTANCE; final StringWriter goodW = mock(StringWriter.class); final TeeWriter tw = new TeeWriter(badW, goodW, null); final String data = "A"; final IOExceptionList e = assertThrows(IOExceptionList.class, () -> tw.append(data, 0, 0)); verify(goodW).append(data, 0, 0); assertEquals(1, e.getCauseList().size()); assertEquals(0, e.getCause(0, IOIndexedException.class).getIndex()); } @Test public void testArrayIOExceptionOnAppendCharSequenceIntInt2() { final Writer badW = BrokenWriter.INSTANCE; final StringWriter goodW = mock(StringWriter.class); final TeeWriter tw = new TeeWriter(goodW, badW, null); final String data = "A"; final IOExceptionList e = assertThrows(IOExceptionList.class, () -> tw.append(data, 0, 0)); 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 = BrokenWriter.INSTANCE; final StringWriter goodW = mock(StringWriter.class); final TeeWriter tw = new TeeWriter(badW, goodW, null); final IOExceptionList e = assertThrows(IOExceptionList.class, tw::close); 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 = BrokenWriter.INSTANCE; final StringWriter goodW = mock(StringWriter.class); final TeeWriter tw = new TeeWriter(goodW, badW, null); final IOExceptionList e = assertThrows(IOExceptionList.class, tw::close); verify(goodW).close(); assertEquals(1, e.getCauseList().size()); assertEquals(1, e.getCause(0, IOIndexedException.class).getIndex()); } @Test public void testArrayIOExceptionOnFlush1() { final Writer badW = BrokenWriter.INSTANCE; final StringWriter goodW = mock(StringWriter.class); final TeeWriter tw = new TeeWriter(badW, goodW, null); final IOExceptionList e = assertThrows(IOExceptionList.class, tw::flush); verify(goodW).flush(); assertEquals(1, e.getCauseList().size()); assertEquals(0, e.getCause(0, IOIndexedException.class).getIndex()); } @Test public void testArrayIOExceptionOnFlush2() { final Writer badW = BrokenWriter.INSTANCE; final StringWriter goodW = mock(StringWriter.class); final TeeWriter tw = new TeeWriter(goodW, badW, null); final IOExceptionList e = assertThrows(IOExceptionList.class, tw::flush); 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 = BrokenWriter.INSTANCE; final StringWriter goodW = mock(StringWriter.class); final TeeWriter tw = new TeeWriter(badW, goodW, null); final char[] data = { 'a' }; final IOExceptionList e = assertThrows(IOExceptionList.class, () -> tw.write(data)); 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 = BrokenWriter.INSTANCE; final StringWriter goodW = mock(StringWriter.class); final TeeWriter tw = new TeeWriter(goodW, badW, null); final char[] data = { 'a' }; final IOExceptionList e = assertThrows(IOExceptionList.class, () -> tw.write(data)); verify(goodW).write(data); assertEquals(1, e.getCauseList().size()); assertEquals(1, e.getCause(0, IOIndexedException.class).getIndex()); } @Test public void testArrayIOExceptionOnWriteCharArrayIntInt1() { final Writer badW = BrokenWriter.INSTANCE; final StringWriter goodW = mock(StringWriter.class); final TeeWriter tw = new TeeWriter(badW, goodW, null); final char[] data = { 'a' }; final IOExceptionList e = assertThrows(IOExceptionList.class, () -> tw.write(data, 0, 0)); verify(goodW).write(data, 0, 0); assertEquals(1, e.getCauseList().size()); assertEquals(0, e.getCause(0, IOIndexedException.class).getIndex()); } @Test public void testArrayIOExceptionOnWriteCharArrayIntInt2() { final Writer badW = BrokenWriter.INSTANCE; final StringWriter goodW = mock(StringWriter.class); final TeeWriter tw = new TeeWriter(goodW, badW, null); final char[] data = { 'a' }; final IOExceptionList e = assertThrows(IOExceptionList.class, () -> tw.write(data, 0, 0)); verify(goodW).write(data, 0, 0); assertEquals(1, e.getCauseList().size()); assertEquals(1, e.getCause(0, IOIndexedException.class).getIndex()); } @Test public void testArrayIOExceptionOnWriteInt1() { final Writer badW = BrokenWriter.INSTANCE; final StringWriter goodW = mock(StringWriter.class); final TeeWriter tw = new TeeWriter(badW, goodW, null); final int data = 32; final IOExceptionList e = assertThrows(IOExceptionList.class, () -> tw.write(data)); verify(goodW).write(data); assertEquals(1, e.getCauseList().size()); assertEquals(0, e.getCause(0, IOIndexedException.class).getIndex()); } @Test public void testArrayIOExceptionOnWriteInt2() { final Writer badW = BrokenWriter.INSTANCE; final StringWriter goodW = mock(StringWriter.class); final TeeWriter tw = new TeeWriter(goodW, badW, null); final IOExceptionList e = assertThrows(IOExceptionList.class, () -> tw.write(32)); verify(goodW).write(32); assertEquals(1, e.getCauseList().size()); assertEquals(1, e.getCause(0, IOIndexedException.class).getIndex()); } @Test public void testArrayIOExceptionOnWriteString1() { final Writer badW = BrokenWriter.INSTANCE; final StringWriter goodW = mock(StringWriter.class); final TeeWriter tw = new TeeWriter(badW, goodW, null); final String data = "A"; final IOExceptionList e = assertThrows(IOExceptionList.class, () -> tw.write(data)); verify(goodW).write(data); assertEquals(1, e.getCauseList().size()); assertEquals(0, e.getCause(0, IOIndexedException.class).getIndex()); } @Test public void testArrayIOExceptionOnWriteString2() { final Writer badW = BrokenWriter.INSTANCE; final StringWriter goodW = mock(StringWriter.class); final TeeWriter tw = new TeeWriter(goodW, badW, null); final String data = "A"; final IOExceptionList e = assertThrows(IOExceptionList.class, () -> tw.write(data)); verify(goodW).write(data); assertEquals(1, e.getCauseList().size()); assertEquals(1, e.getCause(0, IOIndexedException.class).getIndex()); } @Test public void testArrayIOExceptionOnWriteStringIntInt1() { final Writer badW = BrokenWriter.INSTANCE; final StringWriter goodW = mock(StringWriter.class); final TeeWriter tw = new TeeWriter(badW, goodW, null); final String data = "A"; final IOExceptionList e = assertThrows(IOExceptionList.class, () -> tw.write(data, 0, 0)); verify(goodW).write(data, 0, 0); assertEquals(1, e.getCauseList().size()); assertEquals(0, e.getCause(0, IOIndexedException.class).getIndex()); } @Test public void testArrayIOExceptionOnWriteStringIntInt2() { final Writer badW = BrokenWriter.INSTANCE; final StringWriter goodW = mock(StringWriter.class); final TeeWriter tw = new TeeWriter(goodW, badW, null); final String data = "A"; final IOExceptionList e = assertThrows(IOExceptionList.class, () -> tw.write(data, 0, 0)); 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 = BrokenWriter.INSTANCE; final StringWriter goodW = mock(StringWriter.class); final TeeWriter tw = new TeeWriter(Arrays.asList(goodW, badW, null)); final IOExceptionList e = assertThrows(IOExceptionList.class, tw::close); verify(goodW).close(); assertEquals(1, e.getCauseList().size()); assertEquals(1, e.getCause(0, IOIndexedException.class).getIndex()); } @Test public void testConstructorsNull() throws IOException { try (TeeWriter teeWriter = new TeeWriter((Writer[]) null)) { // Call any method, should not throw teeWriter.append('a'); teeWriter.flush(); } try (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 (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.16.1-src/src/test/java/org/apache/commons/io/output/ThresholdingOutputStreamTest.java0100644 0000000 0000000 00000015024 14603604450 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.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; /** * Tests {@link ThresholdingOutputStream}. */ public class ThresholdingOutputStreamTest { @Test public void testSetByteCount_OutputStream() throws Exception { final AtomicBoolean reached = new AtomicBoolean(); try (ThresholdingOutputStream tos = new ThresholdingOutputStream(3) { { setByteCount(2); } @Override protected OutputStream getOutputStream() 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 testSetByteCount_Stream() throws Exception { final AtomicBoolean reached = new AtomicBoolean(); try (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 (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 (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 (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 (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 (ThresholdingOutputStream tos = new ThresholdingOutputStream(1, os -> { throw new IllegalStateException("Threshold reached."); }, os -> new ByteArrayOutputStream(4))) { tos.write('a'); assertThrows(IllegalStateException.class, () -> tos.write('a')); } } /** * Tests the case where the threshold is negative. * The threshold is not reached until something is written to the stream. */ @Test public void testThresholdLessThanZero() throws IOException { final AtomicBoolean reached = new AtomicBoolean(); try (final ThresholdingOutputStream out = new ThresholdingOutputStream(-1) { @Override protected void thresholdReached() throws IOException { reached.set(true); } }) { assertFalse(reached.get()); out.write(89); assertTrue(reached.get()); assertTrue(out.isThresholdExceeded()); } } @Test public void testThresholdZero() throws IOException { final AtomicBoolean reached = new AtomicBoolean(); try (final ThresholdingOutputStream out = new ThresholdingOutputStream(0) { @Override protected void thresholdReached() throws IOException { reached.set(true); } }) { assertFalse(out.isThresholdExceeded()); out.write(89); assertTrue(reached.get()); assertTrue(out.isThresholdExceeded()); } } /** * Tests the case where no bytes are written. * The threshold is not reached until something is written to the stream. */ @Test public void testThresholdZeroWrite() throws IOException { final AtomicBoolean reached = new AtomicBoolean(); try (final ThresholdingOutputStream out = new ThresholdingOutputStream(7) { @Override protected void thresholdReached() throws IOException { reached.set(true); } }) { assertFalse(out.isThresholdExceeded()); assertFalse(reached.get()); out.write(new byte[0]); assertFalse(out.isThresholdExceeded()); assertFalse(reached.get()); } } }commons-io-2.16.1-src/src/test/java/org/apache/commons/io/output/UncheckedAppendableTest.java0100644 0000000 0000000 00000005677 14603604450 032517 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.StringWriter; import java.io.UncheckedIOException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Tests {@link UncheckedAppendable}. */ public class UncheckedAppendableTest { private IOException exception; private UncheckedAppendable appendableBroken; private UncheckedAppendable appendableString; @SuppressWarnings("resource") @BeforeEach public void setUp() { exception = new IOException("test exception"); appendableBroken = UncheckedAppendable.on(new BrokenWriter(exception)); appendableString = UncheckedAppendable.on(new StringWriter()); } @Test public void testAppendChar() { appendableString.append('a').append('b'); assertEquals("ab", appendableString.toString()); } @Test public void testAppendCharSequence() { appendableString.append("a").append("b"); assertEquals("ab", appendableString.toString()); } @Test public void testAppendCharSequenceIndexed() { appendableString.append("a", 0, 1).append("b", 0, 1); assertEquals("ab", appendableString.toString()); } @Test public void testAppendCharSequenceIndexedThrows() { final UncheckedIOException e = assertThrows(UncheckedIOException.class, () -> appendableBroken.append("a", 0, 1)); assertEquals(exception, e.getCause()); } @Test public void testAppendCharSequenceThrows() { final UncheckedIOException e = assertThrows(UncheckedIOException.class, () -> appendableBroken.append("a")); assertEquals(exception, e.getCause()); } @Test public void testAppendCharThrows() { final UncheckedIOException e2 = assertThrows(UncheckedIOException.class, () -> appendableBroken.append('a')); assertEquals(exception, e2.getCause()); } @Test public void testToString() { assertEquals("ab", UncheckedAppendable.on(new StringWriter(2).append("ab")).toString()); } } ././@LongLink0100644 0000000 0000000 00000000146 14603604450 011636 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/output/UncheckedFilterOutputStreamTest.javacommons-io-2.16.1-src/src/test/java/org/apache/commons/io/output/UncheckedFilterOutputStreamTest.jav0100644 0000000 0000000 00000006745 14603604450 034142 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.StringWriter; import java.io.UncheckedIOException; import java.nio.charset.Charset; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; /** * Tests {@link BrokenWriter}. */ public class UncheckedFilterOutputStreamTest { private IOException exception; private UncheckedFilterOutputStream brokenWriter; private UncheckedFilterOutputStream stringWriter; @SuppressWarnings("resource") @BeforeEach public void setUp() throws IOException { exception = new IOException("test exception"); brokenWriter = UncheckedFilterOutputStream.builder().setOutputStream(new BrokenOutputStream(exception)).get(); stringWriter = UncheckedFilterOutputStream.builder() .setOutputStream(WriterOutputStream.builder().setWriter(new StringWriter()).setCharset(Charset.defaultCharset()).get()).get(); } @Test public void testClose() { stringWriter.close(); } @Test public void testCloseThrows() { assertEquals(exception, assertThrows(UncheckedIOException.class, () -> brokenWriter.close()).getCause()); } @Test public void testEquals() { stringWriter.equals(null); } @Test @Disabled("What should happen here?") public void testEqualsThrows() { assertEquals(exception, assertThrows(UncheckedIOException.class, () -> brokenWriter.equals(null)).getCause()); } @Test public void testFlush() { stringWriter.flush(); } @Test public void testFlushThrows() { assertEquals(exception, assertThrows(UncheckedIOException.class, () -> brokenWriter.flush()).getCause()); } @Test public void testHashCode() { stringWriter.hashCode(); } @Test @Disabled("What should happen here?") public void testHashCodeThrows() { assertEquals(exception, assertThrows(UncheckedIOException.class, () -> brokenWriter.hashCode()).getCause()); } @Test public void testToString() { stringWriter.toString(); } @Test @Disabled("What should happen here?") public void testToStringThrows() { assertEquals(exception, assertThrows(UncheckedIOException.class, () -> brokenWriter.toString()).getCause()); } @Test public void testWriteInt() { stringWriter.write(1); } @Test public void testWriteIntThrows() { assertEquals(exception, assertThrows(UncheckedIOException.class, () -> brokenWriter.write(1)).getCause()); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/output/UncheckedFilterWriterTest.java0100644 0000000 0000000 00000012541 14603604450 033072 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.StringWriter; import java.io.UncheckedIOException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; /** * Tests {@link BrokenWriter}. */ public class UncheckedFilterWriterTest { private IOException exception; private UncheckedFilterWriter brokenWriter; private UncheckedFilterWriter stringWriter; @SuppressWarnings("resource") @BeforeEach public void setUp() throws IOException { exception = new IOException("test exception"); brokenWriter = UncheckedFilterWriter.builder().setWriter(new BrokenWriter(exception)).get(); stringWriter = UncheckedFilterWriter.builder().setWriter(new StringWriter()).get(); } @SuppressWarnings("resource") @Test public void testAppendChar() { stringWriter.append('1'); } @SuppressWarnings("resource") @Test public void testAppendCharSequence() { stringWriter.append("01"); } @SuppressWarnings("resource") @Test public void testAppendCharSequenceIndexed() { stringWriter.append("01", 0, 1); } @Test public void testAppendCharSequenceIndexedThrows() { assertEquals(exception, assertThrows(UncheckedIOException.class, () -> brokenWriter.append("01", 0, 1)).getCause()); } @Test public void testAppendCharSequenceThrows() { assertEquals(exception, assertThrows(UncheckedIOException.class, () -> brokenWriter.append("01")).getCause()); } @Test public void testAppendCharThrows() { assertEquals(exception, assertThrows(UncheckedIOException.class, () -> brokenWriter.append('1')).getCause()); } @Test public void testClose() { stringWriter.close(); } @Test public void testCloseThrows() { assertEquals(exception, assertThrows(UncheckedIOException.class, () -> brokenWriter.close()).getCause()); } @Test public void testEquals() { stringWriter.equals(null); } @Test @Disabled("What should happen here?") public void testEqualsThrows() { assertEquals(exception, assertThrows(UncheckedIOException.class, () -> brokenWriter.equals(null)).getCause()); } @Test public void testFlush() { stringWriter.flush(); } @Test public void testFlushThrows() { assertEquals(exception, assertThrows(UncheckedIOException.class, () -> brokenWriter.flush()).getCause()); } @Test public void testHashCode() { stringWriter.hashCode(); } @Test @Disabled("What should happen here?") public void testHashCodeThrows() { assertEquals(exception, assertThrows(UncheckedIOException.class, () -> brokenWriter.hashCode()).getCause()); } @Test public void testToString() { stringWriter.toString(); } @Test @Disabled("What should happen here?") public void testToStringThrows() { assertEquals(exception, assertThrows(UncheckedIOException.class, () -> brokenWriter.toString()).getCause()); } @Test public void testWriteCharArray() { stringWriter.write(new char[1]); } @Test public void testWriteCharArrayIndexed() { stringWriter.write(new char[1], 0, 1); } @Test public void testWriteCharArrayIndexedThrows() { assertEquals(exception, assertThrows(UncheckedIOException.class, () -> brokenWriter.write(new char[1], 0, 1)).getCause()); } @Test public void testWriteCharArrayThrows() { assertEquals(exception, assertThrows(UncheckedIOException.class, () -> brokenWriter.write(new char[1])).getCause()); } @Test public void testWriteInt() { stringWriter.write(1); } @Test public void testWriteIntThrows() { assertEquals(exception, assertThrows(UncheckedIOException.class, () -> brokenWriter.write(1)).getCause()); } @Test public void testWriteString() { stringWriter.write("01"); } @Test public void testWriteStringIndexed() { stringWriter.write("01", 0, 1); } @Test public void testWriteStringIndexedThrows() { assertEquals(exception, assertThrows(UncheckedIOException.class, () -> brokenWriter.write("01", 0, 1)).getCause()); } @Test public void testWriteStringThrows() { assertEquals(exception, assertThrows(UncheckedIOException.class, () -> brokenWriter.write("01")).getCause()); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/output/WriterOutputStreamTest.java0100644 0000000 0000000 00000022003 14603604450 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.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.Charset; import java.nio.charset.CharsetDecoder; import java.nio.charset.StandardCharsets; import java.nio.file.StandardOpenOption; import java.util.Random; import org.apache.commons.io.Charsets; import org.apache.commons.io.charset.CharsetDecoders; import org.junit.jupiter.api.Test; /** * Tests {@link WriterOutputStream}. */ public class WriterOutputStreamTest { private static final String UTF_16LE = StandardCharsets.UTF_16LE.name(); private static final String UTF_16BE = StandardCharsets.UTF_16BE.name(); private static final String UTF_16 = StandardCharsets.UTF_16.name(); private static final String UTF_8 = StandardCharsets.UTF_8.name(); 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(); @Test public void testFlush() throws IOException { final StringWriter writer = new StringWriter(); try (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 testLargeUTF8CharsetWithBufferedWrite() throws IOException { testWithBufferedWrite(LARGE_TEST_STRING, UTF_8); } @Test public void testLargeUTF8CharsetWithSingleByteWrite() throws IOException { testWithSingleByteWrite(LARGE_TEST_STRING, StandardCharsets.UTF_8); } @Test public void testLargeUTF8WithBufferedWrite() throws IOException { testWithBufferedWrite(LARGE_TEST_STRING, UTF_8); } @Test public void testLargeUTF8WithSingleByteWrite() throws IOException { testWithSingleByteWrite(LARGE_TEST_STRING, UTF_8); } @Test public void testNullCharsetDecoderWithSingleByteWrite() throws IOException { testWithSingleByteWrite(TEST_STRING, (CharsetDecoder) null); } @Test public void testNullCharsetNameWithSingleByteWrite() throws IOException { testWithSingleByteWrite(TEST_STRING, (String) null); } @Test public void testNullCharsetWithSingleByteWrite() throws IOException { testWithSingleByteWrite(TEST_STRING, (Charset) null); } @Test public void testUTF16BEWithBufferedWrite() throws IOException { testWithBufferedWrite(TEST_STRING, UTF_16BE); } @Test public void testUTF16BEWithSingleByteWrite() throws IOException { testWithSingleByteWrite(TEST_STRING, UTF_16BE); } @Test public void testUTF16LEWithBufferedWrite() throws IOException { testWithBufferedWrite(TEST_STRING, UTF_16LE); } @Test public void testUTF16LEWithSingleByteWrite() throws IOException { testWithSingleByteWrite(TEST_STRING, UTF_16LE); } @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 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 testUTF8WithBufferedWrite() throws IOException { testWithBufferedWrite(TEST_STRING, UTF_8); } @Test public void testUTF8WithSingleByteWrite() throws IOException { testWithSingleByteWrite(TEST_STRING, UTF_8); } private void testWithBufferedWrite(final String testString, final String charsetName) throws IOException { final byte[] expected = testString.getBytes(charsetName); final StringWriter writer = new StringWriter(); try (WriterOutputStream out = WriterOutputStream.builder().setWriter(writer).setCharset(charsetName).get()) { 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()); } private void testWithSingleByteWrite(final String testString, final Charset charset) throws IOException { final byte[] bytes = testString.getBytes(Charsets.toCharset(charset)); StringWriter writer = new StringWriter(); try (WriterOutputStream out = new WriterOutputStream(writer, charset)) { writeOneAtATime(bytes, out); } assertEquals(testString, writer.toString()); // writer = new StringWriter(); try (WriterOutputStream out = WriterOutputStream.builder().setWriter(writer).setCharset(charset).get()) { writeOneAtATime(bytes, out); } assertEquals(testString, writer.toString()); } private void testWithSingleByteWrite(final String testString, final CharsetDecoder charsetDecoder) throws IOException { final byte[] bytes = testString.getBytes(CharsetDecoders.toCharsetDecoder(charsetDecoder).charset()); StringWriter writer = new StringWriter(); try (WriterOutputStream out = new WriterOutputStream(writer, charsetDecoder)) { writeOneAtATime(bytes, out); } assertEquals(testString, writer.toString()); // writer = new StringWriter(); try (WriterOutputStream out = WriterOutputStream.builder().setWriter(writer).setCharsetDecoder(charsetDecoder).get()) { writeOneAtATime(bytes, out); } assertEquals(testString, writer.toString()); } private void testWithSingleByteWrite(final String testString, final String charsetName) throws IOException { final byte[] bytes = testString.getBytes(Charsets.toCharset(charsetName)); StringWriter writer = new StringWriter(); try (WriterOutputStream out = new WriterOutputStream(writer, charsetName)) { writeOneAtATime(bytes, out); } assertEquals(testString, writer.toString()); // writer = new StringWriter(); try (WriterOutputStream out = WriterOutputStream.builder().setWriter(writer).setCharset(charsetName).get()) { writeOneAtATime(bytes, out); } assertEquals(testString, writer.toString()); } @Test public void testWriteImmediately() throws IOException { final StringWriter writer = new StringWriter(); try (WriterOutputStream out = new WriterOutputStream(writer, "us-ascii", 1024, true)) { out.write("abc".getBytes(StandardCharsets.US_ASCII)); assertEquals("abc", writer.toString()); } // @formatter:off try (WriterOutputStream out = WriterOutputStream.builder() .setWriter(writer) .setCharset("us-ascii") .setBufferSize(1024) .setWriteImmediately(true) .setOpenOptions(StandardOpenOption.CREATE, StandardOpenOption.READ, StandardOpenOption.WRITE) .get()) { // @formatter:on out.write("abc".getBytes(StandardCharsets.US_ASCII)); assertEquals("abcabc", writer.toString()); } } private void writeOneAtATime(final byte[] bytes, final WriterOutputStream out) throws IOException { for (final byte b : bytes) { out.write(b); } } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/output/XmlStreamWriterTest.java0100644 0000000 0000000 00000014762 14603604450 031756 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.assertTrue; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import org.junit.jupiter.api.Test; import org.junitpioneer.jupiter.DefaultLocale; /** * Tests {@link XmlStreamWriter}. */ 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; @SuppressWarnings("resource") private static void checkXmlContent(final String xml, final String encodingName, final String defaultEncodingName) throws IOException { final ByteArrayOutputStream out = new ByteArrayOutputStream(); final XmlStreamWriter writerCheck; try (final XmlStreamWriter writer = XmlStreamWriter.builder().setOutputStream(out).setCharset(defaultEncodingName).get()) { writerCheck = writer; writer.write(xml); } final byte[] xmlContent = out.toByteArray(); final Charset charset = Charset.forName(encodingName); final Charset writerCharset = Charset.forName(writerCheck.getEncoding()); assertEquals(charset, writerCharset); assertTrue(writerCharset.contains(charset), writerCharset.name()); assertArrayEquals(xml.getBytes(encodingName), 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 ? StandardCharsets.UTF_8.name() : defaultEncoding; } checkXmlContent(xml, effectiveEncoding, defaultEncoding); } private static String createXmlContent(final String text, final String encoding) { String xmlDecl = ""; if (encoding != null) { xmlDecl = ""; } return xmlDecl + "\n" + text + ""; } @Test public void testDefaultEncoding() throws IOException { checkXmlWriter(TEXT_UNICODE, null, null); checkXmlWriter(TEXT_UNICODE, null, StandardCharsets.UTF_8.name()); checkXmlWriter(TEXT_UNICODE, null, StandardCharsets.UTF_16.name()); checkXmlWriter(TEXT_UNICODE, null, StandardCharsets.UTF_16BE.name()); checkXmlWriter(TEXT_UNICODE, null, StandardCharsets.ISO_8859_1.name()); } @Test public void testEBCDICEncoding() throws IOException { checkXmlWriter("simple text in EBCDIC", "CP1047"); } @Test public void testEmpty() throws IOException { try (final ByteArrayOutputStream out = new ByteArrayOutputStream(); XmlStreamWriter writer = new XmlStreamWriter(out)) { writer.flush(); writer.write(""); writer.flush(); writer.write("."); writer.flush(); } try (final ByteArrayOutputStream out = new ByteArrayOutputStream(); XmlStreamWriter writer = XmlStreamWriter.builder().setOutputStream(out).get()) { writer.flush(); writer.write(""); writer.flush(); writer.write("."); writer.flush(); } } @Test public void testEUC_JPEncoding() throws IOException { checkXmlWriter(TEXT_EUC_JP, "EUC-JP"); } @Test public void testLatin15Encoding() throws IOException { checkXmlWriter(TEXT_LATIN15, "ISO-8859-15"); } @Test public void testLatin1Encoding() throws IOException { checkXmlWriter(TEXT_LATIN1, StandardCharsets.ISO_8859_1.name()); } @Test public void testLatin7Encoding() throws IOException { checkXmlWriter(TEXT_LATIN7, "ISO-8859-7"); } /** Turkish language has specific rules to convert dotted and dotless 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 testNoXmlHeader() throws IOException { checkXmlContent("text with no XML header", StandardCharsets.UTF_8.name(), null); } @Test public void testUTF16BEEncoding() throws IOException { checkXmlWriter(TEXT_UNICODE, StandardCharsets.UTF_16BE.name()); } @Test public void testUTF16Encoding() throws IOException { checkXmlWriter(TEXT_UNICODE, StandardCharsets.UTF_16.name()); } @Test public void testUTF16LEEncoding() throws IOException { checkXmlWriter(TEXT_UNICODE, StandardCharsets.UTF_16LE.name()); } @Test public void testUTF8Encoding() throws IOException { checkXmlWriter(TEXT_UNICODE, StandardCharsets.UTF_8.name()); } } ././@LongLink0100644 0000000 0000000 00000000147 14603604450 011637 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/serialization/AbstractCloseableListTest.javacommons-io-2.16.1-src/src/test/java/org/apache/commons/io/serialization/AbstractCloseableListTest.ja0100644 0000000 0000000 00000003300 14603604450 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.Closeable; import java.util.ArrayList; import java.util.List; import org.apache.commons.io.IOUtils; 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<>(); @AfterEach public void cleanup() { IOUtils.closeQuietly(closeableList); } /** * 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(); } }././@LongLink0100644 0000000 0000000 00000000146 14603604450 011636 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/serialization/FullClassNameMatcherTest.javacommons-io-2.16.1-src/src/test/java/org/apache/commons/io/serialization/FullClassNameMatcherTest.jav0100644 0000000 0000000 00000003115 14603604450 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.serialization; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; /** * Tests {@link FullClassNameMatcher}. */ public class FullClassNameMatcherTest { private static final String [] NAMES_ARRAY = { Integer.class.getName(), Long.class.getName() }; @Test public void testNoNames() { final FullClassNameMatcher m = new FullClassNameMatcher(); assertFalse(m.matches(Integer.class.getName())); } @Test public void testWithNames() { final FullClassNameMatcher m = new FullClassNameMatcher(NAMES_ARRAY); assertTrue(m.matches(Integer.class.getName())); assertFalse(m.matches(String.class.getName())); } }commons-io-2.16.1-src/src/test/java/org/apache/commons/io/serialization/MockSerializedClass.java0100644 0000000 0000000 00000002611 14603604450 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.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 boolean equals(final Object obj) { if (!(obj instanceof MockSerializedClass)) { return false; } return str.equals(((MockSerializedClass) obj).str); } @Override public int hashCode() { return str.hashCode(); } }commons-io-2.16.1-src/src/test/java/org/apache/commons/io/serialization/MoreComplexObject.java0100644 0000000 0000000 00000003647 14603604450 032703 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * 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.16.1-src/src/test/java/org/apache/commons/io/serialization/MoreComplexObjectTest.java0100644 0000000 0000000 00000010071 14603604450 033530 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * 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; 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"); } @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())); } /** Trusting java.* is probably reasonable and avoids having to be too * detailed in the accepts. */ @Test public void testTrustJavaIncludingArrays() throws IOException, ClassNotFoundException { assertSerialization(closeAfterEachTest( new ValidatingObjectInputStream(inputStream) .accept(MoreComplexObject.class) .accept("java.*", "[Ljava.*") )); } /** 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 testTrustJavaLang() throws IOException, ClassNotFoundException { assertSerialization(closeAfterEachTest( new ValidatingObjectInputStream(inputStream) .accept(MoreComplexObject.class, ArrayList.class, Random.class) .accept("java.lang.*", "[Ljava.lang.*") )); } /** 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 testUseBlacklist() 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 14603604450 011631 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/serialization/RegexpClassNameMatcherTest.javacommons-io-2.16.1-src/src/test/java/org/apache/commons/io/serialization/RegexpClassNameMatcherTest.j0100644 0000000 0000000 00000004416 14603604450 034012 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * 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; /** * Tests {@link RegexpClassNameMatcher}. */ public class RegexpClassNameMatcherTest { @Test public void testNullPatternPattern() { assertThrows(NullPointerException.class, () -> new RegexpClassNameMatcher((Pattern) null)); } @Test public void testNullStringPattern() { assertThrows(NullPointerException.class, () -> new RegexpClassNameMatcher((String) null)); } @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 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 testSimplePatternFromString() { final ClassNameMatcher ca = new RegexpClassNameMatcher("foo.*"); assertTrue(ca.matches("foo.should.match")); assertFalse(ca.matches("bar.should.not.match")); } } ././@LongLink0100644 0000000 0000000 00000000155 14603604450 011636 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/serialization/ValidatingObjectInputStreamTest.javacommons-io-2.16.1-src/src/test/java/org/apache/commons/io/serialization/ValidatingObjectInputStreamT0100644 0000000 0000000 00000017745 14603604450 034137 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * 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; /** * Tests {@link ValidatingObjectInputStream}. */ public class ValidatingObjectInputStreamTest extends AbstractCloseableListTest { private static final ClassNameMatcher ALWAYS_TRUE = className -> true; private MockSerializedClass testObject; private InputStream testStream; private void assertSerialization(final ObjectInputStream ois) throws ClassNotFoundException, IOException { final MockSerializedClass result = (MockSerializedClass) ois.readObject(); assertEquals(testObject, result); } @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())); } @Test public void testAcceptCustomMatcher() throws Exception { assertSerialization( closeAfterEachTest(new ValidatingObjectInputStream(testStream)) .accept(ALWAYS_TRUE) ); } @Test public void testAcceptPattern() throws Exception { assertSerialization( closeAfterEachTest(new ValidatingObjectInputStream(testStream)) .accept(Pattern.compile(".*MockSerializedClass.*")) ); } @Test public void testAcceptWildcard() throws Exception { assertSerialization( closeAfterEachTest(new ValidatingObjectInputStream(testStream)) .accept("org.apache.commons.io.*") ); } @Test public void testCustomInvalidMethod() { final 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) )); } @Test public void testExceptionIncludesClassName() 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 testNoAccept() { assertThrows(InvalidClassException.class, () -> assertSerialization( closeAfterEachTest(new ValidatingObjectInputStream(testStream)))); } @Test public void testOurTestClassAcceptedFirst() throws Exception { assertSerialization( closeAfterEachTest(new ValidatingObjectInputStream(testStream)) .accept(MockSerializedClass.class, Integer.class) ); } @Test public void testOurTestClassAcceptedFirstWildcard() throws Exception { assertSerialization( closeAfterEachTest(new ValidatingObjectInputStream(testStream)) .accept("*MockSerializedClass", "*Integer") ); } @Test public void testOurTestClassAcceptedSecond() throws Exception { assertSerialization( closeAfterEachTest(new ValidatingObjectInputStream(testStream)) .accept(Integer.class, MockSerializedClass.class) ); } @Test public void testOurTestClassAcceptedSecondWildcard() throws Exception { assertSerialization( closeAfterEachTest(new ValidatingObjectInputStream(testStream)) .accept("*Integer", "*MockSerializedClass") ); } @Test public void testOurTestClassNotAccepted() { assertThrows(InvalidClassException.class, () -> assertSerialization( closeAfterEachTest(new ValidatingObjectInputStream(testStream)) .accept(Integer.class) )); } @Test public void testOurTestClassOnlyAccepted() throws Exception { assertSerialization( closeAfterEachTest(new ValidatingObjectInputStream(testStream)) .accept(MockSerializedClass.class) ); } @Test public void testReject() { assertThrows(InvalidClassException.class, () -> assertSerialization( closeAfterEachTest(new ValidatingObjectInputStream(testStream)) .accept(Long.class) .reject(MockSerializedClass.class, Integer.class) )); } @Test public void testRejectCustomMatcher() { assertThrows(InvalidClassException.class, () -> assertSerialization( closeAfterEachTest(new ValidatingObjectInputStream(testStream)) .accept(MockSerializedClass.class) .reject(ALWAYS_TRUE) )); } @Test public void testRejectOnly() { assertThrows(InvalidClassException.class, () -> assertSerialization( closeAfterEachTest(new ValidatingObjectInputStream(testStream)) .reject(Integer.class) )); } @Test public void testRejectPattern() { assertThrows(InvalidClassException.class, () -> assertSerialization( closeAfterEachTest(new ValidatingObjectInputStream(testStream)) .accept(MockSerializedClass.class) .reject(Pattern.compile("org.*")) )); } @Test public void testRejectPrecedence() { assertThrows(InvalidClassException.class, () -> assertSerialization( closeAfterEachTest(new ValidatingObjectInputStream(testStream)) .accept(MockSerializedClass.class) .reject(MockSerializedClass.class, Integer.class) )); } @Test public void testRejectWildcard() { assertThrows(InvalidClassException.class, () -> assertSerialization( closeAfterEachTest(new ValidatingObjectInputStream(testStream)) .accept(MockSerializedClass.class) .reject("org.*") )); } }././@LongLink0100644 0000000 0000000 00000000152 14603604450 011633 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/serialization/WildcardClassNameMatcherTest.javacommons-io-2.16.1-src/src/test/java/org/apache/commons/io/serialization/WildcardClassNameMatcherTest0100644 0000000 0000000 00000003534 14603604450 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.serialization; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; /** * Tests {@link WildcardClassNameMatcher}. */ public class WildcardClassNameMatcherTest { @Test public void testNoPattern() { 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 testStar() { final ClassNameMatcher ca = new WildcardClassNameMatcher("org*"); assertTrue(ca.matches("org.foo.should.match")); assertFalse(ca.matches("bar.should.not.match")); } @Test public void testStarAndQuestionMark() { 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.16.1-src/src/test/java/org/apache/commons/io/test/TestUtils.java0100644 0000000 0000000 00000024123 14603604450 027354 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.nio.file.Path; import java.time.Duration; import org.apache.commons.io.FileUtils; import org.apache.commons.io.output.ByteArrayOutputStream; import org.apache.commons.lang3.ThreadUtils; /** * Base class for tests 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 { assertEqualContent(b0, file.toPath()); } /** * 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 Path file) throws IOException { int count = 0, numRead = 0; final byte[] b1 = new byte[b0.length]; try (InputStream is = Files.newInputStream(file)) { 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 { assertEqualContent(c0, file.toPath()); } /** * 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 Path file) throws IOException { int count = 0, numRead = 0; final char[] c1 = new char[c0.length]; try (Reader ir = Files.newBufferedReader(file)) { 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); assertEquals(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 (BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(file.toPath()))) { generateTestData(output, size); } } public static void createFile(final Path file, final long size) throws IOException { if (!Files.exists(file.getParent())) { throw new IOException("Cannot create file " + file + " as the parent directory does not exist"); } try (BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(file))) { 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 (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 (BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(file.toPath()))) { generateTestData(output, size); } } public static byte[] generateTestData(final long size) { try { try (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; } /** * Sleeps 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. * @throws InterruptedException if interrupted. */ public static void sleep(final long millis) throws InterruptedException { ThreadUtils.sleep(Duration.ofMillis(millis)); } /** * Sleeps and swallows InterruptedException. * * @param millis the number of milliseconds to sleep. */ public static void sleepQuietly(final long millis) { try { sleep(millis); } catch (final InterruptedException ignored){ // ignore InterruptedException. } } private TestUtils() { } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/test/ThrowOnCloseInputStream.java0100644 0000000 0000000 00000003253 14603604450 032177 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 { /** * Constructs a new instance. */ public ThrowOnCloseInputStream() { super(NullInputStream.INSTANCE); } /** * Constructs a new instance. * * @param proxy InputStream to delegate to. */ public ThrowOnCloseInputStream(final InputStream proxy) { super(proxy); } /** * Always throws IOException. * * @see java.io.InputStream#close() */ @Override public void close() throws IOException { throw new IOException(getClass().getSimpleName() + ".close() called."); } } commons-io-2.16.1-src/src/test/java/org/apache/commons/io/test/ThrowOnCloseOutputStream.java0100644 0000000 0000000 00000003124 14603604450 032375 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 constructor. */ public ThrowOnCloseOutputStream() { super(NullOutputStream.INSTANCE); } /** * @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.16.1-src/src/test/java/org/apache/commons/io/test/ThrowOnCloseReader.java0100644 0000000 0000000 00000003020 14603604450 031116 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 constructor. */ public ThrowOnCloseReader() { super(NullReader.INSTANCE); } /** * @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.16.1-src/src/test/java/org/apache/commons/io/test/ThrowOnCloseWriter.java0100644 0000000 0000000 00000003022 14603604450 031172 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 constructor. */ public ThrowOnCloseWriter() { super(NullWriter.INSTANCE); } /** * @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 14603604450 011635 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/java/org/apache/commons/io/test/ThrowOnFlushAndCloseOutputStream.javacommons-io-2.16.1-src/src/test/java/org/apache/commons/io/test/ThrowOnFlushAndCloseOutputStream.java0100644 0000000 0000000 00000004242 14603604450 034024 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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#close() */ @Override public void close() throws IOException { if (throwOnClose) { fail(getClass().getSimpleName() + ".close() called."); } super.close(); } /** @see java.io.OutputStream#flush() */ @Override public void flush() throws IOException { if (throwOnFlush) { fail(getClass().getSimpleName() + ".flush() called."); } super.flush(); } public void off() { throwOnFlush = false; throwOnClose = false; } } commons-io-2.16.1-src/src/test/resources/.gitattributes0100644 0000000 0000000 00000001440 14603604450 023461 0ustar00rootroot0000000 0000000 # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # * -text ././@LongLink0100644 0000000 0000000 00000000204 14603604450 011631 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files1/directory-files-only1/file1.txtcommons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files1/0100644 0000000 0000000 00000000001 14603604450 033515 0ustar00rootroot0000000 0000000 1././@LongLink0100644 0000000 0000000 00000000204 14603604450 011631 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files1/directory-files-only1/file2.txtcommons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files1/0100644 0000000 0000000 00000000001 14603604450 033515 0ustar00rootroot0000000 0000000 2././@LongLink0100644 0000000 0000000 00000000156 14603604450 011637 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files1/file1.txtcommons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files1/0100644 0000000 0000000 00000000001 14603604450 033515 0ustar00rootroot0000000 0000000 1././@LongLink0100644 0000000 0000000 00000000156 14603604450 011637 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files1/file2.txtcommons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files1/0100644 0000000 0000000 00000000001 14603604450 033515 0ustar00rootroot0000000 0000000 2././@LongLink0100644 0000000 0000000 00000000204 14603604450 011631 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files2/directory-files-only2/file1.txtcommons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files2/0100644 0000000 0000000 00000000001 14603604450 033516 0ustar00rootroot0000000 0000000 1././@LongLink0100644 0000000 0000000 00000000204 14603604450 011631 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files2/directory-files-only2/file2.txtcommons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files2/0100644 0000000 0000000 00000000001 14603604450 033516 0ustar00rootroot0000000 0000000 2././@LongLink0100644 0000000 0000000 00000000156 14603604450 011637 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files2/file1.txtcommons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files2/0100644 0000000 0000000 00000000001 14603604450 033516 0ustar00rootroot0000000 0000000 1././@LongLink0100644 0000000 0000000 00000000156 14603604450 011637 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files2/file2.txtcommons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files2/0100644 0000000 0000000 00000000001 14603604450 033516 0ustar00rootroot0000000 0000000 2././@LongLink0100644 0000000 0000000 00000000172 14603604450 011635 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/dir1/directory-files-only1/file1.txtcommons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/dir1/directory-0100644 0000000 0000000 00000000001 14603604450 033670 0ustar00rootroot0000000 0000000 1././@LongLink0100644 0000000 0000000 00000000172 14603604450 011635 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/dir1/directory-files-only1/file2.txtcommons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/dir1/directory-0100644 0000000 0000000 00000000001 14603604450 033670 0ustar00rootroot0000000 0000000 2././@LongLink0100644 0000000 0000000 00000000172 14603604450 011635 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/dir2/directory-files-only1/file1.txtcommons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/dir2/directory-0100644 0000000 0000000 00000000001 14603604450 033671 0ustar00rootroot0000000 0000000 1././@LongLink0100644 0000000 0000000 00000000172 14603604450 011635 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/dir2/directory-files-only1/file2.txtcommons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/dir2/directory-0100644 0000000 0000000 00000000001 14603604450 033671 0ustar00rootroot0000000 0000000 2././@LongLink0100644 0000000 0000000 00000000165 14603604450 011637 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/directory-files-only1/file1.txtcommons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/directory-files0100644 0000000 0000000 00000000001 14603604450 034054 0ustar00rootroot0000000 0000000 1././@LongLink0100644 0000000 0000000 00000000165 14603604450 011637 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/directory-files-only1/file2.txtcommons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/directory-files0100644 0000000 0000000 00000000001 14603604450 034054 0ustar00rootroot0000000 0000000 2././@LongLink0100644 0000000 0000000 00000000165 14603604450 011637 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/directory-files-only2/file1.txtcommons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/directory-files0100644 0000000 0000000 00000000001 14603604450 034054 0ustar00rootroot0000000 0000000 1././@LongLink0100644 0000000 0000000 00000000165 14603604450 011637 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/directory-files-only2/file2.txtcommons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/directory-files0100644 0000000 0000000 00000000001 14603604450 034054 0ustar00rootroot0000000 0000000 2././@LongLink0100644 0000000 0000000 00000000160 14603604450 011632 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-files-only/directory-files-only1/file1.txtcommons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-files-only/directory-files-only0100644 0000000 0000000 00000000001 14603604450 034117 0ustar00rootroot0000000 0000000 1././@LongLink0100644 0000000 0000000 00000000160 14603604450 011632 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-files-only/directory-files-only1/file2.txtcommons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-files-only/directory-files-only0100644 0000000 0000000 00000000001 14603604450 034117 0ustar00rootroot0000000 0000000 2././@LongLink0100644 0000000 0000000 00000000160 14603604450 011632 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-files-only/directory-files-only2/file1.txtcommons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-files-only/directory-files-only0100644 0000000 0000000 00000000001 14603604450 034117 0ustar00rootroot0000000 0000000 1././@LongLink0100644 0000000 0000000 00000000160 14603604450 011632 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-files-only/directory-files-only2/file2.txtcommons-io-2.16.1-src/src/test/resources/dir-equals-tests/dir-equals-files-only/directory-files-only0100644 0000000 0000000 00000000001 14603604450 034117 0ustar00rootroot0000000 0000000 2commons-io-2.16.1-src/src/test/resources/org/apache/commons/io/.gitattributes0100644 0000000 0000000 00000001456 14603604450 027562 0ustar00rootroot0000000 0000000 # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # *.dat -diff commons-io-2.16.1-src/src/test/resources/org/apache/commons/io/CharSequenceReader.bin0100644 0000000 0000000 00000000213 14603604450 031040 0ustar00rootroot0000000 0000000 sr.org.apache.commons.io.input.CharSequenceReader3n:IidxImarkL charSequencetLjava/lang/CharSequence;xptFooBarcommons-io-2.16.1-src/src/test/resources/org/apache/commons/io/FileUtilsTestDataCR.dat0100644 0000000 0000000 00000000006 14603604450 031126 0ustar00rootroot0000000 0000000 1 2 3 commons-io-2.16.1-src/src/test/resources/org/apache/commons/io/FileUtilsTestDataCRLF.dat0100644 0000000 0000000 00000000011 14603604450 031344 0ustar00rootroot0000000 0000000 1 2 3 commons-io-2.16.1-src/src/test/resources/org/apache/commons/io/FileUtilsTestDataLF.dat0100644 0000000 0000000 00000000006 14603604450 031123 0ustar00rootroot0000000 0000000 1 2 3 commons-io-2.16.1-src/src/test/resources/org/apache/commons/io/TIKA-4065.bin0100644 0000000 0000000 00000003640 14603604450 026502 0ustar00rootroot0000000 0000000 W]HW>ɆFZlMMjפmLf_MjÆRLBBdևyH*>a+YvՌ|b  >9;;ٱsw9;?{DnMZ p>{9?m48 "|}&OMIK ޙIA'Vz|n i3J@"=Z8=u[R{=#q\Hs@@Vۺ>ϰO \վ/=EH̥Qhޮ5E$9amU>oΕe8q#B9#rRp}vsy\>)-N{KFb ^ Ь`7lӊgv<`6$h)se%41 1`=3qЃJº, ^;ݞ; O 8RE5JZ&Cݺ @\fPgK4%CXwF ~*8bP!9dD2Oh`Ԕu%˰Bm:oGᱶ3#C|=3{V$ gxGi f$Z5d/z8OP6q[oXqv0{OG[)F&0Ewq Di!BO#O-/^Z/mkg#ꏂ ~;mjvŭ4r~/h憦R_Ns rcFhEYG ͺc:#_9_commons-io-2.16.1-src/src/test/resources/org/apache/commons/io/abitmorethan16k.txt0100644 0000000 0000000 00000041770 14603604450 030432 0ustar00rootroot0000000 0000000 ## Licensed to the Apache Software Foundation (ASF) under one ## or more contributor license agreements. See the NOTICE file ## distributed with this work for additional information ## regarding copyright ownership. The ASF licenses this file ## to you under the Apache License, Version 2.0 (the ## "License"); you may not use this file except in compliance ## with the License. You may obtain a copy of the License at ## ## http://www.apache.org/licenses/LICENSE-2.0 ## ## Unless required by applicable law or agreed to in writing, ## software distributed under the License is distributed on an ## "AS IS" BASIS, WITHOUT 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.16.1-src/src/test/resources/org/apache/commons/io/abitmorethan16kcopy.txt0100644 0000000 0000000 00000041770 14603604450 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. 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.16.1-src/src/test/resources/org/apache/commons/io/bla-copy.zip0100644 0000000 0000000 00000001232 14603604450 027111 0ustar00rootroot0000000 0000000 PKaZn7T>b test1.xmlUT :Guvh͏JCk.H{uy L;jNnfkFؾ| nAڶ/ PKaZn7l5FR test2.xmlUT :GL PKaZn7T>b test1.xmlUT:GUxPKaZn7l5FR ztest2.xmlUT:GUxPKcommons-io-2.16.1-src/src/test/resources/org/apache/commons/io/bla.zip0100644 0000000 0000000 00000001232 14603604450 026141 0ustar00rootroot0000000 0000000 PKaZn7T>b test1.xmlUT :Guvh͏JCk.H{uy L;jNnfkFؾ| nAڶ/ PKaZn7l5FR test2.xmlUT :GL PKaZn7T>b test1.xmlUT:GUxPKaZn7l5FR ztest2.xmlUT:GUxPKcommons-io-2.16.1-src/src/test/resources/org/apache/commons/io/dirs-1-file-size-0/file-size-0.bin0100644 0000000 0000000 00000000000 14603604450 032506 0ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/test/resources/org/apache/commons/io/dirs-1-file-size-1/file-size-1.bin0100644 0000000 0000000 00000000001 14603604450 032511 0ustar00rootroot0000000 0000000 a././@LongLink0100644 0000000 0000000 00000000165 14603604450 011637 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/resources/org/apache/commons/io/dirs-2-file-size-2/dirs-a-file-size-1/file-size-1.bincommons-io-2.16.1-src/src/test/resources/org/apache/commons/io/dirs-2-file-size-2/dirs-a-file-size-10100644 0000000 0000000 00000000001 14603604450 033121 0ustar00rootroot0000000 0000000 a././@LongLink0100644 0000000 0000000 00000000165 14603604450 011637 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/resources/org/apache/commons/io/dirs-2-file-size-2/dirs-b-file-size-1/file-size-1.bincommons-io-2.16.1-src/src/test/resources/org/apache/commons/io/dirs-2-file-size-2/dirs-b-file-size-10100644 0000000 0000000 00000000001 14603604450 033122 0ustar00rootroot0000000 0000000 a././@LongLink0100644 0000000 0000000 00000000165 14603604450 011637 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/resources/org/apache/commons/io/dirs-2-file-size-4/dirs-a-file-size-1/file-size-1.bincommons-io-2.16.1-src/src/test/resources/org/apache/commons/io/dirs-2-file-size-4/dirs-a-file-size-10100644 0000000 0000000 00000000002 14603604450 033124 0ustar00rootroot0000000 0000000 ab././@LongLink0100644 0000000 0000000 00000000165 14603604450 011637 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/resources/org/apache/commons/io/dirs-2-file-size-4/dirs-a-file-size-1/file-size-2.bincommons-io-2.16.1-src/src/test/resources/org/apache/commons/io/dirs-2-file-size-4/dirs-a-file-size-10100644 0000000 0000000 00000000002 14603604450 033124 0ustar00rootroot0000000 0000000 ac././@LongLink0100644 0000000 0000000 00000000165 14603604450 011637 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/resources/org/apache/commons/io/dirs-2-file-size-4/dirs-b-file-size-1/file-size-1.bincommons-io-2.16.1-src/src/test/resources/org/apache/commons/io/dirs-2-file-size-4/dirs-b-file-size-10100644 0000000 0000000 00000000002 14603604450 033125 0ustar00rootroot0000000 0000000 ab././@LongLink0100644 0000000 0000000 00000000165 14603604450 011637 Lustar 0000000 0000000 commons-io-2.16.1-src/src/test/resources/org/apache/commons/io/dirs-2-file-size-4/dirs-b-file-size-1/file-size-2.bincommons-io-2.16.1-src/src/test/resources/org/apache/commons/io/dirs-2-file-size-4/dirs-b-file-size-10100644 0000000 0000000 00000000002 14603604450 033125 0ustar00rootroot0000000 0000000 accommons-io-2.16.1-src/src/test/resources/org/apache/commons/io/io639-1.bin0100644 0000000 0000000 00000000011 14603604450 026352 0ustar00rootroot0000000 0000000 the test commons-io-2.16.1-src/src/test/resources/org/apache/commons/io/io639-2.bin0100644 0000000 0000000 00000000006 14603604450 026357 0ustar00rootroot0000000 0000000 test commons-io-2.16.1-src/src/test/resources/org/apache/commons/io/io639-3.bin0100644 0000000 0000000 00000000007 14603604450 026361 0ustar00rootroot0000000 0000000 test commons-io-2.16.1-src/src/test/resources/org/apache/commons/io/io639-4.bin0100644 0000000 0000000 00000000002 14603604450 026355 0ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/test/resources/org/apache/commons/io/io639-5.bin0100644 0000000 0000000 00000000001 14603604450 026355 0ustar00rootroot0000000 0000000 commons-io-2.16.1-src/src/test/resources/org/apache/commons/io/moby.zip0100644 0000000 0000000 00000011441 14603604450 026354 0ustar00rootroot0000000 0000000 PK " %READMEKO O'/% %% ?%%$(9n _T5&ͥ{[)T9!lÅ!1qx̡~{Zֿdkg3o.uy?__R~R͡~~3N^ʽ9+,3߷ߵ%5~"/ K)1 7?Mm鄟BKn=;%LjM/k"{q޳//H^~>VϷ(SP%R-*4RlԟzJ[ bHޟGNX|ɼ@ ZʦHo /b@T!$"ei|}ɚ~a+۲uBuzIl}}q'|yTWumSg/(,TK䯲ϨlC{NĮJqm%E\m*-"_oNҒ߱~yH]xe) c)xW_vl>GNb}j.858}j_}Oy|lq oVӄ{evrm{~W zzIR{Qz1U(Uk6gy[L_EsZTcn4F= 9x~/gkiuMzdz\6gj?Nr 4fOR{$VcۜE7KA A!jKgŝ Qm%X.%^er|j^?ڵjgߚsKr}벀)VhDպPcoaR-pd9t,RrY# UG!r@1_7e,  /U?kZhe3H-Kq|4~rmfj{ZJDUOd~$;Ƽ2 Qr''ixc~.uw2U2+7w!}VÏȺ 0z fze,!ӲjfY Ktn #mŗAy%;  Vd\WC6 JxwIrJrGտg댋Ȳܻ!./ Jdz{j\`)FՏE7, .=p-z)s,t~R=hTate[Rp`B^:\ ,@R5+'k0*XC+"kvzF ]YҨIX\h^zD8I/) ݅*5N禭0f}.;aevagQglEfFc^=%[Ty+K ^dѮyY;6=ؔ>NVftWf"1{C?Hqqf["pGЊߴN+s.d.J9E-i1^N*a4kEM89Rzr dԈ & ,kK0[(űG BBZDnnTH*s=vBYø|" y #o߅4TSNdt9NydemAZWQՖ1(jZeF&y Qh굿 i?j-і$% ` Q؏z\oVE1ueQ'! lxV'wiiNٝ"$<ΩՆ7+k}Q{oaV^v`k4cS112/2Cm{Ό}]L&ћ?=.+5]xB^~L]o.UZ?{KɛZ+MiVwY~ZEc;Pmje!Y }>ehкt0=H ?e C`|ᇓ(*C݊<՝=ekbryz.3Y#kjNt#@3TEі//cf oc(q*XŏpG^ rQ2ۺk`F9tZ}4Kl8쟍A 2%3Ҥfl)4%<:lUБ:}1)QW"*X^80U!q_&7 cLO)8h*$K26jv#WݧIb%soD)vNw ԰ak sQLU3/9XOI+tRA GkSB߲6wYZ꜍1@;I%~!; a@cX>wǏV%Ԋ@|h97] ~~2_zR| 3Mp%^pI]oq,ˆ7yA)yKx8x.n΄}pApѝ^(8OWY g'!L[u9+Oo$ VovE}Vs*(IٳIE4{A],[3o[kǭQWF}+X y؄e^>CuAMtc"M;@xڸ`į/A C2pۤ5gE:F=S~s~O KEjTF%M*iR[$ #D\|Pg3#S<+6q7U2̯]J#= p o8e"dxflG$pyngމ)iNdS\eUݞ8$RZurgq$"ۈ* ߹H%t3m#jclt I<[ ;VP>M< L6-6ځ$aw~HrfR\j 6P_ x0FO?f#*9s7t %1qb9,QdPi8IҠ<'D e]ûa^\$`jB oL=5$@_gw!r|]p5#,QoN~#9lxOIf SIL[Q$h )V+XTBȉHM1ߊ:< A.j^~,5`1Pfnpd-əEk 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.16.1-src/src/test/resources/org/apache/commons/io/testfileNoBOM.xml0100644 0000000 0000000 00000015360 14603604450 030062 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

* This is a functional interface whose functional method is * {@link #apply(Object, Object, Object)}. *