There are definitely no shared static properties in the DN class. Both the internal RDN array and the string representation of a DN are final. The normalized string representation of a DN isn't final, but it may only be computed based on final arguments, so it will always be exactly the same for a given DN even if it needs to be generated multiple times as a result of a race condition.
However, it is important to note that while the RDN array is final, for performance reasons we don't create a copy of it when making use of it outside the DN class. That is, if you create a DN from an RDN array and then later alter the contents of that RDN array, or if you call the getRDNs() method and then alter the contents of that array, then that will adversely impact the DN using that array. None of the methods in the DN class will ever alter the contents of the RDN array after it has been created, so if you are seeing something weird then it is most likely something that your application is doing to the RDN array outside of the code snippet provided above.
I don't see anything in the code that you have provided which would cause the behavior that you described. If you can provide me with a self-contained test case that reproduces the problem, then I'll be happy to examine it and fix any problem that may exist in the LDAP SDK code. I would also recommend looking at your application and anywhere you call DN.getRDNs() you make sure to create a copy of the array that is returned, and anywhere you create a DN from an array of RDNs you first make a copy of that array and create the DN from the copy. If after doing that the problem no longer exists, then that is confirmation that the problem is in your application rather than the LDAP SDK itself. If the problem still exists after you do that, then there is likely something in the LDAP SDK itself, although I really don't see how that is possible.
Neil
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
You were right, as usual, Neil. Deep down in my code I reversed the RDN array for some entries. What confused me was that toString(), and its sisters, all presented the correct DN even as the RDN array was reversed.
One suggestion though. I think it would be good if you could add a note in the javadoc about getting a reference to the internal RDN array instead of a copy for getRDNs().
Henrik
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
The class-level documentation for the com.unboundid.util.ThreadSafety discusses this as a general rule for the entire LDAP SDK. In particular, it states "If an array is provided as an argument to a constructor or a method, then that array must not be referenced or altered by the caller at any time after that point unless it is clearly noted that it is acceptable to do so" and also "If an array is returned by a method, then the contents of that array must not be altered unless it is clearly noted that it is acceptable to do so".
Because of the pervasive way in which arrays are used throughout the LDAP SDK, it is not really feasible to include comments like that in every context in which they may be used, if for no other reason than that it would be hard to remember to continue putting in that documentation when adding new methods that have arrays as argument or return types. Also, in order to achieve optimal performance, it isn't feasible to alter the LDAP SDK to duplicate an array any time it might be obtained from or returned to external code.
The general rule that I follow when dealing with arrays that I either pass in or get back from a method is that unless I know that the array is going to be copied, I treat it as read-only or create a copy myself.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
There are definitely no shared static properties in the DN class. Both the internal RDN array and the string representation of a DN are final. The normalized string representation of a DN isn't final, but it may only be computed based on final arguments, so it will always be exactly the same for a given DN even if it needs to be generated multiple times as a result of a race condition.
However, it is important to note that while the RDN array is final, for performance reasons we don't create a copy of it when making use of it outside the DN class. That is, if you create a DN from an RDN array and then later alter the contents of that RDN array, or if you call the getRDNs() method and then alter the contents of that array, then that will adversely impact the DN using that array. None of the methods in the DN class will ever alter the contents of the RDN array after it has been created, so if you are seeing something weird then it is most likely something that your application is doing to the RDN array outside of the code snippet provided above.
I don't see anything in the code that you have provided which would cause the behavior that you described. If you can provide me with a self-contained test case that reproduces the problem, then I'll be happy to examine it and fix any problem that may exist in the LDAP SDK code. I would also recommend looking at your application and anywhere you call DN.getRDNs() you make sure to create a copy of the array that is returned, and anywhere you create a DN from an array of RDNs you first make a copy of that array and create the DN from the copy. If after doing that the problem no longer exists, then that is confirmation that the problem is in your application rather than the LDAP SDK itself. If the problem still exists after you do that, then there is likely something in the LDAP SDK itself, although I really don't see how that is possible.
Neil
You were right, as usual, Neil. Deep down in my code I reversed the RDN array for some entries. What confused me was that toString(), and its sisters, all presented the correct DN even as the RDN array was reversed.
One suggestion though. I think it would be good if you could add a note in the javadoc about getting a reference to the internal RDN array instead of a copy for getRDNs().
Henrik
The class-level documentation for the com.unboundid.util.ThreadSafety discusses this as a general rule for the entire LDAP SDK. In particular, it states "If an array is provided as an argument to a constructor or a method, then that array must not be referenced or altered by the caller at any time after that point unless it is clearly noted that it is acceptable to do so" and also "If an array is returned by a method, then the contents of that array must not be altered unless it is clearly noted that it is acceptable to do so".
Because of the pervasive way in which arrays are used throughout the LDAP SDK, it is not really feasible to include comments like that in every context in which they may be used, if for no other reason than that it would be hard to remember to continue putting in that documentation when adding new methods that have arrays as argument or return types. Also, in order to achieve optimal performance, it isn't feasible to alter the LDAP SDK to duplicate an array any time it might be obtained from or returned to external code.
The general rule that I follow when dealing with arrays that I either pass in or get back from a method is that unless I know that the array is going to be copied, I treat it as read-only or create a copy myself.