Skip to content

Commit 7629b20

Browse files
committed
Add Add org.apache.commons.io.Charsets.isAlias(Charset, String)
- Add org.apache.commons.io.Charsets.isUTF8(Charset) - Add org.apache.commons.io.Charsets.toCharsetDefault(String, Charset)
1 parent bb24f0e commit 7629b20

File tree

3 files changed

+115
-3
lines changed

3 files changed

+115
-3
lines changed

src/changes/changes.xml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,10 @@ The <action> type attribute can be add,update,fix,remove.
6767
<action dev="ggregory" type="fix" due-to="Gary Gregory">Fix SpotBugs [ERROR] Medium: Shared primitive variable "closed" in one thread may not yield the value of the most recent write from another thread [org.apache.commons.io.input.ProxyInputStream] At ProxyInputStream.java:[line 233] AT_STALE_THREAD_WRITE_OF_PRIMITIVE.</action>
6868
<action dev="ggregory" type="fix" due-to="Gary Gregory">Fix SpotBugs [ERROR] Medium: Shared primitive variable "propagateClose" in one thread may not yield the value of the most recent write from another thread [org.apache.commons.io.input.BoundedInputStream] At BoundedInputStream.java:[line 555] AT_STALE_THREAD_WRITE_OF_PRIMITIVE.</action>
6969
<!-- ADD -->
70-
<action dev="ggregory" type="add" issue="IO-875" due-to="Pierre Baumard, Gary Gregory">Add and use org.apache.commons.io.file.CountingPathVisitor.accept(Path, BasicFileAttributes) #743.</action>
70+
<action dev="ggregory" type="add" issue="IO-875" due-to="Pierre Baumard, Gary Gregory">Add and use org.apache.commons.io.file.CountingPathVisitor.accept(Path, BasicFileAttributes) #743.</action>
71+
<action dev="ggregory" type="add" due-to="Gary Gregory">Add org.apache.commons.io.Charsets.isAlias(Charset, String).</action>
72+
<action dev="ggregory" type="add" due-to="Gary Gregory">Add org.apache.commons.io.Charsets.isUTF8(Charset).</action>
73+
<action dev="ggregory" type="add" due-to="Gary Gregory">Add org.apache.commons.io.Charsets.toCharsetDefault(String, Charset).</action>
7174
<!-- UPDATE -->
7275
</release>
7376
<release version="2.19.0" date="2025-04-08" description="Version 2.19.0: Java 8 or later is required.">

