Skip to content

Commit cd3271f

Browse files
committed
Merge remote-tracking branch 'upstream/master'
2 parents 02cab72 + 248e10e commit cd3271f

11 files changed

Lines changed: 108 additions & 92 deletions

File tree

.github/workflows/codeql-analysis.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ jobs:
6363
6464
# Initializes the CodeQL tools for scanning.
6565
- name: Initialize CodeQL
66-
uses: github/codeql-action/init@c6f931105cb2c34c8f901cc885ba1e2e259cf745 # v4.34.0
66+
uses: github/codeql-action/init@38697555549f1db7851b81482ff19f1fa5c4fedc # v4.34.1
6767
with:
6868
languages: ${{ matrix.language }}
6969
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -74,7 +74,7 @@ jobs:
7474
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
7575
# If this step fails, then you should remove it and run the build manually (see below)
7676
- name: Autobuild
77-
uses: github/codeql-action/autobuild@c6f931105cb2c34c8f901cc885ba1e2e259cf745 # v4.34.0
77+
uses: github/codeql-action/autobuild@38697555549f1db7851b81482ff19f1fa5c4fedc # v4.34.1
7878

7979
# ℹ️ Command-line programs to run using the OS shell.
8080
# 📚 https://git.io/JvXDl
@@ -88,4 +88,4 @@ jobs:
8888
# make release
8989

9090
- name: Perform CodeQL Analysis
91-
uses: github/codeql-action/analyze@c6f931105cb2c34c8f901cc885ba1e2e259cf745 # v4.34.0
91+
uses: github/codeql-action/analyze@38697555549f1db7851b81482ff19f1fa5c4fedc # v4.34.1

.github/workflows/scorecards-analysis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,6 @@ jobs:
6666
retention-days: 5
6767

6868
- name: "Upload to code-scanning"
69-
uses: github/codeql-action/upload-sarif@c6f931105cb2c34c8f901cc885ba1e2e259cf745 # v4.34.0
69+
uses: github/codeql-action/upload-sarif@38697555549f1db7851b81482ff19f1fa5c4fedc # v4.34.1
7070
with:
7171
sarif_file: results.sarif

src/changes/changes.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ The <action> type attribute can be add,update,fix,remove.
6666
<action type="fix" dev="ggregory" due-to="Gary Gregory">AbstractStreamBuilder.setOpenOptions(OpenOption...) now makes a defensive copy of its input array.</action>
6767
<action type="fix" dev="ggregory" due-to="Peter De Maeyer, Gary Gregory" issue="IO-885">Path visits follow links #832.</action>
6868
<action type="fix" dev="ggregory" due-to="Gary Gregory">BOMInputStream fail-fast and tracks its ByteOrderMark as a final #835.</action>
69+
<action type="fix" dev="ggregory" due-to="Gary Gregory">Refactor UnixLineEndingInputStream and WindowsLineEndingInputStream for duplication.</action>
70+
<action type="fix" dev="ggregory" due-to="Peter De Maeyer, Gary Gregory" issue="IO-857">[Javadoc] PathUtils.cleanDirectory() methods vs FileUtils.</action>
6971
<!-- ADD -->
7072
<action type="add" dev="ggregory" due-to="Gary Gregory, Piotr P. Karwasz">Add and use IOUtils.closeQuietlySuppress(Closeable, Throwable) #818.</action>
7173
<action type="add" dev="ggregory" due-to="Gary Gregory">Add ProxyWriter.setReference(Writer).</action>

src/main/java/org/apache/commons/io/file/PathUtils.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,10 @@ private static AccumulatorPathVisitor accumulate(final Path directory, final int
281281
}
282282

