mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Valery Kharseko
yesterday e9e614a4644288148abe6cb6fae3112e25a86d2d
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/*
 * 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;
    }
}