src/main/java/org/apache/commons/io/Charsets.java

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,39 @@ public class Charsets {
156156
@Deprecated
157157
public static final Charset UTF_8 = StandardCharsets.UTF_8;
158158

159+
/**
160+
* Tests whether the given non-null Charset has an alias of the given name.
161+
*
162+
* @param charset a non-null Charset.
163+
* @param charsetName The name to test.
164+
* @return whether the given non-null charset name is a UTF-8 alias.
165+
* @since 2.20.0
166+
*/
167+
public static boolean isAlias(final Charset charset, final String charsetName) {
168+
return charsetName != null && (charset.name().equalsIgnoreCase(charsetName) || charset.aliases().stream().anyMatch(charsetName::equalsIgnoreCase));
169+
}
170+
171+
/**
172+
* Tests whether a given encoding is UTF-8. If the given charset is null, then check the platform's default encoding.
173+
*
174+
* @param charset If the given charset is null, then check the platform's default encoding.
175+
* @return whether a given encoding is UTF-8.
176+
* @since 2.20.0
177+
*/
178+
public static boolean isUTF8(final Charset charset) {
179+
return isUTF8Alias(toCharset(charset).name());
180+
}
181+
182+
/**
183+
* Tests whether the given non-null charset name is a UTF-8 alias.
184+
*
185+
* @param charsetName a non-null charset name.
186+
* @return whether the given non-null charset name is a UTF-8 alias.
187+
*/
188+
private static boolean isUTF8Alias(final String charsetName) {
189+
return isAlias(StandardCharsets.UTF_8, charsetName);
190+
}
191+
159192
/**
160193
* Constructs a sorted map from canonical charset names to charset objects required of every implementation of the
161194
* Java platform.
@@ -212,7 +245,7 @@ public static Charset toCharset(final String charsetName) throws UnsupportedChar
212245
* Returns a Charset for the named charset. If the name is null, return the given default Charset.
213246
*
214247
* @param charsetName The name of the requested charset, may be null.
215-
* @param defaultCharset The name charset to return if charsetName is null, may be null.
248+
* @param defaultCharset The charset to return if charsetName is null, may be null.
216249
* @return a Charset for the named charset.
217250
* @throws UnsupportedCharsetException If the named charset is unavailable (unchecked exception).
218251
* @since 2.12.0
@@ -221,6 +254,26 @@ public static Charset toCharset(final String charsetName, final Charset defaultC
221254
return charsetName == null ? defaultCharset : Charset.forName(charsetName);
222255
}
223256

257+
/**
258+
* Returns a Charset for the named charset or the {@code defaultCharset}.
259+
* <p>
260+
* If {@code charsetName} cannot load a charset, return {@code defaultCharset}. Therefore, this method should never fail and always return a Charset.
261+
* </p>
262+
*
263+
* @param charsetName The name of the requested charset, may be null.
264+
* @param defaultCharset The charset to return if charsetName is null or there is a problem, may be null which returns {@link Charset#defaultCharset()}.
265+
* @return a Charset for the named charset or {@code defaultCharset} if any errors occur.
266+
* @see Charset#defaultCharset()
267+
* @since 2.20.0
268+
*/
269+
public static Charset toCharsetDefault(final String charsetName, final Charset defaultCharset) {
270+
try {
271+
return toCharset(charsetName);
272+
} catch (final RuntimeException ignored) {
273+
return toCharset(defaultCharset);
274+
}
275+
}
276+
224277
/**
225278
* Construct a new instance.
226279
*

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

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,23 @@
1818
package org.apache.commons.io;
1919

2020
import static org.junit.jupiter.api.Assertions.assertEquals;
21+
import static org.junit.jupiter.api.Assertions.assertFalse;
2122
import static org.junit.jupiter.api.Assertions.assertNull;
23+
import static org.junit.jupiter.api.Assertions.assertTrue;
24+
import static org.junit.jupiter.api.Assumptions.assumeFalse;
2225

2326
import java.nio.charset.Charset;
2427
import java.nio.charset.StandardCharsets;
28+
import java.util.Collection;
2529
import java.util.Set;
2630
import java.util.SortedMap;
31+
import java.util.stream.Stream;
2732

33+
import org.apache.commons.lang3.StringUtils;
2834
import org.junit.jupiter.api.Test;
35+
import org.junit.jupiter.params.ParameterizedTest;
36+
import org.junit.jupiter.params.provider.Arguments;
37+
import org.junit.jupiter.params.provider.MethodSource;
2938

3039
/**
3140
* Tests {@link Charsets}.
@@ -51,6 +60,20 @@ public static Set<String> availableCharsetsKeySet() {
5160
return Charset.availableCharsets().keySet();
5261
}
5362

63+
/**
64+
* For parameterized tests.
65+
*
66+
* @return {@code Charset.availableCharsets().values()}.
67+
*/
68+
public static Collection<Charset> availableCharsetsValues() {
69+
return Charset.availableCharsets().values();
70+
}
71+
72+
static Stream<Arguments> charsetAliasProvider() {
73+
return Charset.availableCharsets().entrySet().stream()
74+
.flatMap(entry -> entry.getValue().aliases().stream().map(a -> Arguments.of(entry.getValue(), a)));
75+
}
76+
5477
/**
5578
* For parameterized tests.
5679
*
@@ -60,11 +83,33 @@ public static Set<String> getRequiredCharsetNames() {
6083
return Charsets.requiredCharsets().keySet();
6184
}
6285

86+
@ParameterizedTest
87+
@MethodSource("charsetAliasProvider")
88+
public void testIsAlias(final Charset charset, final String charsetAlias) {
89+
assertTrue(Charsets.isAlias(charset, charsetAlias));
90+
assertTrue(Charsets.isAlias(charset, charsetAlias.toLowerCase()));
91+
assertTrue(Charsets.isAlias(charset, charsetAlias.toUpperCase()));
92+
assertTrue(Charsets.isAlias(charset, charset.name()));
93+
assertFalse(Charsets.isAlias(charset, null));
94+
}
95+
6396
@Test
6497
public void testIso8859_1() {
6598
assertEquals("ISO-8859-1", Charsets.ISO_8859_1.name());
6699
}
67100

101+
@ParameterizedTest
102+
@MethodSource("availableCharsetsValues")
103+
public void testIsUTF8Charset(final Charset charset) {
104+
assumeFalse(StandardCharsets.UTF_8.equals(charset));
105+
charset.aliases().forEach(n -> assertFalse(Charsets.isUTF8(Charset.forName(n))));
106+
}
107+
108+
public void testIsUTF8CharsetUTF8() {
109+
assertTrue(Charsets.isUTF8(StandardCharsets.UTF_8));
110+
StandardCharsets.UTF_8.aliases().forEach(n -> assertTrue(Charsets.isUTF8(Charset.forName(n))));
111+
}
112+
68113
@Test
69114
public void testRequiredCharsets() {
70115
final SortedMap<String, Charset> requiredCharsets = Charsets.requiredCharsets();
@@ -87,7 +132,18 @@ public void testToCharset_String() {
87132
}
88133

89134
@Test
90-
public void testToCharset_String_Charset() {
135+
public void testToCharsetDefault() {
136+
assertEquals(StandardCharsets.UTF_8, Charsets.toCharsetDefault((String) null, null));
137+
assertEquals(StandardCharsets.UTF_8, Charsets.toCharsetDefault(StringUtils.EMPTY, null));
138+
assertEquals(StandardCharsets.UTF_8, Charsets.toCharsetDefault(".", null));
139+
assertEquals(Charset.defaultCharset(), Charsets.toCharsetDefault(null, Charset.defaultCharset()));
140+
assertEquals(Charset.defaultCharset(), Charsets.toCharsetDefault(Charset.defaultCharset().name(), Charset.defaultCharset()));
141+
assertEquals(StandardCharsets.UTF_8, Charsets.toCharsetDefault(StandardCharsets.UTF_8.name(), Charset.defaultCharset()));
142+
assertEquals(StandardCharsets.UTF_8, Charsets.toCharsetDefault(StandardCharsets.UTF_8.name(), null));
143+
}
144+
145+
@Test
146+
public void testToCharsetWithStringCharset() {
91147
assertNull(Charsets.toCharset((String) null, null));
92148
assertEquals(Charset.defaultCharset(), Charsets.toCharset((String) null, Charset.defaultCharset()));
93149
assertEquals(Charset.defaultCharset(), Charsets.toCharset((Charset) null, Charset.defaultCharset()));

0 commit comments

Comments
 (0)