283283
/**
284-
* Cleans a directory by only deleting files, including in subdirectories, but without deleting the directories.
284+
* Cleans a directory by only deleting files, including in subdirectories, without deleting directories.
285+
* <p>
286+
* This leaves a directory empty of files but the directory and any subdirectories remain.
287+
* </p>
285288
*
286289
* @param directory directory to clean.
287290
* @return The visitation path counters.
@@ -292,7 +295,10 @@ public static PathCounters cleanDirectory(final Path directory) throws IOExcepti
292295
}
293296

294297
/**
295-
* Cleans a directory by only deleting files, including in subdirectories, but without deleting the directories.
298+
* Cleans a directory by only deleting files, including in subdirectories, without deleting directories.
299+
* <p>
300+
* This leaves a directory empty of files but the directory and any subdirectories remain.
301+
* </p>
296302
*
297303
* @param directory directory to clean.
298304
* @param deleteOptions How to handle deletion.
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* https://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.commons.io.input;
19+
20+
import java.io.IOException;
21+
import java.io.InputStream;
22+
23+
/**
24+
* Abstracts {@link UnixLineEndingInputStream} and {@link WindowsLineEndingInputStream} to reduce duplication.
25+
*/
26+
abstract class AbstractLineEndingInputStream extends InputStream {
27+
28+
boolean atEos;
29+
30+
boolean atSlashCr;
31+
32+
boolean atSlashLf;
33+
34+
final InputStream in;
35+
36+
final boolean lineFeedAtEos;
37+
38+
/**
39+
* Constructs an input stream that filters another stream
40+
*
41+
* @param inputStream The input stream to wrap.
42+
* @param lineFeedAtEos true to ensure that the file ends with LF.
43+
*/
44+
AbstractLineEndingInputStream(final InputStream inputStream, final boolean lineFeedAtEos) {
45+
this.in = inputStream;
46+
this.lineFeedAtEos = lineFeedAtEos;
47+
}
48+
49+
/**
50+
* Closes the stream. Also closes the underlying stream.
51+
*
52+
* @throws IOException If an I/O error occurs.
53+
*/
54+
@Override
55+
public void close() throws IOException {
56+
super.close();
57+
in.close();
58+
}
59+
60+
/**
61+
* {@inheritDoc}
62+
*/
63+
@Override
64+
public synchronized void mark(final int readLimit) {
65+
throw UnsupportedOperationExceptions.mark();
66+
}
67+
}

