diff --git a/opendj-config/src/main/java/org/forgerock/opendj/config/dsconfig/BuildVersion.java b/opendj-config/src/main/java/org/forgerock/opendj/config/dsconfig/BuildVersion.java index 7f33935fea..8dcd3e4024 100644 --- a/opendj-config/src/main/java/org/forgerock/opendj/config/dsconfig/BuildVersion.java +++ b/opendj-config/src/main/java/org/forgerock/opendj/config/dsconfig/BuildVersion.java @@ -13,6 +13,7 @@ * * Copyright 2008 Sun Microsystems, Inc. * Portions Copyright 2013-2016 ForgeRock AS. + * Portions Copyright 2026 3A Systems, LLC. */ package org.forgerock.opendj.config.dsconfig; @@ -191,11 +192,8 @@ public int compareTo(final BuildVersion version) { if (major == version.major) { if (minor == version.minor) { if (point == version.point) { - if (rev == version.rev) { - return 0; - } else if (rev.compareTo(version.rev) < 0) { - return -1; - } + // Compares the revisions as strings: they are VCS revisions, not numbers. + return Integer.signum(rev.compareTo(version.rev)); } else if (point < version.point) { return -1; } diff --git a/opendj-config/src/test/java/org/forgerock/opendj/config/dsconfig/BuildVersionTest.java b/opendj-config/src/test/java/org/forgerock/opendj/config/dsconfig/BuildVersionTest.java new file mode 100644 index 0000000000..305fd68f56 --- /dev/null +++ b/opendj-config/src/test/java/org/forgerock/opendj/config/dsconfig/BuildVersionTest.java @@ -0,0 +1,46 @@ +/* + * 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 org.forgerock.opendj.config.dsconfig; + +import org.forgerock.testng.ForgeRockTestCase; +import org.testng.Assert; +import org.testng.annotations.Test; + +@Test(groups = { "precommit", "config" }) +public class BuildVersionTest extends ForgeRockTestCase { + + @Test + public void testEqualRevisionsCompareEqual() { + // Two distinct String instances holding the same revision: the revisions must be compared + // by value, not by reference. + final String rev = "abcdef"; + final String sameRev = new StringBuilder(rev).toString(); + Assert.assertEquals(new BuildVersion(4, 0, 0, rev).compareTo(new BuildVersion(4, 0, 0, sameRev)), 0); + } + + @Test + public void testRevisionsOrderVersionsWhichAreOtherwiseEqual() { + Assert.assertEquals(new BuildVersion(4, 0, 0, "aaa").compareTo(new BuildVersion(4, 0, 0, "bbb")), -1); + Assert.assertEquals(new BuildVersion(4, 0, 0, "bbb").compareTo(new BuildVersion(4, 0, 0, "aaa")), 1); + } + + @Test + public void testVersionNumbersTakePrecedenceOverRevisions() { + Assert.assertEquals(new BuildVersion(3, 9, 9, "zzz").compareTo(new BuildVersion(4, 0, 0, "aaa")), -1); + Assert.assertEquals(new BuildVersion(4, 1, 0, "aaa").compareTo(new BuildVersion(4, 0, 9, "zzz")), 1); + Assert.assertEquals(new BuildVersion(4, 0, 1, "aaa").compareTo(new BuildVersion(4, 0, 0, "zzz")), 1); + } +} diff --git a/opendj-core/src/main/java/com/forgerock/opendj/util/ASCIICharProp.java b/opendj-core/src/main/java/com/forgerock/opendj/util/ASCIICharProp.java index fc8816b64c..86ee0abe15 100644 --- a/opendj-core/src/main/java/com/forgerock/opendj/util/ASCIICharProp.java +++ b/opendj-core/src/main/java/com/forgerock/opendj/util/ASCIICharProp.java @@ -13,6 +13,7 @@ * * Copyright 2009 Sun Microsystems, Inc. * Portions copyright 2011-2016 ForgeRock AS. + * Portions Copyright 2026 3A Systems, LLC. */ package com.forgerock.opendj.util; @@ -110,7 +111,7 @@ private ASCIICharProp(final char c) { this.isKeyChar = true; this.isCompatKeyChar = true; this.decimalValue = -1; - if (c >= 'a' && c <= 'f') { + if (c <= 'f') { this.isHexChar = true; this.hexValue = c - 87; } else { @@ -127,7 +128,7 @@ private ASCIICharProp(final char c) { this.isKeyChar = true; this.isCompatKeyChar = true; this.decimalValue = -1; - if (c >= 'A' && c <= 'F') { + if (c <= 'F') { this.isHexChar = true; this.hexValue = c - 55; } else { diff --git a/opendj-core/src/main/java/com/forgerock/opendj/util/StringPrepProfile.java b/opendj-core/src/main/java/com/forgerock/opendj/util/StringPrepProfile.java index 7d2c291553..2ba8f1ca5c 100644 --- a/opendj-core/src/main/java/com/forgerock/opendj/util/StringPrepProfile.java +++ b/opendj-core/src/main/java/com/forgerock/opendj/util/StringPrepProfile.java @@ -13,6 +13,7 @@ * * Copyright 2010 Sun Microsystems, Inc. * Portions Copyright 2015 ForgeRock AS. + * Portions Copyright 2026 3A Systems, LLC. */ package com.forgerock.opendj.util; @@ -462,7 +463,7 @@ public static void prepareUnicode(final StringBuilder buffer, final ByteSequence if (canMapToSpace(buffer, trim)) { buffer.append(SPACE_CHAR); } - } else if ((b >= '\u0000' && b <= '\u0008') || (b >= '\u000E' && b <= '\u001F') + } else if (b <= '\u0008' || (b >= '\u000E' && b <= '\u001F') || b == '\u007F') { // These characters are mapped to nothing and hence not // copied over.. diff --git a/opendj-core/src/main/java/org/forgerock/opendj/ldap/AVA.java b/opendj-core/src/main/java/org/forgerock/opendj/ldap/AVA.java index 14ddecb1d7..7d8774c51a 100644 --- a/opendj-core/src/main/java/org/forgerock/opendj/ldap/AVA.java +++ b/opendj-core/src/main/java/org/forgerock/opendj/ldap/AVA.java @@ -166,9 +166,10 @@ static void escapeAttributeValue(final String str, final StringBuilder builder) builder.append(StaticUtils.byteToLowerHex(b)); } } else { + // NUL needs no test here: it is already handled by the c < ' ' branch above. if ((c == ' ' && si == length - 1) || (c == '"' || c == '+' || c == ',' || c == ';' || c == '<' - || c == '>' || c == '\\' || c == '\u0000' || c == '=')) { + || c == '>' || c == '\\' || c == '=')) { builder.append('\\'); } builder.append(c); diff --git a/opendj-core/src/main/java/org/forgerock/opendj/ldap/AttributeFilter.java b/opendj-core/src/main/java/org/forgerock/opendj/ldap/AttributeFilter.java index c207ed8468..345e9128e5 100644 --- a/opendj-core/src/main/java/org/forgerock/opendj/ldap/AttributeFilter.java +++ b/opendj-core/src/main/java/org/forgerock/opendj/ldap/AttributeFilter.java @@ -12,6 +12,7 @@ * information: "Portions Copyright [year] [name of copyright owner]". * * Copyright 2013-2016 ForgeRock AS. + * Portions Copyright 2026 3A Systems, LLC. */ package org.forgerock.opendj.ldap; @@ -163,13 +164,19 @@ public Iterable getAllAttributes() { * requested by the user. */ return new Iterable() { - private boolean hasNextMustIterate = true; - private final Iterator iterator = entry.getAllAttributes().iterator(); - private Attribute next = null; - @Override public Iterator iterator() { + /* + * The iteration state belongs to the iterator, not to this Iterable: + * keeping it here is what allows the Iterable to be iterated more than + * once, including by the toString() below. + */ return new Iterator() { + private boolean hasNextMustIterate = true; + private final Iterator iterator = + entry.getAllAttributes().iterator(); + private Attribute next; + @Override public boolean hasNext() { if (hasNextMustIterate) { diff --git a/opendj-core/src/main/java/org/forgerock/opendj/ldap/GeneralizedTime.java b/opendj-core/src/main/java/org/forgerock/opendj/ldap/GeneralizedTime.java index d58dbcfc91..ac11537e25 100644 --- a/opendj-core/src/main/java/org/forgerock/opendj/ldap/GeneralizedTime.java +++ b/opendj-core/src/main/java/org/forgerock/opendj/ldap/GeneralizedTime.java @@ -836,9 +836,9 @@ private GeneralizedTime(final Calendar calendar, final Date date, final long tim @Override public int compareTo(final GeneralizedTime o) { - final Long timeMS1 = getTimeInMillis(); - final Long timeMS2 = o.getTimeInMillis(); - return timeMS1.compareTo(timeMS2); + final long timeMS1 = getTimeInMillis(); + final long timeMS2 = o.getTimeInMillis(); + return Long.compare(timeMS1, timeMS2); } @Override diff --git a/opendj-core/src/main/java/org/forgerock/opendj/ldap/InetAddressValidator.java b/opendj-core/src/main/java/org/forgerock/opendj/ldap/InetAddressValidator.java index ab2c845e63..ef2cd7ed2b 100644 --- a/opendj-core/src/main/java/org/forgerock/opendj/ldap/InetAddressValidator.java +++ b/opendj-core/src/main/java/org/forgerock/opendj/ldap/InetAddressValidator.java @@ -12,6 +12,7 @@ * information: "Portions Copyright [year] [name of copyright owner]". * * Portions copyright 2016 ForgeRock AS. + * Portions Copyright 2026 3A Systems, LLC. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -184,7 +185,7 @@ public static boolean isValidInet6Address(String inet6Address) { if (!inet6Address.endsWith(octet)) { return false; } - if (index > octets.length - 1 || index > 6) { // CHECKSTYLE IGNORE MagicNumber + if (index > 6) { // CHECKSTYLE IGNORE MagicNumber // IPV4 occupies last two octets return false; } diff --git a/opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/PasswordPolicyResponseControl.java b/opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/PasswordPolicyResponseControl.java index 13e3d2fd8f..be39394f45 100644 --- a/opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/PasswordPolicyResponseControl.java +++ b/opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/PasswordPolicyResponseControl.java @@ -138,8 +138,7 @@ public PasswordPolicyResponseControl decodeControl(final Control control, // nested element. reader.readStartSequence(); final int warningChoiceValue = (0x7F & reader.peekType()); - if (warningChoiceValue < 0 - || warningChoiceValue >= PasswordPolicyWarningType.values().length) { + if (warningChoiceValue >= PasswordPolicyWarningType.values().length) { final LocalizableMessage message = ERR_PWPOLICYRES_INVALID_WARNING_TYPE.get(byteToHex(reader .peekType())); diff --git a/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/NameForm.java b/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/NameForm.java index 214bb0ca6d..2e651a4c53 100644 --- a/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/NameForm.java +++ b/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/NameForm.java @@ -12,6 +12,7 @@ * information: "Portions Copyright [year] [name of copyright owner]". * * Copyright 2009 Sun Microsystems, Inc. + * Portions Copyright 2026 3A Systems, LLC. * Portions copyright 2011-2016 ForgeRock AS. */ package org.forgerock.opendj.ldap.schema; @@ -334,7 +335,7 @@ private NameForm(final Builder builder) { if (builder.structuralObjectClassOID == null || builder.structuralObjectClassOID.isEmpty()) { throw new IllegalArgumentException("A structural class OID must be specified."); } - if (builder.requiredAttributes == null || builder.requiredAttributes.isEmpty()) { + if (builder.requiredAttributes.isEmpty()) { throw new IllegalArgumentException("Required attribute must be specified."); } diff --git a/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SchemaUtils.java b/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SchemaUtils.java index 5195e65be6..cb6bb24c7c 100644 --- a/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SchemaUtils.java +++ b/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SchemaUtils.java @@ -13,7 +13,7 @@ * * Copyright 2009 Sun Microsystems, Inc. * Portions copyright 2011-2016 ForgeRock AS. - * Portions Copyright 2024 3A Systems, LLC. + * Portions Copyright 2024-2026 3A Systems, LLC. */ package org.forgerock.opendj.ldap.schema; @@ -229,11 +229,8 @@ static String readOID(final SubstringReader reader, final boolean allowCompatCha && (c = reader.read()) != ' ' && c != ')' && (c != '\'' || !enclosingQuote)) { - if (length == 0 && !isAlpha(c)) { - throw DecodeException.error( - ERR_ATTR_SYNTAX_ILLEGAL_CHAR_IN_STRING_OID1.get(c, reader.pos() - 1)); - } - + // The first character was already required to be alphabetic by the enclosing + // test, so only the key-character check is needed here. if (!isKeyChar(c, allowCompatChars)) { throw DecodeException.error( ERR_ATTR_SYNTAX_ILLEGAL_CHAR_IN_STRING_OID1.get(c, reader.pos() - 1)); @@ -326,11 +323,6 @@ static String readOIDLen(final SubstringReader reader, final boolean allowCompat } length++; } - - if (length == 0) { - throw DecodeException.error( - ERR_ATTR_SYNTAX_OID_NO_VALUE1.get(reader.pos() - 1)); - } } else if (isAlpha(c)) { // This must be an attribute description. In this case, we will // only accept alphabetic characters, numeric digits, and the hyphen. @@ -338,11 +330,8 @@ static String readOIDLen(final SubstringReader reader, final boolean allowCompat && c != ')' && c != '{' && (c != '\'' || !enclosingQuote)) { - if (length == 0 && !isAlpha(c)) { - throw DecodeException.error( - ERR_ATTR_SYNTAX_ILLEGAL_CHAR_IN_STRING_OID1.get(c, reader.pos() - 1)); - } - + // The first character was already required to be alphabetic by the enclosing + // test, so only the key-character check is needed here. if (!isKeyChar(c, allowCompatChars)) { throw DecodeException.error( ERR_ATTR_SYNTAX_ILLEGAL_CHAR_IN_STRING_OID1.get(c, reader.pos() - 1)); diff --git a/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UTCTimeSyntaxImpl.java b/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UTCTimeSyntaxImpl.java index 321e4cb72f..a19944618e 100644 --- a/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UTCTimeSyntaxImpl.java +++ b/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UTCTimeSyntaxImpl.java @@ -12,6 +12,7 @@ * information: "Portions Copyright [year] [name of copyright owner]". * * Copyright 2009 Sun Microsystems, Inc. + * Portions Copyright 2026 3A Systems, LLC. * Portions copyright 2012-2016 ForgeRock AS. */ package org.forgerock.opendj.ldap.schema; @@ -399,16 +400,8 @@ public boolean valueIsAcceptable(final Schema schema, final ByteSequence value, case '3': case '4': case '5': - // There must be at least two more characters, and the next one - // must be a digit between 0 and 9. - if (length < 11) { - final LocalizableMessage message = - ERR_ATTR_SYNTAX_UTC_TIME_INVALID_CHAR.get(valueString, String.valueOf(m1), - 8); - invalidReason.append(message); - return false; - } - + // A length below 11 was already rejected at the top of this method, so the next + // character is present and must be a digit between 0 and 9. switch (valueString.charAt(9)) { case '0': case '1': diff --git a/opendj-core/src/main/java/org/forgerock/opendj/ldif/TemplateTag.java b/opendj-core/src/main/java/org/forgerock/opendj/ldif/TemplateTag.java index dfcabc926b..3df49c28b1 100644 --- a/opendj-core/src/main/java/org/forgerock/opendj/ldif/TemplateTag.java +++ b/opendj-core/src/main/java/org/forgerock/opendj/ldif/TemplateTag.java @@ -13,6 +13,7 @@ * * Copyright 2006-2009 Sun Microsystems, Inc. * Portions Copyright 2013-2015 ForgeRock AS. + * Portions Copyright 2026 3A Systems, LLC. */ package org.forgerock.opendj.ldif; @@ -1322,7 +1323,7 @@ void initializeForTemplate(Schema schema, TemplateFile templateFile, Template te } private void initialize(String[] arguments, int lineNumber) throws DecodeException { - if (arguments.length < 0 || arguments.length > 2) { + if (arguments.length > 2) { throw DecodeException.fatalError(ERR_ENTRY_GENERATOR_TAG_INVALID_ARGUMENT_RANGE_COUNT.get( getName(), lineNumber, 0, 2, arguments.length)); } diff --git a/opendj-core/src/test/java/org/forgerock/opendj/ldap/AttributeFilterTestCase.java b/opendj-core/src/test/java/org/forgerock/opendj/ldap/AttributeFilterTestCase.java new file mode 100644 index 0000000000..13f05b4937 --- /dev/null +++ b/opendj-core/src/test/java/org/forgerock/opendj/ldap/AttributeFilterTestCase.java @@ -0,0 +1,63 @@ +/* + * 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 org.forgerock.opendj.ldap; + +import static org.fest.assertions.Assertions.assertThat; + +import java.util.ArrayList; +import java.util.List; + +import org.testng.annotations.Test; + +/** + * Test {@code AttributeFilter}. + */ +@SuppressWarnings("javadoc") +public final class AttributeFilterTestCase extends SdkTestCase { + + @Test + public void testFilteredViewCanBeIteratedMoreThanOnce() { + final Iterable attributes = filteredView().getAllAttributes(); + + final List firstPass = namesOf(attributes); + assertThat(firstPass).isNotEmpty(); + assertThat(namesOf(attributes)).isEqualTo(firstPass); + } + + @Test + public void testFilteredViewCanBeIteratedAfterToString() { + final Iterable attributes = filteredView().getAllAttributes(); + + final List expected = namesOf(attributes); + attributes.toString(); + assertThat(namesOf(attributes)).isEqualTo(expected); + } + + private Entry filteredView() { + final Entry entry = + new LinkedHashMapEntry("dn: cn=test", "objectClass: top", "objectClass: person", + "cn: test", "sn: user"); + return new AttributeFilter().filteredViewOf(entry); + } + + private List namesOf(final Iterable attributes) { + final List names = new ArrayList<>(); + for (final Attribute attribute : attributes) { + names.add(attribute.getAttributeDescriptionAsString()); + } + return names; + } +} diff --git a/opendj-doc-maven-plugin/src/main/java/org/forgerock/opendj/maven/doc/GenerateConfigurationReferenceMojo.java b/opendj-doc-maven-plugin/src/main/java/org/forgerock/opendj/maven/doc/GenerateConfigurationReferenceMojo.java index 5618a9fc85..94311a9924 100644 --- a/opendj-doc-maven-plugin/src/main/java/org/forgerock/opendj/maven/doc/GenerateConfigurationReferenceMojo.java +++ b/opendj-doc-maven-plugin/src/main/java/org/forgerock/opendj/maven/doc/GenerateConfigurationReferenceMojo.java @@ -12,6 +12,7 @@ * information: "Portions Copyright [year] [name of copyright owner]". * * Copyright 2015-2016 ForgeRock AS. + * Portions Copyright 2026 3A Systems, LLC. */ package org.forgerock.opendj.maven.doc; @@ -151,7 +152,7 @@ private void generateConfigRef() throws MojoExecutionException { */ private void copyResources() throws IOException { for (String file : resourceFiles) { - InputStream original = this.getClass().getResourceAsStream("/config-ref/" + file); + InputStream original = GenerateConfigurationReferenceMojo.class.getResourceAsStream("/config-ref/" + file); File copy = new File(outputDirectory, file); copyInputStreamToFile(original, copy); } diff --git a/opendj-dsml-servlet/src/main/java/org/opends/dsml/protocol/DSMLServlet.java b/opendj-dsml-servlet/src/main/java/org/opends/dsml/protocol/DSMLServlet.java index 3b2d725bb7..46630f4354 100644 --- a/opendj-dsml-servlet/src/main/java/org/opends/dsml/protocol/DSMLServlet.java +++ b/opendj-dsml-servlet/src/main/java/org/opends/dsml/protocol/DSMLServlet.java @@ -234,7 +234,7 @@ public void init(ServletConfig config) throws ServletException { // assign the DSMLv2 schema for validation if(schema==null) { - URL url = getClass().getResource("/resources/DSMLv2.xsd"); + URL url = DSMLServlet.class.getResource("/resources/DSMLv2.xsd"); if ( url != null ) { SchemaFactory sf = SchemaFactory.newInstance(W3C_XML_SCHEMA_NS_URI); schema = sf.newSchema(url); diff --git a/opendj-maven-plugin/src/main/java/org/forgerock/opendj/maven/GenerateConfigMojo.java b/opendj-maven-plugin/src/main/java/org/forgerock/opendj/maven/GenerateConfigMojo.java index 6ab98dcc3a..94f87ec155 100644 --- a/opendj-maven-plugin/src/main/java/org/forgerock/opendj/maven/GenerateConfigMojo.java +++ b/opendj-maven-plugin/src/main/java/org/forgerock/opendj/maven/GenerateConfigMojo.java @@ -184,7 +184,7 @@ public void execute() throws MojoExecutionException { } else if (!isXMLPackageDirectoryValid()) { throw new MojoExecutionException("The XML definition directory \"" + getXMLPackageDirectory() + "\" does not exist."); - } else if (getClass().getResource(getStylesheetDirectory()) == null) { + } else if (GenerateConfigMojo.class.getResource(getStylesheetDirectory()) == null) { throw new MojoExecutionException("The XSLT stylesheet directory \"" + getStylesheetDirectory() + "\" does not exist."); } @@ -439,7 +439,7 @@ private boolean isXMLPackageDirectoryValid() { private Templates loadStylesheet(final String stylesheet) throws TransformerConfigurationException { final Source xslt = - new StreamSource(getClass().getResourceAsStream( + new StreamSource(GenerateConfigMojo.class.getResourceAsStream( getStylesheetDirectory() + "/" + stylesheet)); return stylesheetFactory.newTemplates(xslt); } diff --git a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Rest2LdapHttpApplication.java b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Rest2LdapHttpApplication.java index c70ec3247e..1cacf95405 100644 --- a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Rest2LdapHttpApplication.java +++ b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Rest2LdapHttpApplication.java @@ -13,6 +13,7 @@ * * Copyright 2015-2016 ForgeRock AS. * Portions Copyright 2017 Rosie Applications, Inc. + * Portions Copyright 2026 3A Systems, LLC. */ package org.forgerock.opendj.rest2ldap; @@ -176,10 +177,10 @@ private static String listValues() { public Rest2LdapHttpApplication() { try { // The null check is required for unit test mocks because the resource does not exist. - final URL configUrl = getClass().getResource("/config.json"); + final URL configUrl = Rest2LdapHttpApplication.class.getResource("/config.json"); this.configDirectory = configUrl != null ? new File(configUrl.toURI()).getParentFile() : null; } catch (final URISyntaxException e) { - throw new IllegalStateException(""+getClass().getResource("/config.json"),e); + throw new IllegalStateException("" + Rest2LdapHttpApplication.class.getResource("/config.json"), e); } this.schema = Schema.getDefaultSchema(); } diff --git a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/schema/JsonQueryEqualityMatchingRuleImpl.java b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/schema/JsonQueryEqualityMatchingRuleImpl.java index 8e64239085..ee3600ce80 100644 --- a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/schema/JsonQueryEqualityMatchingRuleImpl.java +++ b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/schema/JsonQueryEqualityMatchingRuleImpl.java @@ -12,6 +12,7 @@ * information: "Portions copyright [year] [name of copyright owner]". * * Copyright 2016 ForgeRock AS. + * Portions Copyright 2026 3A Systems, LLC. */ package org.forgerock.opendj.rest2ldap.schema; @@ -430,7 +431,7 @@ private ByteSequence createIndexKey(final ByteString fieldKey, final Object valu if (value == null) { return createNullIndexKey(builder); } else if (value instanceof Number) { - final Double doubleValue = ((Number) value).doubleValue(); + final double doubleValue = ((Number) value).doubleValue(); return createNumberIndexKey(builder, BigDecimal.valueOf(doubleValue)); } else if (value instanceof Boolean) { final Boolean booleanValue = (Boolean) value; diff --git a/opendj-server-legacy/replace.rb b/opendj-server-legacy/replace.rb index a4b73e3339..8697a14ced 100755 --- a/opendj-server-legacy/replace.rb +++ b/opendj-server-legacy/replace.rb @@ -1,4 +1,7 @@ #!/usr/bin/env ruby +# +# Portions Copyright 2026 3A Systems, LLC. +# require 'fileutils' @@ -471,7 +474,6 @@ def replace_file(file, replacements) (0..replacements.size-1).step(2).each { |index| pattern, replace = replacements[index], replacements[index+1] replace = replace.gsub('{CLASSNAME}', classname(file)) - is_replaced = true #while is_replaced #puts "pattern: " + pattern.to_s is_replaced = contents.gsub!(pattern, replace) diff --git a/opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/GenericDialog.java b/opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/GenericDialog.java index e81c9954f9..f0dec5fb2d 100644 --- a/opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/GenericDialog.java +++ b/opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/GenericDialog.java @@ -13,6 +13,7 @@ * * Copyright 2008-2009 Sun Microsystems, Inc. * Portions Copyright 2014-2016 ForgeRock AS. + * Portions Copyright 2026 3A Systems, LLC. */ package org.opends.guitools.controlpanel.ui; @@ -200,10 +201,6 @@ public void setVisible(boolean visible) } if (visible && lastComponentWithFocus != null && lastComponentWithFocus.isVisible()) { - if (lastComponentWithFocus == null) - { - lastComponentWithFocus = panel.getPreferredFocusComponent(); - } lastComponentWithFocus.requestFocusInWindow(); } updateDefaultButton(panel); diff --git a/opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/util/Utilities.java b/opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/util/Utilities.java index 68fb0d6fcb..42a77c7a0f 100644 --- a/opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/util/Utilities.java +++ b/opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/util/Utilities.java @@ -13,6 +13,7 @@ * * Copyright 2008-2010 Sun Microsystems, Inc. * Portions Copyright 2011-2016 ForgeRock AS. + * Portions Copyright 2026 3A Systems, LLC. */ package org.opends.guitools.controlpanel.util; @@ -2411,7 +2412,7 @@ else if (attr.isNumericDate()) { return NO_VALUE_SET.toString(); } - Long l = Long.parseLong(monitoringValue); + long l = Long.parseLong(monitoringValue); Date date = new Date(l); return ConfigFromConnection.formatter.format(date); } @@ -2437,7 +2438,7 @@ else if (attr.isGMTDate()) } else if (attr.isValueInBytes()) { - Long l = Long.parseLong(monitoringValue); + long l = Long.parseLong(monitoringValue); long mb = l / (1024 * 1024); long kbs = (l - mb * 1024 * 1024) / 1024; return INFO_CTRL_PANEL_MEMORY_VALUE.get(mb, kbs).toString(); diff --git a/opendj-server-legacy/src/main/java/org/opends/quicksetup/installer/Installer.java b/opendj-server-legacy/src/main/java/org/opends/quicksetup/installer/Installer.java index b70df04eca..d6f7de187f 100644 --- a/opendj-server-legacy/src/main/java/org/opends/quicksetup/installer/Installer.java +++ b/opendj-server-legacy/src/main/java/org/opends/quicksetup/installer/Installer.java @@ -13,6 +13,7 @@ * * Copyright 2006-2010 Sun Microsystems, Inc. * Portions Copyright 2011-2016 ForgeRock AS. + * Portions Copyright 2026 3A Systems, LLC. */ package org.opends.quicksetup.installer; @@ -591,7 +592,7 @@ private void initMaps() int cumulatedTime = 0; for (InstallProgressStep s : steps) { - Integer statusTime = s.getRelativeDuration(); + int statusTime = s.getRelativeDuration(); hmRatio.put(s, (100 * cumulatedTime) / totalTime); cumulatedTime += statusTime; } @@ -2676,7 +2677,7 @@ else if (isSchema) { throw new ApplicationException(ReturnCode.APPLICATION_ERROR, pnfe.getMessageObject(), null); } - StaticUtils.sleep((5 - nTries) * 3000); + StaticUtils.sleep((5 - nTries) * 3000L); } nTries--; } diff --git a/opendj-server-legacy/src/main/java/org/opends/server/authorization/dseecompat/BindRule.java b/opendj-server-legacy/src/main/java/org/opends/server/authorization/dseecompat/BindRule.java index 96bbef501c..245c133c3f 100644 --- a/opendj-server-legacy/src/main/java/org/opends/server/authorization/dseecompat/BindRule.java +++ b/opendj-server-legacy/src/main/java/org/opends/server/authorization/dseecompat/BindRule.java @@ -525,11 +525,9 @@ public String toString() { * should be appended. */ public final void toString(StringBuilder buffer) { - if (this.keywordRuleMap != null) { - for (KeywordBindRule rule : this.keywordRuleMap.values()) { - rule.toString(buffer); - buffer.append(";"); - } + for (KeywordBindRule rule : this.keywordRuleMap.values()) { + rule.toString(buffer); + buffer.append(";"); } } } diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/LDIFBackend.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/LDIFBackend.java index 2d7ad26dec..bbcded9b1e 100644 --- a/opendj-server-legacy/src/main/java/org/opends/server/backends/LDIFBackend.java +++ b/opendj-server-legacy/src/main/java/org/opends/server/backends/LDIFBackend.java @@ -13,6 +13,7 @@ * * Copyright 2007-2008 Sun Microsystems, Inc. * Portions Copyright 2011-2016 ForgeRock AS. + * Portions Copyright 2026 3A Systems, LLC. */ package org.opends.server.backends; @@ -366,12 +367,7 @@ public long getEntryCount() try { - if (entryMap != null) - { - return entryMap.size(); - } - - return -1; + return entryMap.size(); } finally { diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/RootContainer.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/RootContainer.java index e2fe9afb34..1adc22a057 100644 --- a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/RootContainer.java +++ b/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/RootContainer.java @@ -13,6 +13,7 @@ * * Copyright 2006-2010 Sun Microsystems, Inc. * Portions Copyright 2011-2016 ForgeRock AS. + * Portions Copyright 2026 3A Systems, LLC. */ package org.opends.server.backends.pluggable; @@ -229,7 +230,8 @@ private void openAndRegisterEntryContainers(WriteableTransaction txn, Set ba } } - nextEntryID = new AtomicLong(highestID.longValue() + 1); + // highestID is null when there was no base DN to open, in which case numbering starts at 1. + nextEntryID = new AtomicLong(highestID != null ? highestID.longValue() + 1 : 1); } /** diff --git a/opendj-server-legacy/src/main/java/org/opends/server/core/MemoryQuota.java b/opendj-server-legacy/src/main/java/org/opends/server/core/MemoryQuota.java index 32af3eb445..9503ef8e5d 100644 --- a/opendj-server-legacy/src/main/java/org/opends/server/core/MemoryQuota.java +++ b/opendj-server-legacy/src/main/java/org/opends/server/core/MemoryQuota.java @@ -12,6 +12,7 @@ * information: "Portions Copyright [year] [name of copyright owner]". * * Copyright 2015 ForgeRock AS. + * Portions Copyright 2026 3A Systems, LLC. */ package org.opends.server.core; @@ -132,7 +133,7 @@ public int memBytesToPercent(long size) */ public long memPercentToBytes(int percent) { - return (reservableMemory * percent / 100) * ONE_MEGABYTE; + return ((long) reservableMemory * percent / 100) * ONE_MEGABYTE; } /** diff --git a/opendj-server-legacy/src/main/java/org/opends/server/core/ModifyDNOperationBasis.java b/opendj-server-legacy/src/main/java/org/opends/server/core/ModifyDNOperationBasis.java index baaa1f3b5d..ac907e6f0c 100644 --- a/opendj-server-legacy/src/main/java/org/opends/server/core/ModifyDNOperationBasis.java +++ b/opendj-server-legacy/src/main/java/org/opends/server/core/ModifyDNOperationBasis.java @@ -13,6 +13,7 @@ * * Copyright 2006-2010 Sun Microsystems, Inc. * Portions Copyright 2011-2016 ForgeRock AS. + * Portions Copyright 2026 3A Systems, LLC. */ package org.opends.server.core; @@ -91,6 +92,12 @@ public class ModifyDNOperationBasis /** The new entry DN. */ private DN newDN; + /** + * Indicates whether the new entry DN has already been computed. The computation does not always + * yield a DN, and its failure is recorded on the operation, so it must not be repeated. + */ + private boolean newDNComputed; + /** * Creates a new modify DN operation with the provided information. * @@ -188,6 +195,9 @@ public final void setRawEntryDN(ByteString rawEntryDN) this.rawEntryDN = rawEntryDN; entryDN = null; + // The new DN is derived from the entry DN, so a failed computation must be allowed to run + // again. Any DN already computed is left in place, as it was before this flag existed. + newDNComputed = false; } @Override @@ -228,6 +238,7 @@ public final void setRawNewRDN(ByteString rawNewRDN) newRDN = null; newDN = null; + newDNComputed = false; } @Override @@ -275,6 +286,7 @@ public final void setRawNewSuperior(ByteString rawNewSuperior) newSuperior = null; newDN = null; + newDNComputed = false; } @Override @@ -510,17 +522,22 @@ public void setProxiedAuthorizationDN(DN dn) @Override public DN getNewDN() { - if (newDN == null) + if (newDN == null && !newDNComputed) { + newDNComputed = true; + // Construct the new DN to use for the entry. - DN parentDN = null; + DN parentDN; if (getNewSuperior() == null) { - if (getEntryDN() != null) + if (getEntryDN() == null) { - parentDN = DirectoryServer.getInstance().getServerContext().getBackendConfigManager() - .getParentDNInSuffix(entryDN); + // The raw DN could not be parsed and INVALID_DN_SYNTAX has already been recorded for it, + // so leave that diagnosis in place rather than replacing it with a less precise one. + return null; } + parentDN = DirectoryServer.getInstance().getServerContext().getBackendConfigManager() + .getParentDNInSuffix(entryDN); } else { @@ -531,6 +548,11 @@ public DN getNewDN() { setResultCode(ResultCode.UNWILLING_TO_PERFORM); appendErrorMessage(ERR_MODDN_NO_PARENT.get(entryDN)); + if (parentDN == null) + { + // Without a parent there is no new DN to build; the error set above is the outcome. + return null; + } } newDN = parentDN.child(getNewRDN()); } diff --git a/opendj-server-legacy/src/main/java/org/opends/server/crypto/CryptoManagerImpl.java b/opendj-server-legacy/src/main/java/org/opends/server/crypto/CryptoManagerImpl.java index 04f3347707..c2f0cb39e9 100644 --- a/opendj-server-legacy/src/main/java/org/opends/server/crypto/CryptoManagerImpl.java +++ b/opendj-server-legacy/src/main/java/org/opends/server/crypto/CryptoManagerImpl.java @@ -14,6 +14,7 @@ * Copyright 2006-2010 Sun Microsystems, Inc. * Portions Copyright 2009 Parametric Technology Corporation (PTC) * Portions Copyright 2011-2016 ForgeRock AS. + * Portions Copyright 2026 3A Systems, LLC. */ package org.opends.server.crypto; @@ -312,7 +313,7 @@ public boolean isConfigurationChangeAcceptable( // Requested encryption cipher validation. String requestedCipherTransformation = cfg.getCipherTransformation(); - Integer requestedCipherTransformationKeyLengthBits = cfg.getCipherKeyLength(); + int requestedCipherTransformationKeyLengthBits = cfg.getCipherKeyLength(); if (! requestedCipherTransformation.equals( this.preferredCipherTransformation) || requestedCipherTransformationKeyLengthBits != @@ -341,7 +342,7 @@ public boolean isConfigurationChangeAcceptable( // Requested MAC algorithm validation. String requestedMACAlgorithm = cfg.getMacAlgorithm(); - Integer requestedMACAlgorithmKeyLengthBits = cfg.getMacKeyLength(); + int requestedMACAlgorithmKeyLengthBits = cfg.getMacKeyLength(); if (!requestedMACAlgorithm.equals(this.preferredMACAlgorithm) || requestedMACAlgorithmKeyLengthBits != this.preferredMACAlgorithmKeyLengthBits) diff --git a/opendj-server-legacy/src/main/java/org/opends/server/extensions/EntryCacheCommon.java b/opendj-server-legacy/src/main/java/org/opends/server/extensions/EntryCacheCommon.java index bb06b58f69..b353c6b15a 100644 --- a/opendj-server-legacy/src/main/java/org/opends/server/extensions/EntryCacheCommon.java +++ b/opendj-server-legacy/src/main/java/org/opends/server/extensions/EntryCacheCommon.java @@ -13,6 +13,7 @@ * * Copyright 2006-2008 Sun Microsystems, Inc. * Portions Copyright 2014-2016 ForgeRock AS. + * Portions Copyright 2026 3A Systems, LLC. */ package org.opends.server.extensions; @@ -362,11 +363,11 @@ public static MonitorData getGenericMonitorData( // Cache misses is required to get cache tries and hit ratio. if (cacheMisses != null) { - Long cacheTries = cacheHits + cacheMisses; + long cacheTries = cacheHits + cacheMisses; attrs.add("entryCacheTries", cacheTries); - Double hitRatioRaw = cacheTries > 0 ? cacheHits.doubleValue() - / cacheTries.doubleValue() : cacheHits.doubleValue() / 1; + double hitRatioRaw = cacheTries > 0 ? cacheHits.doubleValue() + / cacheTries : cacheHits.doubleValue(); Double hitRatio = hitRatioRaw * 100D; attrs.add("entryCacheHitRatio", hitRatio); } diff --git a/opendj-server-legacy/src/main/java/org/opends/server/extensions/SaltedSHA1PasswordStorageScheme.java b/opendj-server-legacy/src/main/java/org/opends/server/extensions/SaltedSHA1PasswordStorageScheme.java index afb064c1e7..e417e1ca7d 100644 --- a/opendj-server-legacy/src/main/java/org/opends/server/extensions/SaltedSHA1PasswordStorageScheme.java +++ b/opendj-server-legacy/src/main/java/org/opends/server/extensions/SaltedSHA1PasswordStorageScheme.java @@ -60,6 +60,13 @@ public class SaltedSHA1PasswordStorageScheme /** The number of bytes of random data to use as the salt when generating the hashes. */ private static final int NUM_SALT_BYTES = 8; + /** + * Source of randomness for the offline encoding, which has no access to the server's + * crypto manager. A single instance is shared because {@code SecureRandom} is thread-safe + * and reseeding it for every password would weaken it. + */ + private static final SecureRandom OFFLINE_RANDOM = new SecureRandom(); + /** The number of bytes SHA algorithm produces. */ private static final int SHA1_LENGTH = 20; @@ -423,7 +430,7 @@ public static String encodeOffline(byte[] passwordBytes) throws DirectoryException { byte[] saltBytes = new byte[NUM_SALT_BYTES]; - new SecureRandom().nextBytes(saltBytes); + OFFLINE_RANDOM.nextBytes(saltBytes); byte[] passwordPlusSalt = new byte[passwordBytes.length + NUM_SALT_BYTES]; System.arraycopy(passwordBytes, 0, passwordPlusSalt, 0, diff --git a/opendj-server-legacy/src/main/java/org/opends/server/extensions/SaltedSHA512PasswordStorageScheme.java b/opendj-server-legacy/src/main/java/org/opends/server/extensions/SaltedSHA512PasswordStorageScheme.java index 1fa32d94c4..23d969b71e 100644 --- a/opendj-server-legacy/src/main/java/org/opends/server/extensions/SaltedSHA512PasswordStorageScheme.java +++ b/opendj-server-legacy/src/main/java/org/opends/server/extensions/SaltedSHA512PasswordStorageScheme.java @@ -60,6 +60,13 @@ public class SaltedSHA512PasswordStorageScheme /** The number of bytes of random data to use as the salt when generating the hashes. */ private static final int NUM_SALT_BYTES = 8; + /** + * Source of randomness for the offline encoding, which has no access to the server's + * crypto manager. A single instance is shared because {@code SecureRandom} is thread-safe + * and reseeding it for every password would weaken it. + */ + private static final SecureRandom OFFLINE_RANDOM = new SecureRandom(); + /** The size of the digest in bytes. */ private static final int SHA512_LENGTH = 512 / 8; @@ -427,7 +434,7 @@ public static String encodeOffline(byte[] passwordBytes) throws DirectoryException { byte[] saltBytes = new byte[NUM_SALT_BYTES]; - new SecureRandom().nextBytes(saltBytes); + OFFLINE_RANDOM.nextBytes(saltBytes); byte[] passwordPlusSalt = new byte[passwordBytes.length + NUM_SALT_BYTES]; System.arraycopy(passwordBytes, 0, passwordPlusSalt, 0, diff --git a/opendj-server-legacy/src/main/java/org/opends/server/loggers/CommonAudit.java b/opendj-server-legacy/src/main/java/org/opends/server/loggers/CommonAudit.java index 59240a4915..8445d97135 100644 --- a/opendj-server-legacy/src/main/java/org/opends/server/loggers/CommonAudit.java +++ b/opendj-server-legacy/src/main/java/org/opends/server/loggers/CommonAudit.java @@ -12,6 +12,7 @@ * information: "Portions Copyright [year] [name of copyright owner]". * * Copyright 2015-2016 ForgeRock AS. + * Portions Copyright 2026 3A Systems, LLC. */ package org.opends.server.loggers; @@ -357,7 +358,7 @@ private AuditServiceProxy buildAuditService(AuditServiceSetup setup) throws IOException, AuditException, ConfigException { final JsonValue jsonConfig; - try (InputStream input = getClass().getResourceAsStream(AUDIT_SERVICE_JSON_CONFIGURATION_FILE)) + try (InputStream input = CommonAudit.class.getResourceAsStream(AUDIT_SERVICE_JSON_CONFIGURATION_FILE)) { jsonConfig = AuditJsonConfig.getJson(input); } diff --git a/opendj-server-legacy/src/main/java/org/opends/server/loggers/CommonAuditAccessLogPublisher.java b/opendj-server-legacy/src/main/java/org/opends/server/loggers/CommonAuditAccessLogPublisher.java index c0129b1626..d281050e9b 100644 --- a/opendj-server-legacy/src/main/java/org/opends/server/loggers/CommonAuditAccessLogPublisher.java +++ b/opendj-server-legacy/src/main/java/org/opends/server/loggers/CommonAuditAccessLogPublisher.java @@ -12,6 +12,7 @@ * information: "Portions Copyright [year] [name of copyright owner]". * * Copyright 2015-2016 ForgeRock AS. + * Portions Copyright 2026 3A Systems, LLC. */ package org.opends.server.loggers; @@ -501,7 +502,7 @@ private String getTransactionIdFromControl(Operation operation) private Pair getExecutionTime(final Operation operation) { - Long etime = operation.getProcessingNanoTime(); + long etime = operation.getProcessingNanoTime(); // if not configured for nanos, use millis return etime <= -1 ? Pair.of(operation.getProcessingTime(), TimeUnit.MILLISECONDS) : diff --git a/opendj-server-legacy/src/main/java/org/opends/server/loggers/JDKLogging.java b/opendj-server-legacy/src/main/java/org/opends/server/loggers/JDKLogging.java index 5fbb17af46..51f0986e7e 100644 --- a/opendj-server-legacy/src/main/java/org/opends/server/loggers/JDKLogging.java +++ b/opendj-server-legacy/src/main/java/org/opends/server/loggers/JDKLogging.java @@ -12,6 +12,7 @@ * information: "Portions Copyright [year] [name of copyright owner]". * * Copyright 2014-2016 ForgeRock AS. + * Portions Copyright 2026 3A Systems, LLC. */ package org.opends.server.loggers; @@ -112,14 +113,16 @@ private OpenDJHandler(final PrintStream out, final PrintStream err) @Override public void publish(LogRecord record) { - if (getFormatter() == null) + // These calls resolve to Handler's own formatter, not to the enclosing + // JDKLogging.getFormatter(); qualify them so that is unambiguous. + if (super.getFormatter() == null) { - setFormatter(new SimpleFormatter()); + super.setFormatter(new SimpleFormatter()); } try { - String message = getFormatter().format(record); + String message = super.getFormatter().format(record); if (record.getLevel().intValue() >= Level.WARNING.intValue()) { err.write(message.getBytes()); diff --git a/opendj-server-legacy/src/main/java/org/opends/server/replication/server/ServerHandler.java b/opendj-server-legacy/src/main/java/org/opends/server/replication/server/ServerHandler.java index ccb3ebdc85..8037b16cee 100644 --- a/opendj-server-legacy/src/main/java/org/opends/server/replication/server/ServerHandler.java +++ b/opendj-server-legacy/src/main/java/org/opends/server/replication/server/ServerHandler.java @@ -791,7 +791,7 @@ public void lockDomainWithTimeout() throws DirectoryException, final Random random = new Random(); final int randomTime = random.nextInt(6); // Random from 0 to 5 // Wait at least 3 seconds + (0 to 5 seconds) - final long timeout = 3000 + randomTime * 1000; + final long timeout = 3000 + randomTime * 1000L; final boolean lockAcquired = replicationServerDomain.tryLock(timeout); if (!lockAcquired) { diff --git a/opendj-server-legacy/src/main/java/org/opends/server/replication/service/ReplicationBroker.java b/opendj-server-legacy/src/main/java/org/opends/server/replication/service/ReplicationBroker.java index 3015639a45..ce1e673aae 100644 --- a/opendj-server-legacy/src/main/java/org/opends/server/replication/service/ReplicationBroker.java +++ b/opendj-server-legacy/src/main/java/org/opends/server/replication/service/ReplicationBroker.java @@ -1341,7 +1341,7 @@ Map getEvaluations() { if (foundBestRS()) { - final Integer bestRSServerId = getBestRS().getServerId(); + final int bestRSServerId = getBestRS().getServerId(); if (rsEvals.get(bestRSServerId) == null) { final LocalizableMessage eval = NOTE_BEST_RS.get(bestRSServerId, localServerId); diff --git a/opendj-server-legacy/src/main/java/org/opends/server/schema/GeneralizedTimeSyntax.java b/opendj-server-legacy/src/main/java/org/opends/server/schema/GeneralizedTimeSyntax.java index 4fc037c6b4..075f539fb3 100644 --- a/opendj-server-legacy/src/main/java/org/opends/server/schema/GeneralizedTimeSyntax.java +++ b/opendj-server-legacy/src/main/java/org/opends/server/schema/GeneralizedTimeSyntax.java @@ -14,6 +14,7 @@ * Copyright 2006-2009 Sun Microsystems, Inc. * Portions Copyright 2009 D. J. Hagberg, Millibits Consulting, Inc. * Portions Copyright 2012-2016 ForgeRock AS. + * Portions Copyright 2026 3A Systems, LLC. */ package org.opends.server.schema; @@ -1199,7 +1200,7 @@ private static long finishDecodingFraction(String value, int startPos, ResultCode.INVALID_ATTRIBUTE_SYNTAX, message); } - Double fractionValue = Double.parseDouble(fractionBuffer.toString()); + double fractionValue = Double.parseDouble(fractionBuffer.toString()); long additionalMilliseconds = Math.round(fractionValue * multiplier); try diff --git a/opendj-server-legacy/src/main/java/org/opends/server/tasks/ImportTask.java b/opendj-server-legacy/src/main/java/org/opends/server/tasks/ImportTask.java index 648c97bc37..f2f12a2d99 100644 --- a/opendj-server-legacy/src/main/java/org/opends/server/tasks/ImportTask.java +++ b/opendj-server-legacy/src/main/java/org/opends/server/tasks/ImportTask.java @@ -13,6 +13,7 @@ * * Copyright 2006-2009 Sun Microsystems, Inc. * Portions Copyright 2013-2016 ForgeRock AS. + * Portions Copyright 2026 3A Systems, LLC. */ package org.opends.server.tasks; @@ -475,6 +476,15 @@ else if(backend != locatedBackend) } } + if (backend == null) + { + // Unlike initializeTask(), this method does not reject an include branch which resolves to no + // backend, so none of them having resolved leaves nothing to import into. The message of the + // backend ID case is reused here rather than adding a new one for a malformed task. + logger.error(ERR_LDIFIMPORT_NO_BACKENDS_FOR_ID); + return TaskState.STOPPED_BY_ERROR; + } + // Find backends with subordinate base DNs that should be excluded from the import. defaultIncludeBranches = new HashSet<>(backend.getBaseDNs()); for (Backend subBackend : getServerContext().getBackendConfigManager().getSubordinateBackends(backend)) diff --git a/opendj-server-legacy/src/main/java/org/opends/server/tasks/PurgeConflictsHistoricalTask.java b/opendj-server-legacy/src/main/java/org/opends/server/tasks/PurgeConflictsHistoricalTask.java index 82affe6f79..e27421da03 100644 --- a/opendj-server-legacy/src/main/java/org/opends/server/tasks/PurgeConflictsHistoricalTask.java +++ b/opendj-server-legacy/src/main/java/org/opends/server/tasks/PurgeConflictsHistoricalTask.java @@ -13,6 +13,7 @@ * * Copyright 2006-2010 Sun Microsystems, Inc. * Portions Copyright 2013-2016 ForgeRock AS. + * Portions Copyright 2026 3A Systems, LLC. */ package org.opends.server.tasks; @@ -123,18 +124,20 @@ public LocalizableMessage getDisplayName() { @Override protected TaskState runTask() { - Boolean purgeCompletedInTime = false; + boolean purgeCompletedInTime = false; logger.trace("PurgeConflictsHistoricalTask is starting on domain: %s max duration (sec): %d", domain.getBaseDN(), purgeTaskMaxDurationInSec); try { - replaceAttributeValue(ATTR_TASK_CONFLICTS_HIST_PURGE_COMPLETED_IN_TIME, purgeCompletedInTime.toString()); + replaceAttributeValue(ATTR_TASK_CONFLICTS_HIST_PURGE_COMPLETED_IN_TIME, + String.valueOf(purgeCompletedInTime)); // launch the task - domain.purgeConflictsHistorical(this, TimeThread.getTime() + purgeTaskMaxDurationInSec*1000); + domain.purgeConflictsHistorical(this, TimeThread.getTime() + purgeTaskMaxDurationInSec * 1000L); purgeCompletedInTime = true; - replaceAttributeValue(ATTR_TASK_CONFLICTS_HIST_PURGE_COMPLETED_IN_TIME, purgeCompletedInTime.toString()); + replaceAttributeValue(ATTR_TASK_CONFLICTS_HIST_PURGE_COMPLETED_IN_TIME, + String.valueOf(purgeCompletedInTime)); initState = TaskState.COMPLETED_SUCCESSFULLY; } diff --git a/opendj-server-legacy/src/main/java/org/opends/server/tools/dsreplication/ReplicationCliMain.java b/opendj-server-legacy/src/main/java/org/opends/server/tools/dsreplication/ReplicationCliMain.java index 07227ffdd5..716009f9cd 100644 --- a/opendj-server-legacy/src/main/java/org/opends/server/tools/dsreplication/ReplicationCliMain.java +++ b/opendj-server-legacy/src/main/java/org/opends/server/tools/dsreplication/ReplicationCliMain.java @@ -6595,7 +6595,7 @@ public void progressUpdate(ProgressUpdateEvent ev) ERR_REPLICATION_INITIALIZING_TRIES_COMPLETED.get( pnfe.getMessageObject()), INITIALIZING_TRIES_COMPLETED, pnfe); } - sleepCatchInterrupt((5 - nTries) * 3000); + sleepCatchInterrupt((5 - nTries) * 3000L); } catch (ApplicationException ae) { @@ -6648,7 +6648,7 @@ public void initializeAllSuffix(DN baseDN, ConnectionWrapper conn, boolean displ ERR_REPLICATION_INITIALIZING_TRIES_COMPLETED.get( pnfe.getMessageObject()), INITIALIZING_TRIES_COMPLETED, pnfe); } - sleepCatchInterrupt((5 - nTries) * 3000); + sleepCatchInterrupt((5 - nTries) * 3000L); } catch (ClientException ae) { diff --git a/opendj-server-legacy/src/main/java/org/opends/server/tools/status/StatusCli.java b/opendj-server-legacy/src/main/java/org/opends/server/tools/status/StatusCli.java index 86a47b9388..ac59a1290d 100644 --- a/opendj-server-legacy/src/main/java/org/opends/server/tools/status/StatusCli.java +++ b/opendj-server-legacy/src/main/java/org/opends/server/tools/status/StatusCli.java @@ -79,7 +79,6 @@ import org.opends.server.types.InitializationException; import org.opends.server.types.NullOutputStream; import org.opends.server.util.BuildVersion; -import org.opends.server.util.StaticUtils; import org.opends.server.util.cli.LDAPConnectionConsoleInteraction; import com.forgerock.opendj.cli.ArgumentException; @@ -355,9 +354,10 @@ private void writeStatus(ControlPanelInfo controlInfo) writeStatus(controlInfo.getServerDescriptor()); int period = argParser.getRefreshPeriod(); boolean first = true; - while (period > 0) + // A positive refresh period means refreshing until the command is interrupted. + while (period > 0 && !Thread.currentThread().isInterrupted()) { - long timeToSleep = period * 1000; + long timeToSleep = period * 1000L; if (!first) { long t1 = System.currentTimeMillis(); @@ -369,7 +369,17 @@ private void writeStatus(ControlPanelInfo controlInfo) if (timeToSleep > 0) { - StaticUtils.sleep(timeToSleep); + try + { + // Not StaticUtils.sleep(): it discards the interruption, which would leave this loop + // running with no way for the caller to stop it. + Thread.sleep(timeToSleep); + } + catch (InterruptedException e) + { + Thread.currentThread().interrupt(); + break; + } } println(); println(LocalizableMessage.raw(" ---------------------")); @@ -1125,7 +1135,7 @@ private ManagementContext getManagementContextFromConnection( // Interact with the user though the console to get // LDAP connection information final String hostName = getHostNameForLdapUrl(ci.getHostName()); - final Integer portNumber = ci.getPortNumber(); + final int portNumber = ci.getPortNumber(); final DN bindDN = ci.getBindDN(); final String bindPassword = ci.getBindPassword(); TrustManager trustManager = ci.getTrustManager(); diff --git a/opendj-server-legacy/src/main/java/org/opends/server/types/Entry.java b/opendj-server-legacy/src/main/java/org/opends/server/types/Entry.java index c8087de18f..9bab17e04c 100644 --- a/opendj-server-legacy/src/main/java/org/opends/server/types/Entry.java +++ b/opendj-server-legacy/src/main/java/org/opends/server/types/Entry.java @@ -13,7 +13,7 @@ * * Copyright 2006-2010 Sun Microsystems, Inc. * Portions Copyright 2011-2016 ForgeRock AS. - * Portions Copyright 2023-2024 3A Systems, LLC. + * Portions Copyright 2023-2026 3A Systems, LLC. */ package org.opends.server.types; @@ -3357,7 +3357,7 @@ public static Entry decode(ByteSequenceReader entryBuffer, { // The first byte must be the entry version. If it's not one // we recognize, then that's an error. - Byte version = entryBuffer.readByte(); + byte version = entryBuffer.readByte(); if (version != 0x03 && version != 0x02 && version != 0x01) { LocalizableMessage message = ERR_ENTRY_DECODE_UNRECOGNIZED_VERSION.get( diff --git a/opendj-server-legacy/src/main/java/org/opends/server/util/CronExecutorService.java b/opendj-server-legacy/src/main/java/org/opends/server/util/CronExecutorService.java index 6b74dc87cc..22486eca46 100644 --- a/opendj-server-legacy/src/main/java/org/opends/server/util/CronExecutorService.java +++ b/opendj-server-legacy/src/main/java/org/opends/server/util/CronExecutorService.java @@ -12,6 +12,7 @@ * information: "Portions Copyright [year] [name of copyright owner]". * * Copyright 2016 ForgeRock AS. + * Portions Copyright 2026 3A Systems, LLC. */ package org.opends.server.util; @@ -90,8 +91,11 @@ public void setSchedulerFuture(Future schedulerFuture) @Override public boolean cancel(boolean mayInterruptIfRunning) { - return schedulerFuture.cancel(mayInterruptIfRunning) - | (executorFuture != null && executorFuture.cancel(mayInterruptIfRunning)); + // Both futures must be cancelled, so neither call may be short circuited. + final boolean schedulerCancelled = schedulerFuture.cancel(mayInterruptIfRunning); + final boolean executorCancelled = + executorFuture != null && executorFuture.cancel(mayInterruptIfRunning); + return schedulerCancelled || executorCancelled; } @Override @@ -351,7 +355,10 @@ public List> invokeAll(final Collection> tas @Override public boolean awaitTermination(final long timeout, final TimeUnit unit) throws InterruptedException { - return cronScheduler.awaitTermination(timeout, unit) & cronExecutorService.awaitTermination(timeout, unit); + // Both services must be awaited, so neither call may be short circuited. + final boolean schedulerTerminated = cronScheduler.awaitTermination(timeout, unit); + final boolean executorTerminated = cronExecutorService.awaitTermination(timeout, unit); + return schedulerTerminated && executorTerminated; } @Override diff --git a/opendj-server-legacy/src/main/java/org/opends/server/util/StaticUtils.java b/opendj-server-legacy/src/main/java/org/opends/server/util/StaticUtils.java index 5e344e8b61..e4d8c8eda5 100644 --- a/opendj-server-legacy/src/main/java/org/opends/server/util/StaticUtils.java +++ b/opendj-server-legacy/src/main/java/org/opends/server/util/StaticUtils.java @@ -511,11 +511,7 @@ public static int compare(byte[] a, byte[] a2) { int firstByte = 0xFF & a[i]; int secondByte = 0xFF & a2[i]; if (firstByte != secondByte) { - if (firstByte < secondByte) { - return -1; - } else if (firstByte > secondByte) { - return 1; - } + return firstByte < secondByte ? -1 : 1; } } @@ -1795,7 +1791,10 @@ public static boolean recursiveDelete(File file) } } - return successful & file.delete(); + // The delete must be attempted even when a child could not be removed, so it is + // evaluated into a local before being combined with the running result. + final boolean deleted = file.delete(); + return successful && deleted; } return false; } diff --git a/opendj-server-legacy/src/snmp/src/org/opends/server/snmp/DsMIBImpl.java b/opendj-server-legacy/src/snmp/src/org/opends/server/snmp/DsMIBImpl.java index 204aaacdc8..d616140d92 100644 --- a/opendj-server-legacy/src/snmp/src/org/opends/server/snmp/DsMIBImpl.java +++ b/opendj-server-legacy/src/snmp/src/org/opends/server/snmp/DsMIBImpl.java @@ -238,8 +238,7 @@ private boolean addRowInDsTable() { this.mib, this.server, this.applIndex); // if the entry already exists nothing to do - if ((this.dsTableEntries.containsKey(entry.getObjectName())) || - (entry == null)) { + if (this.dsTableEntries.containsKey(entry.getObjectName())) { return true; } @@ -279,8 +278,7 @@ private boolean addRowInDsApplIfOpsTable(ObjectName connectionHandlerName) { this.applIndex, this.applIfOpsIndex); // If the entry already exists then nothing to do - if ((this.dsApplIfOpsTableEntries.containsKey(entry.getObjectName())) || - (entry == null)) { + if (this.dsApplIfOpsTableEntries.containsKey(entry.getObjectName())) { return true; } // Add the entry in the Table diff --git a/opendj-server/src/main/java/org/forgerock/opendj/server/core/ProductInformation.java b/opendj-server/src/main/java/org/forgerock/opendj/server/core/ProductInformation.java index 11b7d0a34c..0c81ec7096 100644 --- a/opendj-server/src/main/java/org/forgerock/opendj/server/core/ProductInformation.java +++ b/opendj-server/src/main/java/org/forgerock/opendj/server/core/ProductInformation.java @@ -12,6 +12,7 @@ * information: "Portions Copyright [year] [name of copyright owner]". * * Copyright 2014-2016 ForgeRock AS. + * Portions Copyright 2026 3A Systems, LLC. */ package org.forgerock.opendj.server.core; @@ -43,7 +44,7 @@ public static ProductInformation getInstance() { private ProductInformation(final String productName) { final String resourceName = "/META-INF/product/" + productName + ".properties"; - final InputStream stream = getClass().getResourceAsStream(resourceName); + final InputStream stream = ProductInformation.class.getResourceAsStream(resourceName); if (stream == null) { throw new MissingResourceException("Can't find product information " + resourceName,