/*
|
* The contents of this file are subject to the terms of the Common Development and
|
* Distribution License (the License). You may not use this file except in compliance with the
|
* License.
|
*
|
* You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
|
* specific language governing permission and limitations under the License.
|
*
|
* When distributing Covered Software, include this CDDL Header Notice in each file and include
|
* the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
|
* Header, with the fields enclosed by brackets [] replaced by your own identifying
|
* information: "Portions copyright [year] [name of copyright owner]".
|
*
|
* Copyright 2026 3A Systems, LLC.
|
*/
|
package com.forgerock.opendj.cli;
|
|
import static java.nio.charset.StandardCharsets.ISO_8859_1;
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
import static org.fest.assertions.Assertions.assertThat;
|
|
import java.io.File;
|
import java.nio.file.Files;
|
|
import org.forgerock.i18n.LocalizableMessage;
|
import org.testng.annotations.DataProvider;
|
import org.testng.annotations.Test;
|
|
/** Reading argument defaults from a {@code tools.properties} file. */
|
@SuppressWarnings("javadoc")
|
public final class ArgumentParserPropertiesFileTestCase extends CliTestCase {
|
|
/** Both ways a tool reads the file: through --propertiesFilePath and through an explicit path. */
|
@DataProvider
|
public Object[][] readers() {
|
return new Object[][] { { true }, { false } };
|
}
|
|
@Test(dataProvider = "readers")
|
public void testUtf8FileKeepsNonAsciiCharacters(boolean viaArgument) throws Exception {
|
final File file = write("basedn=ou=Jörg Ж,dc=example,dc=com\n".getBytes(UTF_8));
|
assertThat(baseDN(file, viaArgument)).isEqualTo("ou=Jörg Ж,dc=example,dc=com");
|
}
|
|
/** Some Windows editors start a UTF-8 file with a byte order mark. */
|
@Test(dataProvider = "readers")
|
public void testUtf8ByteOrderMarkIsSkipped(boolean viaArgument) throws Exception {
|
final File file = write("\uFEFFbasedn=dc=example,dc=com\n".getBytes(UTF_8));
|
assertThat(baseDN(file, viaArgument)).isEqualTo("dc=example,dc=com");
|
}
|
|
/** A file that starts as UTF-8 with a byte order mark but later gets a Latin-1 byte. */
|
@Test(dataProvider = "readers")
|
public void testByteOrderMarkIsSkippedInIso88591Fallback(boolean viaArgument) throws Exception {
|
final byte[] bom = { (byte) 0xEF, (byte) 0xBB, (byte) 0xBF };
|
final byte[] text = "basedn=dc=example,dc=com\nx=ö\n".getBytes(ISO_8859_1);
|
final byte[] content = new byte[bom.length + text.length];
|
System.arraycopy(bom, 0, content, 0, bom.length);
|
System.arraycopy(text, 0, content, bom.length, text.length);
|
assertThat(baseDN(write(content), viaArgument)).isEqualTo("dc=example,dc=com");
|
}
|
|
/** Files written for earlier releases, which read them as ISO-8859-1, keep working. */
|
@Test(dataProvider = "readers")
|
public void testIso88591FileIsStillAccepted(boolean viaArgument) throws Exception {
|
final File file = write("basedn=ou=Jörg,dc=example,dc=com\n".getBytes(ISO_8859_1));
|
assertThat(baseDN(file, viaArgument)).isEqualTo("ou=Jörg,dc=example,dc=com");
|
}
|
|
/** The file keeps the properties format: a backslash in a value must be doubled. */
|
@Test(dataProvider = "readers")
|
public void testDoubledBackslashIsOneBackslash(boolean viaArgument) throws Exception {
|
final File file = write("basedn=cn=a\\\\,b,dc=example,dc=com\n".getBytes(UTF_8));
|
assertThat(baseDN(file, viaArgument)).isEqualTo("cn=a\\,b,dc=example,dc=com");
|
}
|
|
private static String baseDN(File file, boolean viaArgument) throws Exception {
|
final ArgumentParser parser =
|
new ArgumentParser(ArgumentParserPropertiesFileTestCase.class.getName(),
|
LocalizableMessage.raw("test"), false);
|
final StringArgument baseDN = StringArgument.builder("baseDN")
|
.valuePlaceholder(LocalizableMessage.raw("{baseDN}"))
|
.description(LocalizableMessage.raw("base DN"))
|
.buildAndAddToParser(parser);
|
if (viaArgument) {
|
final StringArgument propertiesFile =
|
CommonArguments.propertiesFileArgument();
|
parser.addArgument(propertiesFile);
|
parser.setFilePropertiesArgument(propertiesFile);
|
parser.parseArguments(new String[] { "--" + propertiesFile.getLongIdentifier(), file.getPath() });
|
} else {
|
parser.parseArguments(new String[0], file.getPath(), true);
|
}
|
return baseDN.getValue();
|
}
|
|
private static File write(byte[] content) throws Exception {
|
final File file = File.createTempFile("tools", ".properties");
|
file.deleteOnExit();
|
Files.write(file.toPath(), content);
|
return file;
|
}
|
}
|