src/main/java/org/apache/commons/io/input/Input.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
final class Input {
2727

2828
/**
29-
* Throws an IOException on false input.
29+
* Throws an {@link IOException} on false input.
3030
*
3131
* @param isOpen whether an input is open or not.
3232
* @throws IOException if {@code isOpen} is false indicating an input is closed.
@@ -38,7 +38,7 @@ static void checkOpen(final boolean isOpen) throws IOException {
3838
}
3939

4040
/**
41-
* Converts an InterruptedException to an InterruptedIOException.
41+
* Converts an {@link InterruptedException} to an {@link InterruptedIOException}.
4242
* <p>
4343
* The cause of the returned InterruptedIOException is set to the original.
4444
* </p>

src/main/java/org/apache/commons/io/input/UnixLineEndingInputStream.java

Lines changed: 7 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -28,38 +28,16 @@
2828
*
2929
* @since 2.5
3030
*/
31-
public class UnixLineEndingInputStream extends InputStream {
32-
33-
private boolean atEos;
34-
35-
private boolean atSlashCr;
36-
37-
private boolean atSlashLf;
38-
39-
private final InputStream in;
40-
41-
private final boolean lineFeedAtEndOfFile;
31+
public class UnixLineEndingInputStream extends AbstractLineEndingInputStream {
4232

4333
/**
4434
* Constructs an input stream that filters another stream
4535
*
4636
* @param inputStream The input stream to wrap.
47-
* @param ensureLineFeedAtEndOfFile true to ensure that the file ends with LF.
48-
*/
49-
public UnixLineEndingInputStream(final InputStream inputStream, final boolean ensureLineFeedAtEndOfFile) {
50-
this.in = inputStream;
51-
this.lineFeedAtEndOfFile = ensureLineFeedAtEndOfFile;
52-
}
53-
54-
/**
55-
* Closes the stream. Also closes the underlying stream.
56-
*
57-
* @throws IOException If an I/O error occurs.
37+
* @param lineFeedAtEos true to ensure that the file ends with LF.
5838
*/
59-
@Override
60-
public void close() throws IOException {
61-
super.close();
62-
in.close();
39+
public UnixLineEndingInputStream(final InputStream inputStream, final boolean lineFeedAtEos) {
40+
super(inputStream, lineFeedAtEos);
6341
}
6442

6543
/**
@@ -69,7 +47,7 @@ public void close() throws IOException {
6947
* @return The next char to output to the stream.
7048
*/
7149
private int handleEos(final boolean previousWasSlashCr) {
72-
if (previousWasSlashCr || !lineFeedAtEndOfFile) {
50+
if (previousWasSlashCr || !lineFeedAtEos) {
7351
return EOF;
7452
}
7553
if (!atSlashLf) {
@@ -79,14 +57,6 @@ private int handleEos(final boolean previousWasSlashCr) {
7957
return EOF;
8058
}
8159

82-
/**
83-
* {@inheritDoc}
84-
*/
85-
@Override
86-
public synchronized void mark(final int readLimit) {
87-
throw UnsupportedOperationExceptions.mark();
88-
}
89-
9060
/**
9161
* {@inheritDoc}
9262
*/
@@ -96,7 +66,7 @@ public synchronized int read() throws IOException {
9666
if (atEos) {
9767
return handleEos(previousWasSlashR);
9868
}
99-
final int target = readWithUpdate();
69+
final int target = readUpdate();
10070
if (atEos) {
10171
return handleEos(previousWasSlashR);
10272
}
@@ -117,7 +87,7 @@ public synchronized int read() throws IOException {
11787
* @return the next int read from the target stream.
11888
* @throws IOException If an I/O error occurs.
11989
*/
120-
private int readWithUpdate() throws IOException {
90+
private int readUpdate() throws IOException {
12191
final int target = this.in.read();
12292
atEos = target == EOF;
12393
if (atEos) {

src/main/java/org/apache/commons/io/input/WindowsLineEndingInputStream.java

Lines changed: 2 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -28,40 +28,18 @@
2828
*
2929
* @since 2.5
3030
*/
31-
public class WindowsLineEndingInputStream extends InputStream {
32-
33-
private boolean atEos;
34-
35-
private boolean atSlashCr;
36-
37-
private boolean atSlashLf;
38-
39-
private final InputStream in;
31+
public class WindowsLineEndingInputStream extends AbstractLineEndingInputStream {
4032

4133
private boolean injectSlashLf;
4234

43-
private final boolean lineFeedAtEos;
44-
4535
/**
4636
* Constructs an input stream that filters another stream.
4737
*
4838
* @param in The input stream to wrap.
4939
* @param lineFeedAtEos true to ensure that the stream ends with CRLF.
5040
*/
5141
public WindowsLineEndingInputStream(final InputStream in, final boolean lineFeedAtEos) {
52-
this.in = in;
53-
this.lineFeedAtEos = lineFeedAtEos;
54-
}
55-
56-
/**
57-
* Closes the stream. Also closes the underlying stream.
58-
*
59-
* @throws IOException If an I/O error occurs.
60-
*/
61-
@Override
62-
public void close() throws IOException {
63-
super.close();
64-
in.close();
42+
super(in, lineFeedAtEos);
6543
}
6644

6745
/**
@@ -85,14 +63,6 @@ private int handleEos() {
8563
return EOF;
8664
}
8765

88-
/**
89-
* {@inheritDoc}
90-
*/
91-
@Override
92-
public synchronized void mark(final int readLimit) {
93-
throw UnsupportedOperationExceptions.mark();
94-
}
95-
9666
/**
9767
* {@inheritDoc}
9868
*/

src/test/java/org/apache/commons/io/FileUtilsCleanDirectoryTest.java

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -68,66 +68,57 @@ private boolean chmod(final File file, final int mode, final boolean recurse) th
6868
void testCleanDirectoryToForceDelete() throws Exception {
6969
final File file = new File(tempDirFile, "restricted");
7070
FileUtils.touch(file);
71-
7271
// 300 = owner: WE.
7372
// 500 = owner: RE.
7473
// 700 = owner: RWE.
7574
assumeTrue(chmod(tempDirFile, 700, false));
76-
7775
// cleanDirectory calls forceDelete
7876
FileUtils.cleanDirectory(tempDirFile);
77+
assertTrue(tempDirFile.exists());
7978
}
8079

8180
@Test
8281
void testCleanEmpty() throws Exception {
8382
assertEquals(0, tempDirFile.list().length);
84-
8583
FileUtils.cleanDirectory(tempDirFile);
86-
84+
assertTrue(tempDirFile.exists());
8785
assertEquals(0, tempDirFile.list().length);
8886
}
8987

9088
@Test
9189
void testDeletesNested() throws Exception {
9290
final File nested = new File(tempDirFile, "nested");
93-
9491
assertTrue(nested.mkdirs());
95-
9692
FileUtils.touch(new File(nested, "file"));
97-
9893
assertEquals(1, tempDirFile.list().length);
99-
10094
FileUtils.cleanDirectory(tempDirFile);
101-
95+
assertTrue(tempDirFile.exists());
10296
assertEquals(0, tempDirFile.list().length);
10397
}
10498

10599
@Test
106100
void testDeletesRegular() throws Exception {
107101
FileUtils.touch(new File(tempDirFile, "regular"));
108102
FileUtils.touch(new File(tempDirFile, ".hidden"));
109-
110103
assertEquals(2, tempDirFile.list().length);
111-
112104
FileUtils.cleanDirectory(tempDirFile);
113-
105+
assertTrue(tempDirFile.exists());
114106
assertEquals(0, tempDirFile.list().length);
115107
}
116108

117109
@DisabledOnOs(OS.WINDOWS)
118110
@Test
119111
void testThrowsOnNullList() throws Exception {
120-
// test won't work if we can't restrict permissions on the
121-
// directory, so skip it.
112+
// test won't work if we can't restrict permissions on the directory, so skip it.
122113
assumeTrue(chmod(tempDirFile, 0, false));
123-
124114
try {
125115
// cleanDirectory calls forceDelete
126116
final IOException e = assertThrows(IOException.class, () -> FileUtils.cleanDirectory(tempDirFile));
127117
assertEquals("Unknown I/O error listing contents of directory: " + tempDirFile.getAbsolutePath(), e.getMessage());
128118
} finally {
129119
chmod(tempDirFile, 755, false);
130120
}
121+
assertTrue(tempDirFile.exists());
131122
}
132123

133124
}

src/test/java/org/apache/commons/io/FileUtilsCleanSymlinksTest.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ void testCleanDirWithASymlinkDir() throws Exception {
8282

8383
// assert contents of the real directory were removed including the symlink
8484
FileUtils.cleanDirectory(realOuter);
85+
assertTrue(realOuter.exists());
8586
assertEquals(0, realOuter.list().length);
8687

8788
// ensure that the contents of the symlink were NOT removed.
@@ -121,6 +122,7 @@ void testCleanDirWithParentSymlinks() throws Exception {
121122
// assert contents of the real directory were removed including the symlink
122123
// should clean the contents of this but not recurse into other links
123124
FileUtils.cleanDirectory(symlinkParentDirectory);
125+
assertTrue(symlinkParentDirectory.exists());
124126
assertEquals(0, symlinkParentDirectory.list().length);
125127
assertEquals(0, realParent.list().length);
126128

@@ -155,6 +157,7 @@ void testCleanDirWithSymlinkFile() throws Exception {
155157

156158
// assert contents of the real directory were removed including the symlink
157159
FileUtils.cleanDirectory(realOuter);
160+
assertTrue(realOuter.exists());
158161
assertEquals(0, realOuter.list().length);
159162

160163
// ensure that the contents of the symlink were NOT removed.
@@ -256,6 +259,7 @@ void testStillClearsIfGivenDirectoryIsASymlink() throws Exception {
256259
assertTrue(setupSymlink(randomDirectory, symlinkDirectory));
257260

258261
FileUtils.cleanDirectory(symlinkDirectory);
262+
assertTrue(symlinkDirectory.exists());
259263
assertEquals(0, symlinkDirectory.list().length);
260264
assertEquals(0, randomDirectory.list().length);
261265
}

0 commit comments

Comments
 (0)