Refactor DN and RDN classes and improve their test coverage.
The following refactoring work was performed:
* removed the DN, RDN, and AVA comparator classes. The DN
and RDN classes implement Comparable. RDN.compareTo now
uses ordering matching rules where possible (taken from
the original RDN Comparator class)
* RDN class is now almost immutable (it's intention is to
be 100% immutable). It is still possible to retrieve
attribute values and modify them (attribute values should
be immutable - issue raised)
* RDN compareTo, hashCode, and equals methods now
sort AVAs based on the type's name/oid (previously no
sorting was performed)
* provide factory methods for simple RDNs and a builder
class for constructing more complex RDNs
* DN class is now immutable with the exception described above
for RDN attribute values. There are now factory methods for
creating, joining, and splitting DNs
* special factory method for creating null DNs - DN.nullDN()
* DN.getParent() renamed to DN.getParentDNInSuffix() - all references
updated - this method will be moved in a subsequent change
to the DirectoryServer class
* implemented a new DN.getParent() method which ignores suffixes
* DN no longer copy their RDN array when constructing parent
DNs or localNames - instead array offset+length is identifies
which part of the array is associated with the DN
* refactored and simplified much of the DN/RDN decoding routines
3 files deleted
1 files added
77 files modified
| | |
| | | LinkedHashMap<AttributeType,List<Attribute>> userAttrs = |
| | | new LinkedHashMap<AttributeType,List<Attribute>>(1); |
| | | |
| | | AttributeType[] attrTypes = backupBaseDN.getRDN().getAttributeTypes(); |
| | | AttributeValue[] attrValues = backupBaseDN.getRDN().getAttributeValues(); |
| | | for (int i=0; i < attrTypes.length; i++) |
| | | RDN rdn = backupBaseDN.getRDN(); |
| | | int numAVAs = rdn.getNumValues(); |
| | | for (int i=0; i < numAVAs; i++) |
| | | { |
| | | LinkedHashSet<AttributeValue> valueSet = |
| | | new LinkedHashSet<AttributeValue>(1); |
| | | valueSet.add(attrValues[i]); |
| | | valueSet.add(rdn.getAttributeValue(i)); |
| | | |
| | | AttributeType attrType = rdn.getAttributeType(i); |
| | | ArrayList<Attribute> attrList = new ArrayList<Attribute>(1); |
| | | attrList.add(new Attribute(attrTypes[i], attrTypes[i].getNameOrOID(), |
| | | attrList.add(new Attribute(attrType, attrType.getNameOrOID(), |
| | | valueSet)); |
| | | |
| | | userAttrs.put(attrTypes[i], attrList); |
| | | userAttrs.put(attrType, attrList); |
| | | } |
| | | |
| | | backupBaseEntry = new Entry(backupBaseDN, objectClasses, userAttrs, |
| | |
| | | // If so, then it must point to a backup directory. Otherwise, it must be |
| | | // two levels below the backup base entry and must point to a specific |
| | | // backup. |
| | | DN parentDN = entryDN.getParent(); |
| | | DN parentDN = entryDN.getParentDNInSuffix(); |
| | | if (parentDN == null) |
| | | { |
| | | int msgID = MSGID_BACKUP_INVALID_BASE; |
| | |
| | | { |
| | | return getBackupDirectoryEntry(entryDN); |
| | | } |
| | | else if (backupBaseDN.equals(parentDN.getParent())) |
| | | else if (backupBaseDN.equals(parentDN.getParentDNInSuffix())) |
| | | { |
| | | return getBackupEntry(entryDN); |
| | | } |
| | |
| | | |
| | | |
| | | // Next, get the backup directory from the parent DN. |
| | | DN parentDN = entryDN.getParent(); |
| | | DN parentDN = entryDN.getParentDNInSuffix(); |
| | | if (parentDN == null) |
| | | { |
| | | int msgID = MSGID_BACKUP_NO_BACKUP_PARENT_DN; |
| | |
| | | } |
| | | } |
| | | } |
| | | else if (backupBaseDN.equals(parentDN = baseDN.getParent())) |
| | | else if (backupBaseDN.equals(parentDN = baseDN.getParentDNInSuffix())) |
| | | { |
| | | Entry backupDirEntry = getBackupDirectoryEntry(baseDN); |
| | | |
| | |
| | | } |
| | | else |
| | | { |
| | | if ((parentDN == null) || (! backupBaseDN.equals(parentDN.getParent()))) |
| | | if ((parentDN == null) |
| | | || (! backupBaseDN.equals(parentDN.getParentDNInSuffix()))) |
| | | { |
| | | int msgID = MSGID_BACKUP_NO_SUCH_ENTRY; |
| | | String message = getMessage(msgID); |
| | |
| | | public static DN makeChildDN(DN parentDN, AttributeType rdnAttrType, |
| | | String rdnStringValue) |
| | | { |
| | | RDN[] baseComponents = parentDN.getRDNComponents(); |
| | | RDN[] components = new RDN[baseComponents.length+1]; |
| | | AttributeValue attrValue = |
| | | new AttributeValue(rdnAttrType, rdnStringValue); |
| | | components[0] = new RDN(rdnAttrType, attrValue); |
| | | System.arraycopy(baseComponents, 0, components, 1, baseComponents.length); |
| | | return new DN(components); |
| | | return parentDN.concat(RDN.create(rdnAttrType, attrValue)); |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | |
| | | // Get the parent DN and ensure that it exists in the backend. |
| | | DN parentDN = entryDN.getParent(); |
| | | DN parentDN = entryDN.getParentDNInSuffix(); |
| | | if (parentDN == null) |
| | | { |
| | | int msgID = MSGID_MEMORYBACKEND_ENTRY_DOESNT_BELONG; |
| | |
| | | childDNs.remove(entryDN); |
| | | entryMap.remove(entryDN); |
| | | |
| | | DN parentDN = entryDN.getParent(); |
| | | DN parentDN = entryDN.getParentDNInSuffix(); |
| | | if (parentDN != null) |
| | | { |
| | | HashSet<DN> parentsChildren = childDNs.get(parentDN); |
| | |
| | | |
| | | |
| | | // Make sure that the parent of the new entry exists. |
| | | DN parentDN = entry.getDN().getParent(); |
| | | DN parentDN = entry.getDN().getParentDNInSuffix(); |
| | | if ((parentDN == null) || (! entryMap.containsKey(parentDN))) |
| | | { |
| | | int msgID = MSGID_MEMORYBACKEND_RENAME_PARENT_DOESNT_EXIST; |
| | |
| | | |
| | | // See if the monitor base entry is the immediate parent for the requested |
| | | // entry. If not, then throw an exception. |
| | | DN parentDN = entryDN.getParent(); |
| | | DN parentDN = entryDN.getParentDNInSuffix(); |
| | | if ((parentDN == null) || (! parentDN.equals(baseMonitorDN))) |
| | | { |
| | | if (baseMonitorDN.isAncestorOf(entryDN)) |
| | |
| | | |
| | | // Get the RDN value and see if it matches the instance name for one of |
| | | // the directory server monitor providers. |
| | | String rdnValue = entryRDN.getAttributeValues()[0].getStringValue(); |
| | | String rdnValue = entryRDN.getAttributeValue(0).getStringValue(); |
| | | MonitorProvider monitorProvider = |
| | | DirectoryServer.getMonitorProvider(rdnValue.toLowerCase()); |
| | | if (monitorProvider == null) |
| | |
| | | return true; |
| | | } |
| | | |
| | | DN parentDN = entryDN.getParent(); |
| | | DN parentDN = entryDN.getParentDNInSuffix(); |
| | | if ((parentDN == null) || (! parentDN.equals(baseMonitorDN))) |
| | | { |
| | | return false; |
| | |
| | | return false; |
| | | } |
| | | |
| | | String rdnValue = rdn.getAttributeValues()[0].getStringValue(); |
| | | String rdnValue = rdn.getAttributeValue(0).getStringValue(); |
| | | MonitorProvider monitorProvider = |
| | | DirectoryServer.getMonitorProvider(toLowerCase(rdnValue)); |
| | | return (monitorProvider != null); |
| | |
| | | |
| | | // Make sure to include the RDN attribute. |
| | | RDN entryRDN = entryDN.getRDN(); |
| | | AttributeType rdnType = entryRDN.getAttributeTypes()[0]; |
| | | AttributeValue rdnValue = entryRDN.getAttributeValues()[0]; |
| | | AttributeType rdnType = entryRDN.getAttributeType(0); |
| | | AttributeValue rdnValue = entryRDN.getAttributeValue(0); |
| | | |
| | | LinkedHashSet<AttributeValue> rdnValues = |
| | | new LinkedHashSet<AttributeValue>(1); |
| | | rdnValues.add(rdnValue); |
| | | |
| | | Attribute rdnAttr = new Attribute(rdnType, entryRDN.getAttributeNames()[0], |
| | | Attribute rdnAttr = new Attribute(rdnType, entryRDN.getAttributeName(0), |
| | | rdnValues); |
| | | ArrayList<Attribute> rdnList = new ArrayList<Attribute>(1); |
| | | rdnList.add(rdnAttr); |
| | |
| | | import org.opends.server.types.LDIFExportConfig; |
| | | import org.opends.server.types.LDIFImportConfig; |
| | | import org.opends.server.types.ObjectClass; |
| | | import org.opends.server.types.RDN; |
| | | import org.opends.server.types.RestoreConfig; |
| | | import org.opends.server.types.ResultCode; |
| | | import org.opends.server.types.SearchFilter; |
| | |
| | | |
| | | // Create the set of base DNs that we will handle. In this case, it's just |
| | | // the root DSE. |
| | | rootDSEDN = new DN(new ArrayList<RDN>(0)); |
| | | rootDSEDN = DN.nullDN(); |
| | | this.baseDNs = new DN[] { rootDSEDN }; |
| | | |
| | | |
| | |
| | | RDN rdn = entryDN.getRDN(); |
| | | if (rdn != null) |
| | | { |
| | | String[] rdnNames = rdn.getAttributeNames(); |
| | | AttributeType[] rdnTypes = rdn.getAttributeTypes(); |
| | | AttributeValue[] rdnValues = rdn.getAttributeValues(); |
| | | |
| | | int numRDNs = rdnTypes.length; |
| | | for (int i=0; i < numRDNs; i++) |
| | | int numAVAs = rdn.getNumValues(); |
| | | for (int i=0; i < numAVAs; i++) |
| | | { |
| | | LinkedHashSet<AttributeValue> valueSet = |
| | | new LinkedHashSet<AttributeValue>(1); |
| | | valueSet.add(rdnValues[i]); |
| | | valueSet.add(rdn.getAttributeValue(i)); |
| | | |
| | | AttributeType attrType = rdnTypes[i]; |
| | | Attribute a = new Attribute(attrType, rdnNames[i], valueSet); |
| | | AttributeType attrType = rdn.getAttributeType(i); |
| | | String attrName = rdn.getAttributeName(i); |
| | | Attribute a = new Attribute(attrType, attrName, valueSet); |
| | | ArrayList<Attribute> attrList = new ArrayList<Attribute>(1); |
| | | attrList.add(a); |
| | | |
| | |
| | | { |
| | | urlBaseDN = |
| | | EntryContainer.modDN(targetDN, |
| | | referralDN.getRDNComponents().length, |
| | | referralDN.getNumComponents(), |
| | | ldapurl.getBaseDN()); |
| | | } |
| | | ldapurl.setBaseDN(urlBaseDN); |
| | |
| | | // Make sure the referral is within scope. |
| | | if (searchOp.getScope() == SearchScope.SINGLE_LEVEL) |
| | | { |
| | | if ((dn.getRDNComponents().length != |
| | | baseDN.getRDNComponents().length + 1)) |
| | | if ((dn.getNumComponents() != |
| | | baseDN.getNumComponents() + 1)) |
| | | { |
| | | continue; |
| | | } |
| | |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.LockType; |
| | | import org.opends.server.types.Modification; |
| | | import org.opends.server.types.RDN; |
| | | import org.opends.server.types.ResultCode; |
| | | import org.opends.server.types.SearchScope; |
| | | import org.opends.server.util.StaticUtils; |
| | |
| | | if (searchScope == SearchScope.SINGLE_LEVEL) |
| | | { |
| | | // Check if this entry is an immediate child. |
| | | if ((dn.getRDNComponents().length != |
| | | baseDN.getRDNComponents().length + 1)) |
| | | if ((dn.getNumComponents() != |
| | | baseDN.getNumComponents() + 1)) |
| | | { |
| | | isInScope = false; |
| | | } |
| | |
| | | else if (searchScope == SearchScope.SINGLE_LEVEL) |
| | | { |
| | | // Check if this entry is an immediate child. |
| | | if ((entryDN.getRDNComponents().length == |
| | | baseDN.getRDNComponents().length + 1) && |
| | | if ((entryDN.getNumComponents() == |
| | | baseDN.getNumComponents() + 1) && |
| | | entryDN.isDescendantOf(baseDN)) |
| | | { |
| | | isInScope = true; |
| | |
| | | } |
| | | else if (searchScope == SearchScope.SUBORDINATE_SUBTREE) |
| | | { |
| | | if ((entryDN.getRDNComponents().length > |
| | | baseDN.getRDNComponents().length) && |
| | | if ((entryDN.getNumComponents() > |
| | | baseDN.getNumComponents()) && |
| | | entryDN.isDescendantOf(baseDN)) |
| | | { |
| | | isInScope = true; |
| | |
| | | |
| | | // Construct the new DN of the entry. |
| | | DN newDN = modDN(oldEntry.getDN(), |
| | | oldApexDN.getRDNComponents().length, |
| | | oldApexDN.getNumComponents(), |
| | | newApexEntry.getDN()); |
| | | |
| | | if (requestedNewSuperiorDN != null) |
| | |
| | | */ |
| | | public static DN modDN(DN oldDN, int oldSuffixLen, DN newSuffixDN) |
| | | { |
| | | RDN[] oldRDNs = oldDN.getRDNComponents(); |
| | | RDN[] suffixRDNs = newSuffixDN.getRDNComponents(); |
| | | |
| | | int prefixLen = oldRDNs.length - oldSuffixLen; |
| | | RDN[] newRDNs = new RDN[prefixLen + suffixRDNs.length]; |
| | | |
| | | // Copy the unchanged prefix. |
| | | System.arraycopy(oldRDNs, 0, |
| | | newRDNs, 0, |
| | | prefixLen); |
| | | |
| | | // Copy the new suffix. |
| | | System.arraycopy(suffixRDNs, 0, |
| | | newRDNs, prefixLen, |
| | | suffixRDNs.length); |
| | | |
| | | return new DN(newRDNs); |
| | | DN localName = oldDN.getLocalName(oldSuffixLen); |
| | | return newSuffixDN.concat(localName); |
| | | } |
| | | |
| | | /** |
| | |
| | | } |
| | | else |
| | | { |
| | | IDs = new ArrayList<EntryID>(entryDN.getRDNComponents().length); |
| | | IDs = new ArrayList<EntryID>(entryDN.getNumComponents()); |
| | | IDs.add(entryID); |
| | | if (parentID != null) |
| | | { |
| | |
| | | importContext = importMap.get(nodeDN); |
| | | if (importContext == null) |
| | | { |
| | | nodeDN = nodeDN.getParent(); |
| | | nodeDN = nodeDN.getParentDNInSuffix(); |
| | | } |
| | | } |
| | | |
| | |
| | | ec = entryContainers.get(nodeDN); |
| | | if (ec == null) |
| | | { |
| | | nodeDN = nodeDN.getParent(); |
| | | nodeDN = nodeDN.getParentDNInSuffix(); |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | if (!childEntry.getDN().isDescendantOf(entry.getDN()) || |
| | | childEntry.getDN().getRDNComponents().length != |
| | | entry.getDN().getRDNComponents().length + 1) |
| | | childEntry.getDN().getNumComponents() != |
| | | entry.getDN().getNumComponents() + 1) |
| | | { |
| | | errorCount++; |
| | | System.err.printf("File id2children has ID %d with DN <%s> " + |
| | |
| | | { |
| | | return null; |
| | | } |
| | | return dn.getParent(); |
| | | return dn.getParentDNInSuffix(); |
| | | } |
| | | |
| | | /** |
| | |
| | | return taskScheduler.getRecurringTaskParentEntry(); |
| | | } |
| | | |
| | | DN parentDN = entryDN.getParent(); |
| | | DN parentDN = entryDN.getParentDNInSuffix(); |
| | | if (parentDN == null) |
| | | { |
| | | return null; |
| | |
| | | return true; |
| | | } |
| | | |
| | | DN parentDN = entryDN.getParent(); |
| | | DN parentDN = entryDN.getParentDNInSuffix(); |
| | | if (parentDN == null) |
| | | { |
| | | return false; |
| | |
| | | |
| | | // Get the DN for the entry and then get its parent. |
| | | DN entryDN = entry.getDN(); |
| | | DN parentDN = entryDN.getParent(); |
| | | DN parentDN = entryDN.getParentDNInSuffix(); |
| | | |
| | | if (parentDN == null) |
| | | { |
| | |
| | | |
| | | // Get the parent for the provided entry DN. It must be either the |
| | | // scheduled or recurring task parent DN. |
| | | DN parentDN = entryDN.getParent(); |
| | | DN parentDN = entryDN.getParentDNInSuffix(); |
| | | if (parentDN == null) |
| | | { |
| | | int msgID = MSGID_TASKBE_DELETE_INVALID_ENTRY; |
| | |
| | | } |
| | | else |
| | | { |
| | | DN parentDN = baseDN.getParent(); |
| | | DN parentDN = baseDN.getParentDNInSuffix(); |
| | | if (parentDN == null) |
| | | { |
| | | int msgID = MSGID_TASKBE_SEARCH_INVALID_BASE; |
| | |
| | | } |
| | | else |
| | | { |
| | | DN parentDN = entryDN.getParent(); |
| | | DN parentDN = entryDN.getParentDNInSuffix(); |
| | | if (parentDN == null) |
| | | { |
| | | int msgID = MSGID_TASKSCHED_ENTRY_HAS_NO_PARENT; |
| | |
| | | // Check for a zero-length value, which would be for an anonymous user. |
| | | if (authorizationID.value().length == 0) |
| | | { |
| | | return new DN(); |
| | | return DN.nullDN(); |
| | | } |
| | | |
| | | |
| | |
| | | // If the authorization ID is just "u:", then it's an anonymous request. |
| | | if (lowerAuthzID.length() == 2) |
| | | { |
| | | return new DN(); |
| | | return DN.nullDN(); |
| | | } |
| | | |
| | | |
| | |
| | | Lock parentLock = null; |
| | | Lock entryLock = null; |
| | | |
| | | DN parentDN = entryDN.getParent(); |
| | | DN parentDN = entryDN.getParentDNInSuffix(); |
| | | if (parentDN == null) |
| | | { |
| | | // Either this entry is a suffix or doesn't belong in the directory. |
| | | if (entryDN.isSuffix()) |
| | | if (DirectoryServer.isSuffix(entryDN)) |
| | | { |
| | | // This is fine. This entry is one of the configured suffixes. |
| | | parentLock = null; |
| | |
| | | |
| | | if (parentEntry == null) |
| | | { |
| | | DN matchedDN = parentDN.getParent(); |
| | | DN matchedDN = parentDN.getParentDNInSuffix(); |
| | | while (matchedDN != null) |
| | | { |
| | | try |
| | |
| | | break; |
| | | } |
| | | |
| | | matchedDN = matchedDN.getParent(); |
| | | matchedDN = matchedDN.getParentDNInSuffix(); |
| | | } |
| | | |
| | | |
| | |
| | | // Check to make sure that all of the RDN attributes are included as |
| | | // attribute values. If not, then either add them or report an error. |
| | | RDN rdn = entryDN.getRDN(); |
| | | AttributeType[] rdnTypes = rdn.getAttributeTypes(); |
| | | AttributeValue[] rdnValues = rdn.getAttributeValues(); |
| | | String[] rdnNames = rdn.getAttributeNames(); |
| | | |
| | | for (int i=0; i < rdnTypes.length; i++) |
| | | int numAVAs = rdn.getNumValues(); |
| | | for (int i=0; i < numAVAs; i++) |
| | | { |
| | | AttributeType t = rdnTypes[i]; |
| | | AttributeValue v = rdnValues[i]; |
| | | |
| | | AttributeType t = rdn.getAttributeType(i); |
| | | AttributeValue v = rdn.getAttributeValue(i); |
| | | String n = rdn.getAttributeName(i); |
| | | if (t.isOperational()) |
| | | { |
| | | List<Attribute> attrList = operationalAttributes.get(t); |
| | |
| | | valueList.add(v); |
| | | |
| | | attrList = new ArrayList<Attribute>(); |
| | | attrList.add(new Attribute(t, rdnNames[i], valueList)); |
| | | attrList.add(new Attribute(t, n, valueList)); |
| | | |
| | | operationalAttributes.put(t, attrList); |
| | | } |
| | |
| | | |
| | | int msgID = MSGID_ADD_MISSING_RDN_ATTRIBUTE; |
| | | appendErrorMessage(getMessage(msgID, String.valueOf(entryDN), |
| | | rdnNames[i])); |
| | | n)); |
| | | |
| | | break addProcessing; |
| | | } |
| | |
| | | LinkedHashSet<AttributeValue> valueList = |
| | | new LinkedHashSet<AttributeValue>(1); |
| | | valueList.add(v); |
| | | attrList.add(new Attribute(t, rdnNames[i], valueList)); |
| | | attrList.add(new Attribute(t, n, valueList)); |
| | | } |
| | | else |
| | | { |
| | |
| | | |
| | | int msgID = MSGID_ADD_MISSING_RDN_ATTRIBUTE; |
| | | appendErrorMessage(getMessage(msgID, String.valueOf(entryDN), |
| | | rdnNames[i])); |
| | | n)); |
| | | |
| | | break addProcessing; |
| | | } |
| | |
| | | valueList.add(v); |
| | | |
| | | attrList = new ArrayList<Attribute>(); |
| | | attrList.add(new Attribute(t, rdnNames[i], valueList)); |
| | | attrList.add(new Attribute(t, n, valueList)); |
| | | |
| | | userAttributes.put(t, attrList); |
| | | } |
| | |
| | | |
| | | int msgID = MSGID_ADD_MISSING_RDN_ATTRIBUTE; |
| | | appendErrorMessage(getMessage(msgID, String.valueOf(entryDN), |
| | | rdnNames[i])); |
| | | n)); |
| | | |
| | | break addProcessing; |
| | | } |
| | |
| | | LinkedHashSet<AttributeValue> valueList = |
| | | new LinkedHashSet<AttributeValue>(1); |
| | | valueList.add(v); |
| | | attrList.add(new Attribute(t, rdnNames[i], valueList)); |
| | | attrList.add(new Attribute(t, n, valueList)); |
| | | } |
| | | else |
| | | { |
| | |
| | | |
| | | int msgID = MSGID_ADD_MISSING_RDN_ATTRIBUTE; |
| | | appendErrorMessage(getMessage(msgID, String.valueOf(entryDN), |
| | | rdnNames[i])); |
| | | n)); |
| | | |
| | | break addProcessing; |
| | | } |
| | |
| | | try |
| | | { |
| | | ConfigEntry parentEntry = |
| | | DirectoryServer.getConfigEntry(configEntryDN.getParent()); |
| | | DirectoryServer |
| | | .getConfigEntry(configEntryDN.getParentDNInSuffix()); |
| | | if (parentEntry != null) |
| | | { |
| | | parentEntry.registerAddListener(this); |
| | |
| | | configEntry.registerChangeListener(this); |
| | | try |
| | | { |
| | | DN parentDN = configEntryDN.getParent(); |
| | | DN parentDN = configEntryDN.getParentDNInSuffix(); |
| | | ConfigEntry parentEntry = DirectoryServer.getConfigEntry(parentDN); |
| | | if (parentEntry != null) |
| | | { |
| | |
| | | configEntry.registerChangeListener(this); |
| | | try |
| | | { |
| | | DN parentDN = configEntry.getDN().getParent(); |
| | | DN parentDN = configEntry.getDN().getParentDNInSuffix(); |
| | | ConfigEntry parentEntry = DirectoryServer.getConfigEntry(parentDN); |
| | | if (parentEntry != null) |
| | | { |
| | |
| | | String.valueOf(entryDN))); |
| | | |
| | | // See if one of the entry's ancestors exists. |
| | | DN parentDN = entryDN.getParent(); |
| | | DN parentDN = entryDN.getParentDNInSuffix(); |
| | | while (parentDN != null) |
| | | { |
| | | try |
| | |
| | | break; |
| | | } |
| | | |
| | | parentDN = parentDN.getParent(); |
| | | parentDN = parentDN.getParentDNInSuffix(); |
| | | } |
| | | |
| | | break compareProcessing; |
| | |
| | | |
| | | try |
| | | { |
| | | DN parentDN = entryDN.getParent(); |
| | | DN parentDN = entryDN.getParentDNInSuffix(); |
| | | while (parentDN != null) |
| | | { |
| | | if (DirectoryServer.entryExists(parentDN)) |
| | |
| | | break; |
| | | } |
| | | |
| | | parentDN = parentDN.getParent(); |
| | | parentDN = parentDN.getParentDNInSuffix(); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | |
| | | import java.io.FileOutputStream; |
| | | import java.io.PrintStream; |
| | | import java.net.InetAddress; |
| | | import java.util.ArrayList; |
| | | import java.util.Collections; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.LinkedHashSet; |
| | |
| | | throw new InitializationException(msgID, message, e); |
| | | } |
| | | |
| | | DN[] baseDNs = { new DN(new RDN[0]) }; |
| | | DN[] baseDNs = { DN.nullDN() }; |
| | | rootDSEBackend = new RootDSEBackend(); |
| | | rootDSEBackend.initializeBackend(rootDSEConfigEntry, baseDNs); |
| | | } |
| | |
| | | |
| | | while (backend == null) |
| | | { |
| | | dn = dn.getParent(); |
| | | dn = dn.getParentDNInSuffix(); |
| | | if (dn == null) |
| | | { |
| | | break; |
| | |
| | | } |
| | | |
| | | boolean found = false; |
| | | DN parentDN = suffixDN.getParent(); |
| | | DN parentDN = suffixDN.getParentDNInSuffix(); |
| | | while (parentDN != null) |
| | | { |
| | | b = directoryServer.suffixes.get(suffixDN); |
| | |
| | | } |
| | | } |
| | | |
| | | parentDN = parentDN.getParent(); |
| | | parentDN = parentDN.getParentDNInSuffix(); |
| | | } |
| | | |
| | | |
| | |
| | | throw new ConfigException(msgID, message); |
| | | } |
| | | |
| | | DN parentDN = suffixDN.getParent(); |
| | | DN parentDN = suffixDN.getParentDNInSuffix(); |
| | | while (parentDN != null) |
| | | { |
| | | b = directoryServer.suffixes.get(suffixDN); |
| | |
| | | throw new ConfigException(msgID, message); |
| | | } |
| | | |
| | | parentDN = suffixDN.getParent(); |
| | | parentDN = suffixDN.getParentDNInSuffix(); |
| | | } |
| | | } |
| | | |
| | |
| | | throw new ConfigException(msgID, message); |
| | | } |
| | | |
| | | DN parentDN = suffixDN.getParent(); |
| | | DN parentDN = suffixDN.getParentDNInSuffix(); |
| | | while (parentDN != null) |
| | | { |
| | | b = directoryServer.privateSuffixes.get(suffixDN); |
| | |
| | | } |
| | | } |
| | | |
| | | parentDN = suffixDN.getParent(); |
| | | parentDN = suffixDN.getParentDNInSuffix(); |
| | | } |
| | | |
| | | |
| | |
| | | return; |
| | | } |
| | | |
| | | DN parentDN = suffixDN.getParent(); |
| | | DN parentDN = suffixDN.getParentDNInSuffix(); |
| | | while (parentDN != null) |
| | | { |
| | | b = directoryServer.suffixes.get(parentDN); |
| | |
| | | return; |
| | | } |
| | | |
| | | DN parentDN = suffixDN.getParent(); |
| | | DN parentDN = suffixDN.getParentDNInSuffix(); |
| | | while (parentDN != null) |
| | | { |
| | | b = directoryServer.privateSuffixes.get(parentDN); |
| | |
| | | { |
| | | // The config handler hasn't been initialized yet. Just return the DN |
| | | // of the root DSE. |
| | | return new DN(new ArrayList<RDN>(0)); |
| | | return DN.nullDN(); |
| | | } |
| | | |
| | | return configHandler.getConfigRootEntry().getDN(); |
| | |
| | | |
| | | // This could theoretically happen if an alert needs to be sent before the |
| | | // configuration is initialized. In that case, just return an empty DN. |
| | | return new DN(new ArrayList<RDN>(0)); |
| | | return DN.nullDN(); |
| | | } |
| | | } |
| | | |
| | |
| | | // Cannot reach this point. |
| | | throw new RuntimeException(); |
| | | } |
| | | RDN[] baseRDNs = monitorRootDN.getRDNComponents(); |
| | | RDN[] rdns = new RDN[baseRDNs.length+1]; |
| | | rdns[0] = new RDN(cnType, new AttributeValue(cnType, monitorName)); |
| | | System.arraycopy(baseRDNs, 0, rdns, 1, baseRDNs.length); |
| | | return new DN(rdns); |
| | | |
| | | RDN rdn = RDN.create(cnType, new AttributeValue(cnType, monitorName)); |
| | | return monitorRootDN.concat(rdn); |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | try |
| | | { |
| | | ConfigEntry parentEntry = |
| | | DirectoryServer.getConfigEntry(configEntryDN.getParent()); |
| | | ConfigEntry parentEntry = DirectoryServer |
| | | .getConfigEntry(configEntryDN.getParentDNInSuffix()); |
| | | if (parentEntry != null) |
| | | { |
| | | parentEntry.registerAddListener(this); |
| | |
| | | configEntry.registerChangeListener(this); |
| | | try |
| | | { |
| | | DN parentDN = configEntryDN.getParent(); |
| | | DN parentDN = configEntryDN.getParentDNInSuffix(); |
| | | ConfigEntry parentEntry = DirectoryServer.getConfigEntry(parentDN); |
| | | if (parentEntry != null) |
| | | { |
| | |
| | | |
| | | try |
| | | { |
| | | ConfigEntry parentEntry = |
| | | DirectoryServer.getConfigEntry(configEntryDN.getParent()); |
| | | ConfigEntry parentEntry = DirectoryServer |
| | | .getConfigEntry(configEntryDN.getParentDNInSuffix()); |
| | | if (parentEntry != null) |
| | | { |
| | | parentEntry.registerAddListener(this); |
| | |
| | | configEntry.registerChangeListener(this); |
| | | try |
| | | { |
| | | DN parentDN = configEntryDN.getParent(); |
| | | DN parentDN = configEntryDN.getParentDNInSuffix(); |
| | | ConfigEntry parentEntry = DirectoryServer.getConfigEntry(parentDN); |
| | | if (parentEntry != null) |
| | | { |
| | |
| | | configEntry.registerChangeListener(this); |
| | | try |
| | | { |
| | | DN parentDN = configEntry.getDN().getParent(); |
| | | DN parentDN = configEntry.getDN().getParentDNInSuffix(); |
| | | ConfigEntry parentEntry = DirectoryServer.getConfigEntry(parentDN); |
| | | if (parentEntry != null) |
| | | { |
| | |
| | | DN parentDN; |
| | | if (newSuperior == null) |
| | | { |
| | | parentDN = entryDN.getParent(); |
| | | parentDN = entryDN.getParentDNInSuffix(); |
| | | } |
| | | else |
| | | { |
| | |
| | | break modifyDNProcessing; |
| | | } |
| | | |
| | | RDN[] parentComponents = parentDN.getRDNComponents(); |
| | | RDN[] newComponents = new RDN[parentComponents.length+1]; |
| | | System.arraycopy(parentComponents, 0, newComponents, 1, |
| | | parentComponents.length); |
| | | newComponents[0] = newRDN; |
| | | |
| | | DN newDN = new DN(newComponents); |
| | | |
| | | DN newDN = parentDN.concat(newRDN); |
| | | |
| | | // Get the backend for the current entry, and the backend for the new |
| | | // entry. If either is null, or if they are different, then fail. |
| | |
| | | if (currentEntry == null) |
| | | { |
| | | // See if one of the entry's ancestors exists. |
| | | parentDN = entryDN.getParent(); |
| | | parentDN = entryDN.getParentDNInSuffix(); |
| | | while (parentDN != null) |
| | | { |
| | | try |
| | |
| | | break; |
| | | } |
| | | |
| | | parentDN = parentDN.getParent(); |
| | | parentDN = parentDN.getParentDNInSuffix(); |
| | | } |
| | | |
| | | setResultCode(ResultCode.NO_SUCH_OBJECT); |
| | |
| | | { |
| | | LinkedHashSet<AttributeValue> valueSet = |
| | | new LinkedHashSet<AttributeValue>(1); |
| | | valueSet.add(currentRDN.getAttributeValues()[i]); |
| | | valueSet.add(currentRDN.getAttributeValue(i)); |
| | | |
| | | Attribute a = new Attribute(currentRDN.getAttributeTypes()[i], |
| | | currentRDN.getAttributeNames()[i], |
| | | Attribute a = new Attribute(currentRDN.getAttributeType(i), |
| | | currentRDN.getAttributeName(i), |
| | | valueSet); |
| | | |
| | | // If the associated attribute type is marked NO-USER-MODIFICATION, |
| | |
| | | { |
| | | LinkedHashSet<AttributeValue> valueSet = |
| | | new LinkedHashSet<AttributeValue>(1); |
| | | valueSet.add(newRDN.getAttributeValues()[i]); |
| | | valueSet.add(newRDN.getAttributeValue(i)); |
| | | |
| | | Attribute a = new Attribute(newRDN.getAttributeTypes()[i], |
| | | newRDN.getAttributeNames()[i], |
| | | Attribute a = new Attribute(newRDN.getAttributeType(i), |
| | | newRDN.getAttributeName(i), |
| | | valueSet); |
| | | |
| | | LinkedList<AttributeValue> duplicateValues = |
| | |
| | | String.valueOf(entryDN))); |
| | | |
| | | // See if one of the entry's ancestors exists. |
| | | DN parentDN = entryDN.getParent(); |
| | | DN parentDN = entryDN.getParentDNInSuffix(); |
| | | while (parentDN != null) |
| | | { |
| | | try |
| | |
| | | break; |
| | | } |
| | | |
| | | parentDN = parentDN.getParent(); |
| | | parentDN = parentDN.getParentDNInSuffix(); |
| | | } |
| | | |
| | | break modifyProcessing; |
| | |
| | | import org.opends.server.types.DN; |
| | | import org.opends.server.types.DirectoryException; |
| | | import org.opends.server.types.OperationType; |
| | | import org.opends.server.types.RDN; |
| | | import org.opends.server.types.ResultCode; |
| | | import org.opends.server.types.operation.PostOperationOperation; |
| | | import org.opends.server.types.operation.PostResponseOperation; |
| | |
| | | AuthenticationInfo authInfo = clientConnection.getAuthenticationInfo(); |
| | | if (authInfo == null) |
| | | { |
| | | return new DN(new RDN[0]); |
| | | return DN.nullDN(); |
| | | } |
| | | else |
| | | { |
| | |
| | | } |
| | | break; |
| | | case SINGLE_LEVEL: |
| | | if (! baseDN.equals(entry.getDN().getParent())) |
| | | if (! baseDN.equals(entry.getDN().getParentDNInSuffix())) |
| | | { |
| | | return; |
| | | } |
| | |
| | | } |
| | | break; |
| | | case SINGLE_LEVEL: |
| | | if (! baseDN.equals(entry.getDN().getParent())) |
| | | if (! baseDN.equals(entry.getDN().getParentDNInSuffix())) |
| | | { |
| | | return; |
| | | } |
| | |
| | | } |
| | | break; |
| | | case SINGLE_LEVEL: |
| | | if (! baseDN.equals(oldEntry.getDN().getParent())) |
| | | if (! baseDN.equals(oldEntry.getDN().getParentDNInSuffix())) |
| | | { |
| | | return; |
| | | } |
| | |
| | | |
| | | break; |
| | | case SINGLE_LEVEL: |
| | | oldMatches = baseDN.equals(oldEntry.getDN().getParent()); |
| | | newMatches = baseDN.equals(newEntry.getDN().getParent()); |
| | | oldMatches = baseDN.equals(oldEntry.getDN().getParentDNInSuffix()); |
| | | newMatches = baseDN.equals(newEntry.getDN().getParentDNInSuffix()); |
| | | |
| | | if (! (oldMatches || newMatches)) |
| | | { |
| | |
| | | public RFC3672SubtreeSpecification(DN rootDN, DN relativeBaseDN, |
| | | int minimumDepth, int maximumDepth, Iterable<DN> chopBefore, |
| | | Iterable<DN> chopAfter, Refinement refinements) { |
| | | super(relativeBaseDN == null ? rootDN : new DN(rootDN, relativeBaseDN), |
| | | super(relativeBaseDN == null ? rootDN : rootDN.concat(relativeBaseDN), |
| | | minimumDepth, maximumDepth, chopBefore, chopAfter); |
| | | |
| | | assert debugConstructor(CLASS_NAME); |
| | |
| | | public RelativeSubtreeSpecification(DN rootDN, DN relativeBaseDN, |
| | | int minimumDepth, int maximumDepth, Iterable<DN> chopBefore, |
| | | Iterable<DN> chopAfter, SearchFilter filter) { |
| | | super(relativeBaseDN == null ? rootDN : new DN(rootDN, relativeBaseDN), |
| | | super(relativeBaseDN == null ? rootDN : rootDN.concat(relativeBaseDN), |
| | | minimumDepth, maximumDepth, chopBefore, chopAfter); |
| | | |
| | | assert debugConstructor(CLASS_NAME); |
| | |
| | | this.chopBefore = new TreeMap<DN, DN>(); |
| | | |
| | | for (DN localName : chopBefore) { |
| | | this.chopBefore.put(new DN(baseDN, localName), localName); |
| | | this.chopBefore.put(baseDN.concat(localName), localName); |
| | | } |
| | | } else { |
| | | // No chop before specifications. |
| | |
| | | this.chopAfter = new TreeMap<DN, DN>(); |
| | | |
| | | for (DN localName : chopAfter) { |
| | | this.chopAfter.put(new DN(baseDN, localName), localName); |
| | | this.chopAfter.put(baseDN.concat(localName), localName); |
| | | } |
| | | } else { |
| | | // No chop after specifications. |
| | |
| | | } |
| | | |
| | | // Check minimum and maximum depths. |
| | | int baseRDNCount = baseDN.getRDNComponents().length; |
| | | int baseRDNCount = baseDN.getNumComponents(); |
| | | |
| | | if (minimumDepth > 0) { |
| | | int entryRDNCount = dn.getRDNComponents().length; |
| | | int entryRDNCount = dn.getNumComponents(); |
| | | |
| | | if (entryRDNCount - baseRDNCount < minimumDepth) { |
| | | return false; |
| | |
| | | } |
| | | |
| | | if (maximumDepth >= 0) { |
| | | int entryRDNCount = dn.getRDNComponents().length; |
| | | int entryRDNCount = dn.getNumComponents(); |
| | | |
| | | if (entryRDNCount - baseRDNCount > maximumDepth) { |
| | | return false; |
| | |
| | | |
| | | try |
| | | { |
| | | ConfigEntry parentEntry = |
| | | DirectoryServer.getConfigEntry(configEntryDN.getParent()); |
| | | ConfigEntry parentEntry = DirectoryServer |
| | | .getConfigEntry(configEntryDN.getParentDNInSuffix()); |
| | | if (parentEntry != null) |
| | | { |
| | | parentEntry.registerAddListener(this); |
| | |
| | | configEntry.registerChangeListener(this); |
| | | try |
| | | { |
| | | DN parentDN = configEntryDN.getParent(); |
| | | DN parentDN = configEntryDN.getParentDNInSuffix(); |
| | | ConfigEntry parentEntry = DirectoryServer.getConfigEntry(parentDN); |
| | | if (parentEntry != null) |
| | | { |
| | |
| | | configEntry.registerChangeListener(this); |
| | | try |
| | | { |
| | | DN parentDN = configEntry.getDN().getParent(); |
| | | DN parentDN = configEntry.getDN().getParentDNInSuffix(); |
| | | ConfigEntry parentEntry = DirectoryServer.getConfigEntry(parentDN); |
| | | if (parentEntry != null) |
| | | { |
| | |
| | | String.valueOf(entryDN))); |
| | | |
| | | // See if one of the entry's ancestors exists. |
| | | DN parentDN = entryDN.getParent(); |
| | | DN parentDN = entryDN.getParentDNInSuffix(); |
| | | while (parentDN != null) |
| | | { |
| | | try |
| | |
| | | break; |
| | | } |
| | | |
| | | parentDN = parentDN.getParent(); |
| | | parentDN = parentDN.getParentDNInSuffix(); |
| | | } |
| | | |
| | | return null; |
| | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the string that will be used if an attempt is made to |
| | | * decode a string as an RDN but that string contained an unexpected comma or |
| | | * semicolon. This takes two arguments, which are the RDN string to decode |
| | | * and the position of the illegal comma or semicolon. |
| | | * The message ID for the string that will be used if an attempt is |
| | | * made to decode a string as an RDN but that string contained an |
| | | * unexpected plus, comma, or semicolon. This takes two arguments, |
| | | * which are the RDN string to decode and the position of the |
| | | * illegal plus, comma, or semicolon. |
| | | */ |
| | | public static final int MSGID_RDN_UNEXPECTED_COMMA = |
| | | CATEGORY_MASK_CORE | SEVERITY_MASK_MILD_ERROR | 174; |
| | |
| | | registerMessage(MSGID_RDN_UNEXPECTED_COMMA, |
| | | "Unable to decode the provided string \"%s\" as a " + |
| | | "relative distinguished name because it contained an " + |
| | | "unexpected comma or semicolon at position %d, which is " + |
| | | "not allowed in an RDN."); |
| | | "unexpected plus, comma, or semicolon at position %d, "+ |
| | | "which is not allowed in an RDN."); |
| | | registerMessage(MSGID_RDN_ILLEGAL_CHARACTER, |
| | | "Unable to decode the provided string \"%s\" as a " + |
| | | "relative distinguished name because an illegal " + |
| | |
| | | // in the current entry. |
| | | // Always return true as the check will be performed by the |
| | | // hasAcceptableConfiguration call |
| | | if (configEntry.getDN().compareTo(configEntryDN) == 0) |
| | | if (configEntry.getDN().equals(configEntryDN)) |
| | | { |
| | | return true; |
| | | } |
| | |
| | | // |
| | | // We are checking first if we are dealing with a change |
| | | // in the current entry. |
| | | if (configEntry.getDN().compareTo(configEntryDN) == 0) |
| | | if (configEntry.getDN().equals(configEntryDN)) |
| | | { |
| | | ArrayList<String> messages = new ArrayList<String>(); |
| | | return new ConfigChangeResult(ResultCode.SUCCESS, false, messages); |
| | |
| | | import org.opends.server.types.ByteString; |
| | | import org.opends.server.types.DirectoryException; |
| | | import org.opends.server.types.InitializationException; |
| | | import org.opends.server.util.StaticUtils; |
| | | |
| | | import static org.opends.server.loggers.Debug.*; |
| | | import static org.opends.server.messages.MessageHandler.*; |
| | | import static org.opends.server.messages.SchemaMessages.*; |
| | | import static org.opends.server.schema.SchemaConstants.*; |
| | | import static org.opends.server.util.StaticUtils.*; |
| | | |
| | | |
| | | |
| | |
| | | assert debugEnter(CLASS_NAME, "compareValues", String.valueOf(b1), |
| | | String.valueOf(b2)); |
| | | |
| | | int minLength = Math.min(b1.length, b2.length); |
| | | |
| | | for (int i=0; i < minLength; i++) |
| | | { |
| | | if (b1[i] == b2[i]) |
| | | { |
| | | continue; |
| | | } |
| | | else if (b1[i] < b2[i]) |
| | | { |
| | | return -1; |
| | | } |
| | | else if (b1[i] > b2[i]) |
| | | { |
| | | return 1; |
| | | } |
| | | } |
| | | |
| | | if (b1.length == b2.length) |
| | | { |
| | | return 0; |
| | | } |
| | | else if (b1.length < b2.length) |
| | | { |
| | | return -1; |
| | | } |
| | | else |
| | | { |
| | | return 1; |
| | | } |
| | | return StaticUtils.compare(b1, b2); |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | // Use the subtree specification code to make this determination. |
| | | try { |
| | | RFC3672SubtreeSpecification.valueOf(new DN(), value.stringValue()); |
| | | RFC3672SubtreeSpecification.valueOf(DN.nullDN(), value.stringValue()); |
| | | |
| | | return true; |
| | | } catch (DirectoryException e) { |
| | |
| | | |
| | | // Use the subtree specification code to make this determination. |
| | | try { |
| | | RelativeSubtreeSpecification.valueOf(new DN(), value.stringValue()); |
| | | RelativeSubtreeSpecification.valueOf(DN.nullDN(), value.stringValue()); |
| | | |
| | | return true; |
| | | } catch (DirectoryException e) { |
| | |
| | | do |
| | | { |
| | | domain = domains.get(temp); |
| | | temp = temp.getParent(); |
| | | temp = temp.getParentDNInSuffix(); |
| | | if (temp == null) |
| | | { |
| | | break; |
| | |
| | | { |
| | | AddContext ctx = new AddContext(generateChangeNumber(addOperation), |
| | | Historical.getEntryUuid(addOperation), |
| | | findEntryId(addOperation.getEntryDN().getParent())); |
| | | findEntryId(addOperation.getEntryDN().getParentDNInSuffix())); |
| | | |
| | | addOperation.setAttachment(SYNCHROCONTEXT, ctx); |
| | | } |
| | |
| | | throw new Exception("operation parameters are invalid"); |
| | | } |
| | | |
| | | RDN[] parentComponents = parentDN.getRDNComponents(); |
| | | RDN[] newComponents = new RDN[parentComponents.length+1]; |
| | | System.arraycopy(parentComponents, 0, newComponents, 1, |
| | | parentComponents.length); |
| | | newComponents[0] = newRDN; |
| | | |
| | | DN newDN = new DN(newComponents); |
| | | DN newDN = parentDN.concat(newRDN); |
| | | |
| | | // get the current DN of this entry in the database. |
| | | DN currentDN = findEntryDN(entryUid); |
| | |
| | | import org.opends.server.types.AttributeType; |
| | | import org.opends.server.types.AttributeValue; |
| | | import org.opends.server.types.DN; |
| | | import org.opends.server.types.DNComparator; |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.ExistingFileBehavior; |
| | | import org.opends.server.types.LDIFImportConfig; |
| | |
| | | return 1; |
| | | } |
| | | |
| | | DNComparator comparator = new DNComparator(); |
| | | TreeMap<DN,Entry> sourceMap = new TreeMap<DN,Entry>(comparator); |
| | | TreeMap<DN,Entry> sourceMap = new TreeMap<DN,Entry>(); |
| | | try |
| | | { |
| | | while (true) |
| | |
| | | return 1; |
| | | } |
| | | |
| | | TreeMap<DN,Entry> targetMap = new TreeMap<DN,Entry>(comparator); |
| | | TreeMap<DN,Entry> targetMap = new TreeMap<DN,Entry>(); |
| | | try |
| | | { |
| | | while (true) |
| | |
| | | |
| | | while (true) |
| | | { |
| | | // Use the DN comparator to determine the relative order of the |
| | | // Compare the DNs to determine the relative order of the |
| | | // entries. |
| | | int comparatorValue = comparator.compare(sourceDN, targetDN); |
| | | int comparatorValue = sourceDN.compareTo(targetDN); |
| | | if (comparatorValue < 0) |
| | | { |
| | | // The source entry should be before the target entry, which means |
| | |
| | | import org.opends.server.types.Attribute; |
| | | import org.opends.server.types.AttributeType; |
| | | import org.opends.server.types.AttributeValue; |
| | | import org.opends.server.types.DNComparator; |
| | | import org.opends.server.types.DirectoryException; |
| | | import org.opends.server.types.DN; |
| | | import org.opends.server.types.Entry; |
| | |
| | | throws IOException, LDIFException |
| | | { |
| | | // Read the changes into memory. |
| | | DNComparator comparator = new DNComparator(); |
| | | TreeMap<DN,AddChangeRecordEntry> adds = |
| | | new TreeMap<DN,AddChangeRecordEntry>(comparator); |
| | | new TreeMap<DN,AddChangeRecordEntry>(); |
| | | TreeMap<DN,Entry> ldifEntries = |
| | | new TreeMap<DN,Entry>(comparator); |
| | | new TreeMap<DN,Entry>(); |
| | | HashMap<DN,DeleteChangeRecordEntry> deletes = |
| | | new HashMap<DN,DeleteChangeRecordEntry>(); |
| | | HashMap<DN,LinkedList<Modification>> modifications = |
| | |
| | | } |
| | | else |
| | | { |
| | | baseDNs.add(new DN()); |
| | | baseDNs.add(DN.nullDN()); |
| | | } |
| | | |
| | | |
| | |
| | | |
| | | import org.opends.server.types.DN; |
| | | import org.opends.server.types.InitializationException; |
| | | import org.opends.server.types.RDN; |
| | | |
| | | import static org.opends.server.messages.MessageHandler.*; |
| | | import static org.opends.server.messages.ToolMessages.*; |
| | |
| | | } |
| | | else if (numComponents > 0) |
| | | { |
| | | RDN[] rdnComps = dn.getRDNComponents(); |
| | | int count = Math.min(numComponents, rdnComps.length); |
| | | int count = Math.min(numComponents, dn.getNumComponents()); |
| | | |
| | | rdnComps[0].toString(templateValue.getValue()); |
| | | dn.getRDN(0).toString(templateValue.getValue()); |
| | | for (int i=1; i < count; i++) |
| | | { |
| | | templateValue.append(","); |
| | | rdnComps[i].toString(templateValue.getValue()); |
| | | dn.getRDN(i).toString(templateValue.getValue()); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | RDN[] rdnComps = dn.getRDNComponents(); |
| | | int count = Math.min(Math.abs(numComponents), rdnComps.length); |
| | | int sz = dn.getNumComponents(); |
| | | int count = Math.min(Math.abs(numComponents), sz); |
| | | |
| | | rdnComps[rdnComps.length-count].toString(templateValue.getValue()); |
| | | dn.getRDN(sz - count).toString(templateValue.getValue()); |
| | | for (int i=1; i < count; i++) |
| | | { |
| | | templateValue.append(","); |
| | | rdnComps[rdnComps.length-count+i].toString(templateValue.getValue()); |
| | | dn.getRDN(sz - count + i).toString(templateValue.getValue()); |
| | | } |
| | | } |
| | | |
| | |
| | | */ |
| | | public DN getDN() |
| | | { |
| | | if (dn == null) |
| | | { |
| | | AttributeType[] rdnAttributes = template.getRDNAttributes(); |
| | | String[] rdnNames = new String[rdnAttributes.length]; |
| | | AttributeValue[] rdnValues = new AttributeValue[rdnAttributes.length]; |
| | | if (dn == null) { |
| | | RDN.Builder builder = RDN.createBuilder(); |
| | | |
| | | for (int i=0; i < rdnAttributes.length; i++) |
| | | { |
| | | TemplateValue v = getValue(rdnAttributes[i]); |
| | | if (v == null) |
| | | { |
| | | for (AttributeType type : template.getRDNAttributes()) { |
| | | TemplateValue v = getValue(type); |
| | | if (v == null) { |
| | | return null; |
| | | } |
| | | |
| | | rdnNames[i] = rdnAttributes[i].getNameOrOID(); |
| | | rdnValues[i] = new AttributeValue(rdnAttributes[i], |
| | | AttributeValue value = new AttributeValue(type, |
| | | v.getValue().toString()); |
| | | |
| | | builder.append(type, value); |
| | | } |
| | | |
| | | RDN[] parentComponents = parentDN.getRDNComponents(); |
| | | RDN[] dnComponents = new RDN[parentComponents.length+1]; |
| | | |
| | | dnComponents[0] = new RDN(rdnAttributes, rdnNames, rdnValues); |
| | | System.arraycopy(parentComponents, 0, dnComponents, 1, |
| | | parentComponents.length); |
| | | |
| | | dn = new DN(dnComponents); |
| | | dn = parentDN.concat(builder.getInstance()); |
| | | } |
| | | |
| | | return dn; |
| | |
| | | |
| | | import org.opends.server.types.DN; |
| | | import org.opends.server.types.InitializationException; |
| | | import org.opends.server.types.RDN; |
| | | |
| | | import static org.opends.server.messages.MessageHandler.*; |
| | | import static org.opends.server.messages.ToolMessages.*; |
| | |
| | | |
| | | if (numComponents == 0) |
| | | { |
| | | RDN[] rdnComps = dn.getRDNComponents(); |
| | | |
| | | rdnComps[0].toString(templateValue.getValue()); |
| | | for (int i=1; i < rdnComps.length; i++) |
| | | dn.getRDN(0).toString(templateValue.getValue()); |
| | | for (int i=1; i < dn.getNumComponents(); i++) |
| | | { |
| | | templateValue.append("_"); |
| | | rdnComps[i].toString(templateValue.getValue()); |
| | | dn.getRDN(i).toString(templateValue.getValue()); |
| | | } |
| | | } |
| | | else if (numComponents > 0) |
| | | { |
| | | RDN[] rdnComps = dn.getRDNComponents(); |
| | | int count = Math.min(numComponents, rdnComps.length); |
| | | int count = Math.min(numComponents, dn.getNumComponents()); |
| | | |
| | | rdnComps[0].toString(templateValue.getValue()); |
| | | dn.getRDN(0).toString(templateValue.getValue()); |
| | | for (int i=1; i < count; i++) |
| | | { |
| | | templateValue.append("_"); |
| | | rdnComps[i].toString(templateValue.getValue()); |
| | | dn.getRDN(i).toString(templateValue.getValue()); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | RDN[] rdnComps = dn.getRDNComponents(); |
| | | int count = Math.min(Math.abs(numComponents), rdnComps.length); |
| | | int sz = dn.getNumComponents(); |
| | | int count = Math.min(Math.abs(numComponents), sz); |
| | | |
| | | rdnComps[rdnComps.length-count].toString(templateValue.getValue()); |
| | | for (int i=1; i < count; i++) |
| | | { |
| | | dn.getRDN(sz - count).toString(templateValue.getValue()); |
| | | for (int i = 1; i < count; i++) { |
| | | templateValue.append("_"); |
| | | rdnComps[rdnComps.length-count+i].toString(templateValue.getValue()); |
| | | dn.getRDN(sz - count + i).toString(templateValue.getValue()); |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | import org.opends.server.types.DN; |
| | | import org.opends.server.types.InitializationException; |
| | | import org.opends.server.types.RDN; |
| | | |
| | | import static org.opends.server.messages.MessageHandler.*; |
| | | import static org.opends.server.messages.ToolMessages.*; |
| | |
| | | return TagResult.SUCCESS_RESULT; |
| | | } |
| | | |
| | | RDN[] rdnComps = parentDN.getRDNComponents(); |
| | | rdnComps[0].toString(templateValue.getValue()); |
| | | for (int i=1; i < rdnComps.length; i++) |
| | | parentDN.getRDN(0).toString(templateValue.getValue()); |
| | | for (int i=1; i < parentDN.getNumComponents(); i++) |
| | | { |
| | | templateValue.append("_"); |
| | | rdnComps[i].toString(templateValue.getValue()); |
| | | parentDN.getRDN(i).toString(templateValue.getValue()); |
| | | } |
| | | |
| | | return TagResult.SUCCESS_RESULT; |
| | |
| | | import org.opends.server.protocols.asn1.ASN1OctetString; |
| | | |
| | | import static org.opends.server.loggers.Debug.*; |
| | | import static org.opends.server.util.StaticUtils.*; |
| | | |
| | | |
| | | |
| | |
| | | |
| | | |
| | | /** |
| | | * Retrieves a string representation of the user-defined form of |
| | | * this attribute value in a form suitable for use in a DN. |
| | | * |
| | | * @return A string representation of the user-defined form of this |
| | | * attribute value in a form suitable for use in a DN. |
| | | */ |
| | | public String getDNStringValue() |
| | | { |
| | | assert debugEnter(CLASS_NAME, "getDNStringValue"); |
| | | |
| | | return getDNValue(getStringValue()); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the normalized form of this attribute value. |
| | | * |
| | | * @return The normalized form of this attribute value. |
| | |
| | | |
| | | |
| | | /** |
| | | * Retrieves a string representation of the normalized form of this |
| | | * attribute value in a form suitable for use in a DN. |
| | | * |
| | | * @return A string representation of the normalized form of this |
| | | * attribute value in a form suitable for use in a DN. |
| | | * |
| | | * @throws DirectoryException If an error occurs while trying to |
| | | * normalize the value (e.g., if it is |
| | | * not acceptable for use with the |
| | | * associated equality matching rule). |
| | | */ |
| | | public String getNormalizedDNStringValue() |
| | | throws DirectoryException |
| | | { |
| | | assert debugEnter(CLASS_NAME, "getNormalizedDNStringValue"); |
| | | |
| | | return getDNValue(getNormalizedStringValue()); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves a version of the provided value in a form that is |
| | | * properly escaped for use in a DN or RDN. |
| | | * |
| | | * @param value The value to be represented in a DN-safe form. |
| | | * |
| | | * @return A version of the provided value in a form that is |
| | | * properly escaped for use in a DN or RDN. |
| | | */ |
| | | private static String getDNValue(String value) |
| | | { |
| | | assert debugEnter(CLASS_NAME, "getDNValue", |
| | | String.valueOf(value)); |
| | | |
| | | if ((value == null) || (value.length() == 0)) |
| | | { |
| | | return ""; |
| | | } |
| | | |
| | | StringBuilder buffer = new StringBuilder(value); |
| | | |
| | | int length = buffer.length(); |
| | | for (int i=0; i < length; i++) |
| | | { |
| | | char c = buffer.charAt(i); |
| | | |
| | | if ((c < ' ') || (c > '~')) |
| | | { |
| | | buffer.deleteCharAt(i); |
| | | length -= 1; |
| | | |
| | | for (byte b : getBytes(String.valueOf(c))) |
| | | { |
| | | buffer.insert(i++, "\\"); |
| | | buffer.insert(i++, byteToLowerHex(b)); |
| | | i++; |
| | | |
| | | length += 3; |
| | | } |
| | | |
| | | i -= 1; |
| | | } |
| | | else |
| | | { |
| | | switch (buffer.charAt(i)) |
| | | { |
| | | case ',': |
| | | case '+': |
| | | case '"': |
| | | case '\\': |
| | | case '<': |
| | | case '>': |
| | | case ';': |
| | | buffer.insert(i++, '\\'); |
| | | length++; |
| | | } |
| | | } |
| | | } |
| | | |
| | | char c = buffer.charAt(0); |
| | | if ((c == ' ') || (c == '#')) |
| | | { |
| | | buffer.insert(0, '\\'); |
| | | length++; |
| | | } |
| | | |
| | | if (buffer.charAt(length-1) == ' ') |
| | | { |
| | | buffer.insert(length-1, '\\'); |
| | | length++; |
| | | } |
| | | |
| | | return buffer.toString(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Determines whether this attribute value is equal to the provided |
| | | * object. |
| | | * |
| | |
| | | |
| | | |
| | | |
| | | import static org.opends.server.loggers.Debug.*; |
| | | import static org.opends.server.util.Validator.ensureNotNull; |
| | | |
| | | import java.io.Serializable; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.protocols.asn1.ASN1OctetString; |
| | | |
| | | import static org.opends.server.config.ConfigConstants.*; |
| | | import static org.opends.server.loggers.Debug.*; |
| | | import static org.opends.server.messages.MessageHandler.*; |
| | | import static org.opends.server.messages.SchemaMessages.*; |
| | | import static org.opends.server.util.StaticUtils.*; |
| | | |
| | | |
| | | |
| | |
| | | * This class defines a data structure for storing and interacting |
| | | * with the distinguished names associated with entries in the |
| | | * Directory Server. |
| | | * <p> |
| | | * All the methods in this class will throw a |
| | | * <code>NullPointerException</code> when provided with |
| | | * <code>null</code> reference parameters unless otherwise stated. |
| | | */ |
| | | public class DN |
| | | implements Comparable<DN>, Serializable |
| | | { |
| | | public final class DN implements Comparable<DN>, Serializable { |
| | | // FIXME: Don't store the normalized form and define equals(), |
| | | // hashCode(), and compareTo() in terms of RDN components (which |
| | | // cache their normalized form). This could potentially lead to less |
| | | // memory utilization for very little performance loss. |
| | | |
| | | // FIXME: Optimize normalization for common use-cases. E.g. |
| | | // concat(DN) can simply join the two normalized forms together. |
| | | // Similarly, getParent() and getLocalName() can avoid |
| | | // recalculating the normalized form and take a substring from the |
| | | // source DN's normalized form (this requires parsing commas, but |
| | | // could save memory). |
| | | |
| | | /** |
| | | * The fully-qualified name of this class for debugging purposes. |
| | | */ |
| | | private static final String CLASS_NAME = |
| | | "org.opends.server.types.DN"; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The serial version identifier required to satisfy the compiler |
| | | * because this class implements the |
| | | * <CODE>java.io.Serializable</CODE> interface. This value was |
| | | * generated using the <CODE>serialver</CODE> command-line utility |
| | | * <code>java.io.Serializable</code> interface. This value was |
| | | * generated using the <code>serialver</code> command-line utility |
| | | * included with the Java SDK. |
| | | */ |
| | | private static final long serialVersionUID = 1184263456768819888L; |
| | | |
| | | |
| | | |
| | | // The number of RDN components that comprise this DN. |
| | | private int numComponents; |
| | | private final int numComponents; |
| | | |
| | | // The index of the first RDN component (furthest from the root) in |
| | | // this DN. |
| | | private final int offset; |
| | | |
| | | // The set of RDN components that comprise this DN, arranged with |
| | | // the suffix as the last element. |
| | | private RDN[] rdnComponents; |
| | | private final RDN[] rdnComponents; |
| | | |
| | | // The string representation of this DN. |
| | | private String dnString; |
| | | // The cached normalized string representation of this DN. |
| | | private final String normalizedDN; |
| | | |
| | | // The normalized string representation of this DN. |
| | | private String normalizedDN; |
| | | // A DN comprising of zero RDN components. |
| | | private static final DN EMPTY_DN = new DN(new RDN[0], 0, 0); |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new DN with no RDN components (i.e., a null DN or root |
| | | * DSE). |
| | | * Creates a new DN comprising of zero RDN components (a null DN or |
| | | * root DSE). |
| | | * |
| | | * @return Returns a new DN comprising of zero RDN components. |
| | | */ |
| | | public DN() |
| | | { |
| | | this(new RDN[0]); |
| | | public static DN nullDN() { |
| | | return EMPTY_DN; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new <code>DN</code> containing the specified RDN |
| | | * sequence. |
| | | * <p> |
| | | * If the argument RDN sequence is empty, then the effect is the |
| | | * same as if {@link #nullDN()} had been called. |
| | | * |
| | | * @param rdns |
| | | * The RDN sequence that the new DN will represent. |
| | | * @return Returns a DN that represents the specified RDN sequence |
| | | * onto the end of this DN. |
| | | */ |
| | | public static DN create(RDN... rdns) { |
| | | ensureNotNull(rdns); |
| | | |
| | | if (rdns.length == 0) { |
| | | return nullDN(); |
| | | } |
| | | |
| | | RDN[] allRDNs = new RDN[rdns.length]; |
| | | System.arraycopy(rdns, 0, allRDNs, 0, rdns.length); |
| | | return new DN(allRDNs, 0, rdns.length); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Returns a <code>DN</code> object holding the value of the |
| | | * specified <code>String</code>. The argument is interpreted as |
| | | * representing the LDAP string representation of a DN. |
| | | * <p> |
| | | * This method is identical to {@link #decode(String)}. |
| | | * |
| | | * @param s |
| | | * The string to be parsed, or <code>null</code> in |
| | | * which case a <code>nullDN</code> will be returned. |
| | | * @return Returns a <code>DN</code> holding the value represented |
| | | * by the <code>string</code> argument. |
| | | * @throws DirectoryException |
| | | * If a problem occurs while trying to decode the provided |
| | | * string as a DN. |
| | | */ |
| | | public static DN valueOf(String s) throws DirectoryException { |
| | | return decode(s); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Decodes the provided ASN.1 octet string as a DN. |
| | | * |
| | | * @param dnString |
| | | * The ASN.1 octet string to decode as a DN, or |
| | | * <code>null</code> in which case a <code>nullDN</code> |
| | | * will be returned. |
| | | * @return The decoded DN. |
| | | * @throws DirectoryException |
| | | * If a problem occurs while trying to decode the provided |
| | | * ASN.1 octet string as a DN. |
| | | */ |
| | | public static DN decode(ByteString dnString) |
| | | throws DirectoryException { |
| | | assert debugEnter(CLASS_NAME, "decode", String.valueOf(dnString)); |
| | | |
| | | // A null or empty DN is acceptable. |
| | | if (dnString == null) { |
| | | return nullDN(); |
| | | } |
| | | |
| | | byte[] dnBytes = dnString.value(); |
| | | int length = dnBytes.length; |
| | | if (length == 0) { |
| | | return nullDN(); |
| | | } |
| | | |
| | | // Use string-based decoder. |
| | | return decode(dnString.stringValue()); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Decodes the provided string as a DN. |
| | | * |
| | | * @param dnString |
| | | * The string to decode as a DN, or <code>null</code> in |
| | | * which case a <code>nullDN</code> will be returned. |
| | | * @return The decoded DN. |
| | | * @throws DirectoryException |
| | | * If a problem occurs while trying to decode the provided |
| | | * string as a DN. |
| | | */ |
| | | public static DN decode(String dnString) throws DirectoryException { |
| | | assert debugEnter(CLASS_NAME, "decode", String.valueOf(dnString)); |
| | | |
| | | // A null or empty DN is acceptable. |
| | | if (dnString == null || dnString.length() == 0) { |
| | | return nullDN(); |
| | | } |
| | | |
| | | // Parse the first RDN. |
| | | int pos = 0; |
| | | RDN.Builder builder = RDN.createBuilder(); |
| | | pos = builder.parse(dnString, pos, true); |
| | | |
| | | if (builder.isEmpty()) { |
| | | return nullDN(); |
| | | } else { |
| | | // Parse the remaining RDNs. |
| | | List<RDN> rdns = new ArrayList<RDN>(10); |
| | | rdns.add(builder.getInstance()); |
| | | |
| | | while (pos >= 0) { |
| | | // Skip the RDN separator. |
| | | pos++; |
| | | |
| | | // Parse the next RDN. |
| | | builder.clear(); |
| | | pos = builder.parse(dnString, pos, false); |
| | | rdns.add(builder.getInstance()); |
| | | } |
| | | |
| | | // Parse successful - create the DN. |
| | | int sz = rdns.size(); |
| | | return new DN(rdns.toArray(new RDN[sz]), 0, sz); |
| | | } |
| | | } |
| | | |
| | | |
| | |
| | | * Creates a new DN with the provided set of RDNs, arranged with the |
| | | * suffix as the last element. |
| | | * |
| | | * @param rdnComponents The set of RDN components that make up |
| | | * this DN. |
| | | * @param rdnComponents |
| | | * The set of RDN components that make up this DN. |
| | | * @param offset |
| | | * The index of the first RDN component (furthest from the |
| | | * root) in this DN. |
| | | * @param count |
| | | * The number of RDNs to include in this DN. |
| | | */ |
| | | public DN(RDN[] rdnComponents) |
| | | { |
| | | private DN(RDN[] rdnComponents, int offset, int count) { |
| | | assert debugConstructor(CLASS_NAME, |
| | | String.valueOf(rdnComponents)); |
| | | String.valueOf(rdnComponents), String.valueOf(offset)); |
| | | |
| | | if (rdnComponents == null) |
| | | { |
| | | this.rdnComponents = new RDN[0]; |
| | | } |
| | | else |
| | | { |
| | | this.rdnComponents = rdnComponents; |
| | | } |
| | | |
| | | numComponents = this.rdnComponents.length; |
| | | dnString = null; |
| | | normalizedDN = toNormalizedString(); |
| | | this.offset = offset; |
| | | this.numComponents = count; |
| | | this.normalizedDN = normalize(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new DN with the provided set of RDNs, arranged with the |
| | | * suffix as the last element. |
| | | * |
| | | * @param rdnComponents The set of RDN components that make up |
| | | * Concatenates the specified DN to the end of this DN. |
| | | * <p> |
| | | * If the argument DN is the null DN, then this DN is returned. |
| | | * Conversely, if this DN is the null DN then the argument DN will |
| | | * be returned. Otherwise, the returned DN will be a descendent of |
| | | * this DN. |
| | | * |
| | | * @param localName |
| | | * The DN that will be concatenated to the end of this DN. |
| | | * @return Returns a DN that represents the concatenation of the |
| | | * specified DN onto the end of this DN. |
| | | */ |
| | | public DN(ArrayList<RDN> rdnComponents) |
| | | { |
| | | assert debugConstructor(CLASS_NAME, |
| | | String.valueOf(rdnComponents)); |
| | | public DN concat(DN localName) { |
| | | ensureNotNull(localName); |
| | | |
| | | if ((rdnComponents == null) || rdnComponents.isEmpty()) |
| | | { |
| | | this.rdnComponents = new RDN[0]; |
| | | } |
| | | else |
| | | { |
| | | this.rdnComponents = new RDN[rdnComponents.size()]; |
| | | rdnComponents.toArray(this.rdnComponents); |
| | | if (localName.isNullDN()) { |
| | | return this; |
| | | } |
| | | |
| | | numComponents = this.rdnComponents.length; |
| | | dnString = null; |
| | | normalizedDN = toNormalizedString(); |
| | | if (isNullDN()) { |
| | | return localName; |
| | | } |
| | | |
| | | RDN[] allRDNs = new RDN[numComponents + localName.numComponents]; |
| | | System.arraycopy(localName.rdnComponents, localName.offset, |
| | | allRDNs, 0, localName.numComponents); |
| | | System.arraycopy(rdnComponents, offset, allRDNs, |
| | | localName.numComponents, numComponents); |
| | | |
| | | return new DN(allRDNs, 0, allRDNs.length); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Constructs a new DN which is the concatenation of a base DN and a |
| | | * relative DN. The constructed DN has the following property: |
| | | * Concatenates the specified RDN sequence to the end of this DN. |
| | | * <p> |
| | | * If the argument RDN sequence is empty, then this DN is returned. |
| | | * Otherwise, the returned DN will be a descendent of this DN. |
| | | * |
| | | * @param rdns |
| | | * The RDN sequence that will be concatenated to the end of |
| | | * this DN. |
| | | * @return Returns a DN that represents the concatenation of the |
| | | * specified RDN sequence onto the end of this DN. |
| | | */ |
| | | public DN concat(RDN... rdns) { |
| | | ensureNotNull(rdns); |
| | | |
| | | if (rdns.length == 0) { |
| | | return this; |
| | | } |
| | | |
| | | // Don't check if this is a nullDN, because were going to copy the |
| | | // RDN sequence anyway. |
| | | |
| | | RDN[] allRDNs = new RDN[rdns.length + numComponents]; |
| | | |
| | | System.arraycopy(rdns, 0, allRDNs, 0, rdns.length); |
| | | System.arraycopy(rdnComponents, offset, allRDNs, |
| | | rdns.length, numComponents); |
| | | |
| | | return new DN(allRDNs, 0, allRDNs.length); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Get the parent DN of this DN. |
| | | * |
| | | * @return Returns the parent DN of this DN, or <code>null</code> |
| | | * if this DN does not have a parent (i.e. it is a DN having |
| | | * a single RDN component, or the null DN). |
| | | */ |
| | | public DN getParent() { |
| | | if (numComponents <= 1) { |
| | | return null; |
| | | } else { |
| | | return new DN(rdnComponents, offset + 1, numComponents - 1); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Create a local name (a relative DN) from this DN. |
| | | * <p> |
| | | * Examples: <blockquote> |
| | | * |
| | | * <pre> |
| | | * DN suffix; |
| | | * DN localName; |
| | | * DN dn = DN.decode("cn=john,o=example,c=us"); |
| | | * |
| | | * suffix.isAncestorOf(new DN(suffix, localName)) == true; |
| | | * dn.getLocalName(0) returns "cn=john,o=example,c=us" |
| | | * dn.getLocalName(1) returns "cn=john,o=example" |
| | | * dn.getLocalName(3) returns "" (null DN). |
| | | * </pre> |
| | | * |
| | | * @param baseDN |
| | | * The base DN. |
| | | * @param localName |
| | | * The relative DN. |
| | | * </blockquote> |
| | | * |
| | | * @param beginIndex |
| | | * The index of the first RDN component (nearest the root), |
| | | * inclusive. |
| | | * @return Returns the specified local name. |
| | | * @throws IndexOutOfBoundsException |
| | | * If <code>beginIndex</code> is negative, or greater |
| | | * than the number of RDN components in this DN. |
| | | */ |
| | | public DN(DN baseDN, DN localName) |
| | | { |
| | | this(baseDN, localName.rdnComponents); |
| | | public DN getLocalName(int beginIndex) |
| | | throws IndexOutOfBoundsException { |
| | | return getLocalName(beginIndex, numComponents); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Constructs a new DN which is the concatenation of a base DN and |
| | | * an RDN sequence. |
| | | * Create a local name (a relative DN) from this DN. |
| | | * <p> |
| | | * Examples: <blockquote> |
| | | * |
| | | * @param baseDN The base DN. |
| | | * @param rdnSequence The RDN sequence which will become the |
| | | * outermost RDNs of the concatenated DN. |
| | | * <pre> |
| | | * DN dn = DN.decode("cn=john,o=example,c=us"); |
| | | * |
| | | * dn.getLocalName(0, 3) returns "cn=john,o=example,c=us" |
| | | * dn.getLocalName(1, 2) returns "o=example" |
| | | * dn.getLocalName(2, 2) returns "" (null DN). |
| | | * </pre> |
| | | * |
| | | * </blockquote> |
| | | * |
| | | * @param beginIndex |
| | | * The index of the first RDN component (nearest the root), |
| | | * inclusive. |
| | | * @param endIndex |
| | | * The index of the last RDN component (furthest from the |
| | | * root), exclusive. |
| | | * @return Returns the specified local name. |
| | | * @throws IndexOutOfBoundsException |
| | | * If <code>beginIndex</code> is negative, or |
| | | * <code>endIndex</code> is larger than the number of |
| | | * RDN components in this DN, or <code>beginIndex</code> |
| | | * is larger than <code>endIndex</code>. |
| | | */ |
| | | public DN(DN baseDN, RDN[] rdnSequence) |
| | | { |
| | | assert debugConstructor(CLASS_NAME, String.valueOf(baseDN), |
| | | String.valueOf(rdnSequence)); |
| | | public DN getLocalName(int beginIndex, int endIndex) |
| | | throws IndexOutOfBoundsException { |
| | | if (beginIndex < 0) { |
| | | throw new IndexOutOfBoundsException("beginIndex out of range: " |
| | | + beginIndex); |
| | | } |
| | | |
| | | RDN[] allRDNs = new RDN[rdnSequence.length+baseDN.numComponents]; |
| | | if (endIndex > numComponents) { |
| | | throw new IndexOutOfBoundsException("endIndex out of range: " |
| | | + endIndex); |
| | | } |
| | | |
| | | System.arraycopy(rdnSequence, 0, allRDNs, 0, rdnSequence.length); |
| | | System.arraycopy(baseDN.rdnComponents, 0, allRDNs, |
| | | rdnSequence.length, baseDN.numComponents); |
| | | if (beginIndex > endIndex) { |
| | | throw new IndexOutOfBoundsException( |
| | | "beginIndex greater than endIndex"); |
| | | } |
| | | |
| | | this.rdnComponents = allRDNs; |
| | | this.numComponents = allRDNs.length; |
| | | this.dnString = null; |
| | | this.normalizedDN = toNormalizedString(); |
| | | if (beginIndex == 0 && endIndex == numComponents) { |
| | | return this; |
| | | } else { |
| | | int i = offset + numComponents - endIndex; |
| | | return new DN(rdnComponents, i, endIndex - beginIndex); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the set of RDN components that make up this DN, |
| | | * arranged with the suffix as the last element. The caller must not |
| | | * modify the contents of the returned list. |
| | | * Get the number of RDN components that make up this DN. |
| | | * |
| | | * @return The set of RDN components that make up this DN. |
| | | * @return Returns the number of RDN components that make up this |
| | | * DN. |
| | | */ |
| | | public RDN[] getRDNComponents() |
| | | { |
| | | assert debugEnter(CLASS_NAME, "getRDNComponents"); |
| | | public int getNumComponents() { |
| | | assert debugEnter(CLASS_NAME, "getNumComponents"); |
| | | |
| | | return rdnComponents; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Specifies the set of RDN components that make up this DN. |
| | | * |
| | | * @param rdnComponents The set of RDN components that make up |
| | | * this DN arranged with the suffix as the |
| | | * last element. |
| | | */ |
| | | public void setRDNComponents(RDN[] rdnComponents) |
| | | { |
| | | assert debugEnter(CLASS_NAME, "setRDNComponents", |
| | | String.valueOf(rdnComponents)); |
| | | |
| | | if (rdnComponents == null) |
| | | { |
| | | this.rdnComponents = new RDN[0]; |
| | | } |
| | | else |
| | | { |
| | | this.rdnComponents = rdnComponents; |
| | | } |
| | | |
| | | numComponents = this.rdnComponents.length; |
| | | dnString = null; |
| | | normalizedDN = null; // Get rid of the old cached value. |
| | | normalizedDN = toNormalizedString(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Specifies the set of RDN components that make up this DN. |
| | | * |
| | | * @param rdnComponents The set of RDN components that make up |
| | | * this DN, arranged with the suffix as the |
| | | * last element. |
| | | */ |
| | | public void setRDNComponents(ArrayList<RDN> rdnComponents) |
| | | { |
| | | assert debugEnter(CLASS_NAME, "setRDNComponents", |
| | | String.valueOf(rdnComponents)); |
| | | |
| | | if (rdnComponents == null) |
| | | { |
| | | this.rdnComponents = new RDN[0]; |
| | | } |
| | | else |
| | | { |
| | | this.rdnComponents = new RDN[rdnComponents.size()]; |
| | | rdnComponents.toArray(this.rdnComponents); |
| | | } |
| | | |
| | | numComponents = this.rdnComponents.length; |
| | | dnString = null; |
| | | normalizedDN = toNormalizedString(); |
| | | return numComponents; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the outermost RDN component for this DN (i.e., the one |
| | | * that is furthest from the suffix). |
| | | * that is furthest from the suffix). This method is equivalent to |
| | | * calling <code>getRDN(0)</code> for non-null DNs. |
| | | * |
| | | * @return The outermost RDN component for this DN, or |
| | | * <CODE>null</CODE> if there are no RDN components in the |
| | | * <code>null</code> if there are no RDN components in the |
| | | * DN. |
| | | */ |
| | | public RDN getRDN() |
| | | { |
| | | public RDN getRDN() { |
| | | assert debugEnter(CLASS_NAME, "getRDN"); |
| | | |
| | | if (numComponents == 0) |
| | | { |
| | | if (numComponents == 0) { |
| | | return null; |
| | | } else { |
| | | return getRDN(0); |
| | | } |
| | | else |
| | | { |
| | | return rdnComponents[0]; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Get the RDN at the specified index. |
| | | * |
| | | * @param index |
| | | * The index of the RDN to retrieve, where <code>0</code> |
| | | * indicates the outermost RDN component (i.e. the one that |
| | | * is furthest from the suffix). |
| | | * @return Returns the RDN at the specified index. |
| | | * @throws IndexOutOfBoundsException |
| | | * If <code>index</code> is negative, or greater than or |
| | | * equal to the number of RDN components in this DN. |
| | | */ |
| | | public RDN getRDN(int index) throws IndexOutOfBoundsException { |
| | | if (index < 0) { |
| | | throw new IndexOutOfBoundsException("index out of range: " |
| | | + index); |
| | | } |
| | | |
| | | if (index >= numComponents) { |
| | | throw new IndexOutOfBoundsException("index out of range: " |
| | | + index); |
| | | } |
| | | |
| | | return rdnComponents[offset + index]; |
| | | } |
| | | |
| | | |
| | |
| | | * Retrieves the DN of the entry that is the immediate parent for |
| | | * this entry. |
| | | * |
| | | * @return The DN of the entry that is the immediate parent for |
| | | * this entry, or <CODE>null</CODE> if the entry with this |
| | | * DN does not have a parent (either because there is only |
| | | * a single RDN component or because this DN is a suffix |
| | | * @return The DN of the entry that is the immediate parent for this |
| | | * entry, or <code>null</code> if the entry with this DN |
| | | * does not have a parent (either because there is only a |
| | | * single RDN component or because this DN is a suffix |
| | | * defined in the server). |
| | | */ |
| | | public DN getParent() |
| | | { |
| | | assert debugEnter(CLASS_NAME, "getParent"); |
| | | public DN getParentDNInSuffix() { |
| | | assert debugEnter(CLASS_NAME, "getParentDNInSuffix"); |
| | | |
| | | if ((numComponents <= 1) || (DirectoryServer.isSuffix(this))) |
| | | { |
| | | if ((numComponents <= 1) || (DirectoryServer.isSuffix(this))) { |
| | | return null; |
| | | } |
| | | |
| | | RDN[] parentComponents = new RDN[numComponents-1]; |
| | | System.arraycopy(rdnComponents, 1, parentComponents, 0, |
| | | numComponents-1); |
| | | return new DN(parentComponents); |
| | | return getParent(); |
| | | } |
| | | |
| | | |
| | |
| | | * the root DSE for the Directory Server, or the authorization DN |
| | | * for an anonymous or unauthenticated client. |
| | | * |
| | | * @return <CODE>true</CODE> if this does represent a null DN, or |
| | | * <CODE>false</CODE> if it does not. |
| | | * @return <code>true</code> if this does represent a null DN, or |
| | | * <code>false</code> if it does not. |
| | | */ |
| | | public boolean isNullDN() |
| | | { |
| | | public boolean isNullDN() { |
| | | assert debugEnter(CLASS_NAME, "isNullDN"); |
| | | |
| | | return (numComponents == 0); |
| | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether this DN is one of the suffixes defined in the |
| | | * Directory Server. |
| | | * |
| | | * @return <CODE>true</CODE> if this DN is one of the suffixes |
| | | * defined in the Directory Server, or <CODE>false</CODE> |
| | | * if not. |
| | | */ |
| | | public boolean isSuffix() |
| | | { |
| | | assert debugEnter(CLASS_NAME, "isSuffix"); |
| | | |
| | | return DirectoryServer.isSuffix(this); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether this DN is a descendant of the provided DN |
| | | * (i.e., that the RDN components of the provided DN are the same as |
| | | * the last RDN components for this DN). |
| | | * |
| | | * @param dn The DN for which to make the determination. |
| | | * |
| | | * @return <CODE>true</CODE> if this DN is a descendant of the |
| | | * provided DN, or <CODE>false</CODE> if not. |
| | | * @param dn |
| | | * The DN for which to make the determination. |
| | | * @return <code>true</code> if this DN is a descendant of the |
| | | * provided DN, or <code>false</code> if not. |
| | | */ |
| | | public boolean isDescendantOf(DN dn) |
| | | { |
| | | assert debugEnter(CLASS_NAME, "isDescendantOf", |
| | | String.valueOf(dn)); |
| | | public boolean isDescendantOf(DN dn) { |
| | | assert debugEnter(CLASS_NAME, "isDescendantOf", String |
| | | .valueOf(dn)); |
| | | |
| | | int offset = numComponents - dn.numComponents; |
| | | if (offset < 0) |
| | | { |
| | | ensureNotNull(dn); |
| | | |
| | | int diff = numComponents - dn.numComponents; |
| | | if (diff < 0) { |
| | | return false; |
| | | } |
| | | |
| | | for (int i=0; i < dn.numComponents; i++) |
| | | { |
| | | if (! rdnComponents[i+offset].equals(dn.rdnComponents[i])) |
| | | { |
| | | for (int i = 0; i < dn.numComponents; i++) { |
| | | if (!getRDN(i + diff).equals(dn.getRDN(i))) { |
| | | return false; |
| | | } |
| | | } |
| | |
| | | * (i.e., that the RDN components of this DN are the same as the |
| | | * last RDN components for the provided DN). |
| | | * |
| | | * @param dn The DN for which to make the determination. |
| | | * |
| | | * @return <CODE>true</CODE> if this DN is an ancestor of the |
| | | * provided DN, or <CODE>false</CODE> if not. |
| | | * @param dn |
| | | * The DN for which to make the determination. |
| | | * @return <code>true</code> if this DN is an ancestor of the |
| | | * provided DN, or <code>false</code> if not. |
| | | */ |
| | | public boolean isAncestorOf(DN dn) |
| | | { |
| | | public boolean isAncestorOf(DN dn) { |
| | | assert debugEnter(CLASS_NAME, "isAncestorOf", String.valueOf(dn)); |
| | | |
| | | int offset = dn.numComponents - numComponents; |
| | | if (offset < 0) |
| | | { |
| | | ensureNotNull(dn); |
| | | |
| | | int diff = dn.numComponents - numComponents; |
| | | if (diff < 0) { |
| | | return false; |
| | | } |
| | | |
| | | for (int i=0; i < numComponents; i++) |
| | | { |
| | | if (! rdnComponents[i].equals(dn.rdnComponents[i+offset])) |
| | | { |
| | | for (int i = 0; i < numComponents; i++) { |
| | | if (!getRDN(i).equals(dn.getRDN(i + diff))) { |
| | | return false; |
| | | } |
| | | } |
| | |
| | | |
| | | |
| | | /** |
| | | * Decodes the provided ASN.1 octet string as a DN. |
| | | * |
| | | * @param dnString The ASN.1 octet string to decode as a DN. |
| | | * |
| | | * @return The decoded DN. |
| | | * |
| | | * @throws DirectoryException If a problem occurs while trying to |
| | | * decode the provided ASN.1 octet |
| | | * string as a DN. |
| | | */ |
| | | public static DN decode(ByteString dnString) |
| | | throws DirectoryException |
| | | { |
| | | assert debugEnter(CLASS_NAME, "decode", String.valueOf(dnString)); |
| | | |
| | | |
| | | // A null or empty DN is acceptable. |
| | | if (dnString == null) |
| | | { |
| | | return new DN(new ArrayList<RDN>(0)); |
| | | } |
| | | |
| | | byte[] dnBytes = dnString.value(); |
| | | int length = dnBytes.length; |
| | | if (length == 0) |
| | | { |
| | | return new DN(new ArrayList<RDN>(0)); |
| | | } |
| | | |
| | | |
| | | // See if we are dealing with any non-ASCII characters, or any |
| | | // escaped characters. If so, then the easiest and safest |
| | | // approach is to convert the DN to a string and decode it that |
| | | // way. |
| | | for (byte b : dnBytes) |
| | | { |
| | | if (((b & 0x7F) != b) || (b == '\\')) |
| | | { |
| | | return decode(dnString.stringValue()); |
| | | } |
| | | } |
| | | |
| | | |
| | | // Iterate through the DN string. The first thing to do is to get |
| | | // rid of any leading spaces. |
| | | int pos = 0; |
| | | byte b = dnBytes[pos]; |
| | | while (b == ' ') |
| | | { |
| | | pos++; |
| | | if (pos == length) |
| | | { |
| | | // This means that the DN was completely comprised of spaces |
| | | // and therefore should be considered the same as a null or |
| | | // empty DN. |
| | | return new DN(new ArrayList<RDN>(0)); |
| | | } |
| | | else |
| | | { |
| | | b = dnBytes[pos]; |
| | | } |
| | | } |
| | | |
| | | |
| | | // We know that it's not an empty DN, so we can do the real |
| | | // processing. Create a loop and iterate through all the RDN |
| | | // components. |
| | | boolean allowExceptions = |
| | | DirectoryServer.allowAttributeNameExceptions(); |
| | | ArrayList<RDN> rdnComponents = new ArrayList<RDN>(); |
| | | while (true) |
| | | { |
| | | StringBuilder attributeName = new StringBuilder(); |
| | | pos = parseAttributeName(dnBytes, pos, attributeName, |
| | | allowExceptions); |
| | | |
| | | |
| | | // Make sure that we're not at the end of the DN string because |
| | | // that would be invalid. |
| | | if (pos >= length) |
| | | { |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_END_WITH_ATTR_NAME; |
| | | String message = getMessage(msgID, dnString.stringValue(), |
| | | attributeName.toString()); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | |
| | | |
| | | // Skip over any spaces between the attribute name and its |
| | | // value. |
| | | b = dnBytes[pos]; |
| | | while (b == ' ') |
| | | { |
| | | pos++; |
| | | if (pos >= length) |
| | | { |
| | | // This means that we hit the end of the value before |
| | | // finding a '='. This is illegal because there is no |
| | | // attribute-value separator. |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_END_WITH_ATTR_NAME; |
| | | String message = getMessage(msgID, dnString.stringValue(), |
| | | attributeName.toString()); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | else |
| | | { |
| | | b = dnBytes[pos]; |
| | | } |
| | | } |
| | | |
| | | |
| | | // The next character must be an equal sign. If it is not, |
| | | // then that's an error. |
| | | if (b == '=') |
| | | { |
| | | pos++; |
| | | } |
| | | else |
| | | { |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_NO_EQUAL; |
| | | String message = getMessage(msgID, dnString.stringValue(), |
| | | attributeName.toString(), |
| | | (char) b); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | |
| | | |
| | | // Skip over any spaces after the equal sign. |
| | | while ((pos < length) && ((b = dnBytes[pos]) == ' ')) |
| | | { |
| | | pos++; |
| | | } |
| | | |
| | | |
| | | // If we are at the end of the DN string, then that must mean |
| | | // that the attribute value was empty. This will probably never |
| | | // happen in a real-world environment, but technically isn't |
| | | // illegal. If it does happen, then go ahead and create the RDN |
| | | // component and return the DN. |
| | | if (pos >= length) |
| | | { |
| | | String name = attributeName.toString(); |
| | | String lowerName = toLowerCase(name); |
| | | AttributeType attrType = |
| | | DirectoryServer.getAttributeType(lowerName); |
| | | |
| | | if (attrType == null) |
| | | { |
| | | // This must be an attribute type that we don't know about. |
| | | // In that case, we'll create a new attribute using the |
| | | // default syntax. If this is a problem, it will be caught |
| | | // later either by not finding the target entry or by not |
| | | // allowing the entry to be added. |
| | | attrType = DirectoryServer.getDefaultAttributeType(name); |
| | | } |
| | | |
| | | AttributeValue value = |
| | | new AttributeValue(new ASN1OctetString(), |
| | | new ASN1OctetString()); |
| | | rdnComponents.add(new RDN(attrType, name, value)); |
| | | return new DN(rdnComponents); |
| | | } |
| | | |
| | | |
| | | // Parse the value for this RDN component. |
| | | ByteString parsedValue = new ASN1OctetString(); |
| | | pos = parseAttributeValue(dnBytes, pos, parsedValue); |
| | | |
| | | |
| | | // Create the new RDN with the provided information. |
| | | String name = attributeName.toString(); |
| | | String lowerName = toLowerCase(name); |
| | | AttributeType attrType = |
| | | DirectoryServer.getAttributeType(lowerName); |
| | | if (attrType == null) |
| | | { |
| | | // This must be an attribute type that we don't know about. |
| | | // In that case, we'll create a new attribute using the |
| | | // default syntax. If this is a problem, it will be caught |
| | | // later either by not finding the target entry or by not |
| | | // allowing the entry to be added. |
| | | attrType = DirectoryServer.getDefaultAttributeType(name); |
| | | } |
| | | |
| | | AttributeValue value = |
| | | new AttributeValue(attrType, parsedValue); |
| | | RDN rdn = new RDN(attrType, name, value); |
| | | |
| | | |
| | | // Skip over any spaces that might be after the attribute value. |
| | | while ((pos < length) && ((b = dnBytes[pos]) == ' ')) |
| | | { |
| | | pos++; |
| | | } |
| | | |
| | | |
| | | // Most likely, we will be at either the end of the RDN |
| | | // component or the end of the DN. If so, then handle that |
| | | // appropriately. |
| | | if (pos >= length) |
| | | { |
| | | // We're at the end of the DN string and should have a valid |
| | | // DN so return it. |
| | | rdnComponents.add(rdn); |
| | | return new DN(rdnComponents); |
| | | } |
| | | else if ((b == ',') || (b == ';')) |
| | | { |
| | | // We're at the end of the RDN component, so add it to the |
| | | // list, skip over the comma/semicolon, and start on the next |
| | | // component. |
| | | rdnComponents.add(rdn); |
| | | pos++; |
| | | continue; |
| | | } |
| | | else if (b != '+') |
| | | { |
| | | // This should not happen. At any rate, it's an illegal |
| | | // character, so throw an exception. |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_INVALID_CHAR; |
| | | String message = getMessage(msgID, new String(dnBytes), |
| | | (char) b, pos); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | |
| | | |
| | | // If we have gotten here, then this must be a multi-valued RDN. |
| | | // In that case, parse the remaining attribute/value pairs and |
| | | // add them to the RDN that we've already created. |
| | | while (true) |
| | | { |
| | | // Skip over the plus sign and any spaces that may follow it |
| | | // before the next attribute name. |
| | | pos++; |
| | | while ((pos < length) && (dnBytes[pos] == ' ')) |
| | | { |
| | | pos++; |
| | | } |
| | | |
| | | |
| | | // Parse the attribute name from the DN string. |
| | | attributeName = new StringBuilder(); |
| | | pos = parseAttributeName(dnBytes, pos, attributeName, |
| | | allowExceptions); |
| | | |
| | | |
| | | // Make sure that we're not at the end of the DN string |
| | | // because that would be invalid. |
| | | if (pos >= length) |
| | | { |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_END_WITH_ATTR_NAME; |
| | | String message = getMessage(msgID, dnString.stringValue(), |
| | | attributeName.toString()); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | |
| | | |
| | | // Skip over any spaces between the attribute name and its |
| | | // value. |
| | | b = dnBytes[pos]; |
| | | while (b == ' ') |
| | | { |
| | | pos++; |
| | | if (pos >= length) |
| | | { |
| | | // This means that we hit the end of the value before |
| | | // finding a '='. This is illegal because there is no |
| | | // attribute-value separator. |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_END_WITH_ATTR_NAME; |
| | | String message = getMessage(msgID, dnString.stringValue(), |
| | | attributeName.toString()); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | else |
| | | { |
| | | b = dnBytes[pos]; |
| | | } |
| | | } |
| | | |
| | | |
| | | // The next character must be an equal sign. If it is not, |
| | | // then that's an error. |
| | | if (b == '=') |
| | | { |
| | | pos++; |
| | | } |
| | | else |
| | | { |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_NO_EQUAL; |
| | | String message = getMessage(msgID, dnString.stringValue(), |
| | | attributeName.toString(), |
| | | (char) b); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | |
| | | |
| | | // Skip over any spaces after the equal sign. |
| | | while ((pos < length) && ((b = dnBytes[pos]) == ' ')) |
| | | { |
| | | pos++; |
| | | } |
| | | |
| | | |
| | | // If we are at the end of the DN string, then that must mean |
| | | // that the attribute value was empty. This will probably |
| | | // never happen in a real-world environment, but technically |
| | | // isn't illegal. If it does happen, then go ahead and create |
| | | // the RDN component and return the DN. |
| | | if (pos >= length) |
| | | { |
| | | name = attributeName.toString(); |
| | | lowerName = toLowerCase(name); |
| | | attrType = DirectoryServer.getAttributeType(lowerName); |
| | | |
| | | if (attrType == null) |
| | | { |
| | | // This must be an attribute type that we don't know |
| | | // about. In that case, we'll create a new attribute |
| | | // using the default syntax. If this is a problem, it |
| | | // will be caught later either by not finding the target |
| | | // entry or by not allowing the entry to be added. |
| | | attrType = DirectoryServer.getDefaultAttributeType(name); |
| | | } |
| | | |
| | | value = new AttributeValue(new ASN1OctetString(), |
| | | new ASN1OctetString()); |
| | | rdn.addValue(attrType, name, value); |
| | | rdnComponents.add(rdn); |
| | | return new DN(rdnComponents); |
| | | } |
| | | |
| | | |
| | | // Parse the value for this RDN component. |
| | | parsedValue = new ASN1OctetString(); |
| | | pos = parseAttributeValue(dnBytes, pos, parsedValue); |
| | | |
| | | |
| | | // Create the new RDN with the provided information. |
| | | name = attributeName.toString(); |
| | | lowerName = toLowerCase(name); |
| | | attrType = DirectoryServer.getAttributeType(lowerName); |
| | | if (attrType == null) |
| | | { |
| | | // This must be an attribute type that we don't know about. |
| | | // In that case, we'll create a new attribute using the |
| | | // default syntax. If this is a problem, it will be caught |
| | | // later either by not finding the target entry or by not |
| | | // allowing the entry to be added. |
| | | attrType = DirectoryServer.getDefaultAttributeType(name); |
| | | } |
| | | |
| | | value = new AttributeValue(attrType, parsedValue); |
| | | rdn.addValue(attrType, name, value); |
| | | |
| | | |
| | | // Skip over any spaces that might be after the attribute |
| | | // value. |
| | | while ((pos < length) && ((b = dnBytes[pos]) == ' ')) |
| | | { |
| | | pos++; |
| | | } |
| | | |
| | | |
| | | // Most likely, we will be at either the end of the RDN |
| | | // component or the end of the DN. If so, then handle that |
| | | // appropriately. |
| | | if (pos >= length) |
| | | { |
| | | // We're at the end of the DN string and should have a valid |
| | | // DN so return it. |
| | | rdnComponents.add(rdn); |
| | | return new DN(rdnComponents); |
| | | } |
| | | else if ((b == ',') || (b == ';')) |
| | | { |
| | | // We're at the end of the RDN component, so add it to the |
| | | // list, skip over the comma/semicolon, and start on the |
| | | // next component. |
| | | rdnComponents.add(rdn); |
| | | pos++; |
| | | break; |
| | | } |
| | | else if (b != '+') |
| | | { |
| | | // This should not happen. At any rate, it's an illegal |
| | | // character, so throw an exception. |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_INVALID_CHAR; |
| | | String message = getMessage(msgID, dnString.stringValue(), |
| | | (char) b, pos); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Decodes the provided string as a DN. |
| | | * |
| | | * @param dnString The string to decode as a DN. |
| | | * |
| | | * @return The decoded DN. |
| | | * |
| | | * @throws DirectoryException If a problem occurs while trying to |
| | | * decode the provided string as a DN. |
| | | */ |
| | | public static DN decode(String dnString) |
| | | throws DirectoryException |
| | | { |
| | | assert debugEnter(CLASS_NAME, "decode", String.valueOf(dnString)); |
| | | |
| | | |
| | | // A null or empty DN is acceptable. |
| | | if (dnString == null) |
| | | { |
| | | return new DN(new ArrayList<RDN>(0)); |
| | | } |
| | | |
| | | int length = dnString.length(); |
| | | if (length == 0) |
| | | { |
| | | return new DN(new ArrayList<RDN>(0)); |
| | | } |
| | | |
| | | |
| | | // Iterate through the DN string. The first thing to do is to get |
| | | // rid of any leading spaces. |
| | | int pos = 0; |
| | | char c = dnString.charAt(pos); |
| | | while (c == ' ') |
| | | { |
| | | pos++; |
| | | if (pos == length) |
| | | { |
| | | // This means that the DN was completely comprised of spaces |
| | | // and therefore should be considered the same as a null or |
| | | // empty DN. |
| | | return new DN(new ArrayList<RDN>(0)); |
| | | } |
| | | else |
| | | { |
| | | c = dnString.charAt(pos); |
| | | } |
| | | } |
| | | |
| | | |
| | | // We know that it's not an empty DN, so we can do the real |
| | | // processing. Create a loop and iterate through all the RDN |
| | | // components. |
| | | boolean allowExceptions = |
| | | DirectoryServer.allowAttributeNameExceptions(); |
| | | ArrayList<RDN> rdnComponents = new ArrayList<RDN>(); |
| | | while (true) |
| | | { |
| | | StringBuilder attributeName = new StringBuilder(); |
| | | pos = parseAttributeName(dnString, pos, attributeName, |
| | | allowExceptions); |
| | | |
| | | |
| | | // Make sure that we're not at the end of the DN string because |
| | | // that would be invalid. |
| | | if (pos >= length) |
| | | { |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_END_WITH_ATTR_NAME; |
| | | String message = getMessage(msgID, dnString, |
| | | attributeName.toString()); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | |
| | | |
| | | // Skip over any spaces between the attribute name and its |
| | | // value. |
| | | c = dnString.charAt(pos); |
| | | while (c == ' ') |
| | | { |
| | | pos++; |
| | | if (pos >= length) |
| | | { |
| | | // This means that we hit the end of the value before |
| | | // finding a '='. This is illegal because there is no |
| | | // attribute-value separator. |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_END_WITH_ATTR_NAME; |
| | | String message = getMessage(msgID, dnString, |
| | | attributeName.toString()); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | else |
| | | { |
| | | c = dnString.charAt(pos); |
| | | } |
| | | } |
| | | |
| | | |
| | | // The next character must be an equal sign. If it is not, then |
| | | // that's an error. |
| | | if (c == '=') |
| | | { |
| | | pos++; |
| | | } |
| | | else |
| | | { |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_NO_EQUAL; |
| | | String message = getMessage(msgID, dnString, |
| | | attributeName.toString(), c); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | |
| | | |
| | | // Skip over any spaces after the equal sign. |
| | | while ((pos < length) && ((c = dnString.charAt(pos)) == ' ')) |
| | | { |
| | | pos++; |
| | | } |
| | | |
| | | |
| | | // If we are at the end of the DN string, then that must mean |
| | | // that the attribute value was empty. This will probably never |
| | | // happen in a real-world environment, but technically isn't |
| | | // illegal. If it does happen, then go ahead and create the |
| | | // RDN component and return the DN. |
| | | if (pos >= length) |
| | | { |
| | | String name = attributeName.toString(); |
| | | String lowerName = toLowerCase(name); |
| | | AttributeType attrType = |
| | | DirectoryServer.getAttributeType(lowerName); |
| | | |
| | | if (attrType == null) |
| | | { |
| | | // This must be an attribute type that we don't know about. |
| | | // In that case, we'll create a new attribute using the |
| | | // default syntax. If this is a problem, it will be caught |
| | | // later either by not finding the target entry or by not |
| | | // allowing the entry to be added. |
| | | attrType = DirectoryServer.getDefaultAttributeType(name); |
| | | } |
| | | |
| | | AttributeValue value = |
| | | new AttributeValue(new ASN1OctetString(), |
| | | new ASN1OctetString()); |
| | | rdnComponents.add(new RDN(attrType, name, value)); |
| | | return new DN(rdnComponents); |
| | | } |
| | | |
| | | |
| | | // Parse the value for this RDN component. |
| | | ByteString parsedValue = new ASN1OctetString(); |
| | | pos = parseAttributeValue(dnString, pos, parsedValue); |
| | | |
| | | |
| | | // Create the new RDN with the provided information. |
| | | String name = attributeName.toString(); |
| | | String lowerName = toLowerCase(name); |
| | | AttributeType attrType = |
| | | DirectoryServer.getAttributeType(lowerName); |
| | | if (attrType == null) |
| | | { |
| | | // This must be an attribute type that we don't know about. |
| | | // In that case, we'll create a new attribute using the |
| | | // default syntax. If this is a problem, it will be caught |
| | | // later either by not finding the target entry or by not |
| | | // allowing the entry to be added. |
| | | attrType = DirectoryServer.getDefaultAttributeType(name); |
| | | } |
| | | |
| | | AttributeValue value = |
| | | new AttributeValue(attrType, parsedValue); |
| | | RDN rdn = new RDN(attrType, name, value); |
| | | |
| | | |
| | | // Skip over any spaces that might be after the attribute value. |
| | | while ((pos < length) && ((c = dnString.charAt(pos)) == ' ')) |
| | | { |
| | | pos++; |
| | | } |
| | | |
| | | |
| | | // Most likely, we will be at either the end of the RDN |
| | | // component or the end of the DN. If so, then handle that |
| | | // appropriately. |
| | | if (pos >= length) |
| | | { |
| | | // We're at the end of the DN string and should have a valid |
| | | // DN so return it. |
| | | rdnComponents.add(rdn); |
| | | return new DN(rdnComponents); |
| | | } |
| | | else if ((c == ',') || (c == ';')) |
| | | { |
| | | // We're at the end of the RDN component, so add it to the |
| | | // list, skip over the comma/semicolon, and start on the next |
| | | // component. |
| | | rdnComponents.add(rdn); |
| | | pos++; |
| | | continue; |
| | | } |
| | | else if (c != '+') |
| | | { |
| | | // This should not happen. At any rate, it's an illegal |
| | | // character, so throw an exception. |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_INVALID_CHAR; |
| | | String message = getMessage(msgID, dnString, c, pos); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | |
| | | |
| | | // If we have gotten here, then this must be a multi-valued RDN. |
| | | // In that case, parse the remaining attribute/value pairs and |
| | | // add them to the RDN that we've already created. |
| | | while (true) |
| | | { |
| | | // Skip over the plus sign and any spaces that may follow it |
| | | // before the next attribute name. |
| | | pos++; |
| | | while ((pos < length) && (dnString.charAt(pos) == ' ')) |
| | | { |
| | | pos++; |
| | | } |
| | | |
| | | |
| | | // Parse the attribute name from the DN string. |
| | | attributeName = new StringBuilder(); |
| | | pos = parseAttributeName(dnString, pos, attributeName, |
| | | allowExceptions); |
| | | |
| | | |
| | | // Make sure that we're not at the end of the DN string |
| | | // because that would be invalid. |
| | | if (pos >= length) |
| | | { |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_END_WITH_ATTR_NAME; |
| | | String message = getMessage(msgID, dnString, |
| | | attributeName.toString()); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | |
| | | |
| | | // Skip over any spaces between the attribute name and its |
| | | // value. |
| | | c = dnString.charAt(pos); |
| | | while (c == ' ') |
| | | { |
| | | pos++; |
| | | if (pos >= length) |
| | | { |
| | | // This means that we hit the end of the value before |
| | | // finding a '='. This is illegal because there is no |
| | | // attribute-value separator. |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_END_WITH_ATTR_NAME; |
| | | String message = getMessage(msgID, dnString, |
| | | attributeName.toString()); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | else |
| | | { |
| | | c = dnString.charAt(pos); |
| | | } |
| | | } |
| | | |
| | | |
| | | // The next character must be an equal sign. If it is not, |
| | | // then that's an error. |
| | | if (c == '=') |
| | | { |
| | | pos++; |
| | | } |
| | | else |
| | | { |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_NO_EQUAL; |
| | | String message = getMessage(msgID, dnString, |
| | | attributeName.toString(), c); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | |
| | | |
| | | // Skip over any spaces after the equal sign. |
| | | while ((pos < length) && ((c = dnString.charAt(pos)) == ' ')) |
| | | { |
| | | pos++; |
| | | } |
| | | |
| | | |
| | | // If we are at the end of the DN string, then that must mean |
| | | // that the attribute value was empty. This will probably |
| | | // never happen in a real-world environment, but technically |
| | | // isn't illegal. If it does happen, then go ahead and create |
| | | // the RDN component and return the DN. |
| | | if (pos >= length) |
| | | { |
| | | name = attributeName.toString(); |
| | | lowerName = toLowerCase(name); |
| | | attrType = DirectoryServer.getAttributeType(lowerName); |
| | | |
| | | if (attrType == null) |
| | | { |
| | | // This must be an attribute type that we don't know |
| | | // about. In that case, we'll create a new attribute |
| | | // using the default syntax. If this is a problem, it |
| | | // will be caught later either by not finding the target |
| | | // entry or by not allowing the entry to be added. |
| | | attrType = DirectoryServer.getDefaultAttributeType(name); |
| | | } |
| | | |
| | | value = new AttributeValue(new ASN1OctetString(), |
| | | new ASN1OctetString()); |
| | | rdn.addValue(attrType, name, value); |
| | | rdnComponents.add(rdn); |
| | | return new DN(rdnComponents); |
| | | } |
| | | |
| | | |
| | | // Parse the value for this RDN component. |
| | | parsedValue = new ASN1OctetString(); |
| | | pos = parseAttributeValue(dnString, pos, parsedValue); |
| | | |
| | | |
| | | // Create the new RDN with the provided information. |
| | | name = attributeName.toString(); |
| | | lowerName = toLowerCase(name); |
| | | attrType = DirectoryServer.getAttributeType(lowerName); |
| | | if (attrType == null) |
| | | { |
| | | // This must be an attribute type that we don't know about. |
| | | // In that case, we'll create a new attribute using the |
| | | // default syntax. If this is a problem, it will be caught |
| | | // later either by not finding the target entry or by not |
| | | // allowing the entry to be added. |
| | | attrType = DirectoryServer.getDefaultAttributeType(name); |
| | | } |
| | | |
| | | value = new AttributeValue(attrType, parsedValue); |
| | | rdn.addValue(attrType, name, value); |
| | | |
| | | |
| | | // Skip over any spaces that might be after the attribute |
| | | // value. |
| | | while ((pos < length) && ((c = dnString.charAt(pos)) == ' ')) |
| | | { |
| | | pos++; |
| | | } |
| | | |
| | | |
| | | // Most likely, we will be at either the end of the RDN |
| | | // component or the end of the DN. If so, then handle that |
| | | // appropriately. |
| | | if (pos >= length) |
| | | { |
| | | // We're at the end of the DN string and should have a valid |
| | | // DN so return it. |
| | | rdnComponents.add(rdn); |
| | | return new DN(rdnComponents); |
| | | } |
| | | else if ((c == ',') || (c == ';')) |
| | | { |
| | | // We're at the end of the RDN component, so add it to the |
| | | // list, skip over the comma/semicolon, and start on the |
| | | // next component. |
| | | rdnComponents.add(rdn); |
| | | pos++; |
| | | break; |
| | | } |
| | | else if (c != '+') |
| | | { |
| | | // This should not happen. At any rate, it's an illegal |
| | | // character, so throw an exception. |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_INVALID_CHAR; |
| | | String message = getMessage(msgID, dnString, c, pos); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Parses an attribute name from the provided DN string starting at |
| | | * the specified location. |
| | | * |
| | | * @param dnBytes The byte array containing the DN to |
| | | * parse. |
| | | * @param pos The position at which to start parsing |
| | | * the attribute name. |
| | | * @param attributeName The buffer to which to append the parsed |
| | | * attribute name. |
| | | * @param allowExceptions Indicates whether to allow certain |
| | | * exceptions to the strict requirements |
| | | * for attribute names. |
| | | * |
| | | * @return The position of the first character that is not part of |
| | | * the attribute name. |
| | | * |
| | | * @throws DirectoryException If it was not possible to parse a |
| | | * valid attribute name from the |
| | | * provided DN string. |
| | | */ |
| | | public static int parseAttributeName(byte[] dnBytes, int pos, |
| | | StringBuilder attributeName, |
| | | boolean allowExceptions) |
| | | throws DirectoryException |
| | | { |
| | | assert debugEnter(CLASS_NAME, "parseAttributeName", |
| | | String.valueOf(dnBytes), String.valueOf(pos), |
| | | "java.lang.StringBuilder"); |
| | | |
| | | int length = dnBytes.length; |
| | | |
| | | |
| | | // Skip over any leading spaces. |
| | | if (pos < length) |
| | | { |
| | | while (dnBytes[pos] == ' ') |
| | | { |
| | | pos++; |
| | | if (pos == length) |
| | | { |
| | | // This means that the remainder of the DN was completely |
| | | // comprised of spaces. If we have gotten here, then we |
| | | // know that there is at least one RDN component, and |
| | | // therefore the last non-space character of the DN must |
| | | // have been a comma. This is not acceptable. |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_END_WITH_COMMA; |
| | | String message = getMessage(msgID, new String(dnBytes)); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | // Next, we should find the attribute name for this RDN component. |
| | | // It may either be a name (with only letters, digits, and dashes |
| | | // and starting with a letter) or an OID (with only digits and |
| | | // periods, optionally prefixed with "oid."), and there is also a |
| | | // special case in which we will allow underscores. Because of |
| | | // the complexity involved, read the entire name first with |
| | | // minimal validation and then do more thorough validation later. |
| | | boolean checkForOID = false; |
| | | boolean endOfName = false; |
| | | while (pos < length) |
| | | { |
| | | // To make the switch more efficient, we'll include all ASCII |
| | | // characters in the range of allowed values and then reject the |
| | | // ones that aren't allowed. |
| | | byte b = dnBytes[pos]; |
| | | switch (b) |
| | | { |
| | | case ' ': |
| | | // This should denote the end of the attribute name. |
| | | endOfName = true; |
| | | break; |
| | | |
| | | |
| | | case '!': |
| | | case '"': |
| | | case '#': |
| | | case '$': |
| | | case '%': |
| | | case '&': |
| | | case '\'': |
| | | case '(': |
| | | case ')': |
| | | case '*': |
| | | case '+': |
| | | case ',': |
| | | // None of these are allowed in an attribute name or any |
| | | // character immediately following it. |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_ATTR_ILLEGAL_CHAR; |
| | | String message = getMessage(msgID, new String(dnBytes), |
| | | (char) b, pos); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | |
| | | |
| | | case '-': |
| | | // This will be allowed as long as it isn't the first |
| | | // character in the attribute name. |
| | | if (attributeName.length() > 0) |
| | | { |
| | | attributeName.append((char) b); |
| | | } |
| | | else |
| | | { |
| | | msgID = MSGID_ATTR_SYNTAX_DN_ATTR_ILLEGAL_INITIAL_DASH; |
| | | message = getMessage(msgID, new String(dnBytes), |
| | | (char) b); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | break; |
| | | |
| | | |
| | | case '.': |
| | | // The period could be allowed if the attribute name is |
| | | // actually expressed as an OID. We'll accept it for now, |
| | | // but make sure to check it later. |
| | | attributeName.append((char) b); |
| | | checkForOID = true; |
| | | break; |
| | | |
| | | |
| | | case '/': |
| | | // This is not allowed in an attribute name or any character |
| | | // immediately following it. |
| | | msgID = MSGID_ATTR_SYNTAX_DN_ATTR_ILLEGAL_CHAR; |
| | | message = getMessage(msgID, new String(dnBytes), |
| | | (char) b, pos); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | |
| | | |
| | | case '0': |
| | | case '1': |
| | | case '2': |
| | | case '3': |
| | | case '4': |
| | | case '5': |
| | | case '6': |
| | | case '7': |
| | | case '8': |
| | | case '9': |
| | | // Digits are always allowed if they are not the first |
| | | // character. However, they may be allowed if they are the |
| | | // first character if the valid is an OID or if the |
| | | // attribute name exceptions option is enabled. Therefore, |
| | | // we'll accept it now and check it later. |
| | | attributeName.append((char) b); |
| | | break; |
| | | |
| | | |
| | | case ':': |
| | | case ';': // NOTE: attribute options are not allowed in a DN. |
| | | case '<': |
| | | // None of these are allowed in an attribute name or any |
| | | // character immediately following it. |
| | | msgID = MSGID_ATTR_SYNTAX_DN_ATTR_ILLEGAL_CHAR; |
| | | message = getMessage(msgID, new String(dnBytes), |
| | | (char) b, pos); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | |
| | | |
| | | case '=': |
| | | // This should denote the end of the attribute name. |
| | | endOfName = true; |
| | | break; |
| | | |
| | | |
| | | case '>': |
| | | case '?': |
| | | case '@': |
| | | // None of these are allowed in an attribute name or any |
| | | // character immediately following it. |
| | | msgID = MSGID_ATTR_SYNTAX_DN_ATTR_ILLEGAL_CHAR; |
| | | message = getMessage(msgID, new String(dnBytes), |
| | | (char) b, pos); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | |
| | | |
| | | case 'A': |
| | | case 'B': |
| | | case 'C': |
| | | case 'D': |
| | | case 'E': |
| | | case 'F': |
| | | case 'G': |
| | | case 'H': |
| | | case 'I': |
| | | case 'J': |
| | | case 'K': |
| | | case 'L': |
| | | case 'M': |
| | | case 'N': |
| | | case 'O': |
| | | case 'P': |
| | | case 'Q': |
| | | case 'R': |
| | | case 'S': |
| | | case 'T': |
| | | case 'U': |
| | | case 'V': |
| | | case 'W': |
| | | case 'X': |
| | | case 'Y': |
| | | case 'Z': |
| | | // These will always be allowed. |
| | | attributeName.append((char) b); |
| | | break; |
| | | |
| | | |
| | | case '[': |
| | | case '\\': |
| | | case ']': |
| | | case '^': |
| | | // None of these are allowed in an attribute name or any |
| | | // character immediately following it. |
| | | msgID = MSGID_ATTR_SYNTAX_DN_ATTR_ILLEGAL_CHAR; |
| | | message = getMessage(msgID, new String(dnBytes), |
| | | (char) b, pos); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | |
| | | |
| | | case '_': |
| | | // This will never be allowed as the first character. It |
| | | // may be allowed for subsequent characters if the attribute |
| | | // name exceptions option is enabled. |
| | | if (attributeName.length() == 0) |
| | | { |
| | | msgID = |
| | | MSGID_ATTR_SYNTAX_DN_ATTR_ILLEGAL_INITIAL_UNDERSCORE; |
| | | message = getMessage(msgID, new String(dnBytes), |
| | | ATTR_ALLOW_ATTRIBUTE_NAME_EXCEPTIONS); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | else if (allowExceptions) |
| | | { |
| | | attributeName.append((char) b); |
| | | } |
| | | else |
| | | { |
| | | msgID = MSGID_ATTR_SYNTAX_DN_ATTR_ILLEGAL_UNDERSCORE_CHAR; |
| | | message = getMessage(msgID, new String(dnBytes), |
| | | ATTR_ALLOW_ATTRIBUTE_NAME_EXCEPTIONS); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | break; |
| | | |
| | | |
| | | case '`': |
| | | // This is not allowed in an attribute name or any character |
| | | // immediately following it. |
| | | msgID = MSGID_ATTR_SYNTAX_DN_ATTR_ILLEGAL_CHAR; |
| | | message = getMessage(msgID, new String(dnBytes), |
| | | (char) b, pos); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | |
| | | |
| | | case 'a': |
| | | case 'b': |
| | | case 'c': |
| | | case 'd': |
| | | case 'e': |
| | | case 'f': |
| | | case 'g': |
| | | case 'h': |
| | | case 'i': |
| | | case 'j': |
| | | case 'k': |
| | | case 'l': |
| | | case 'm': |
| | | case 'n': |
| | | case 'o': |
| | | case 'p': |
| | | case 'q': |
| | | case 'r': |
| | | case 's': |
| | | case 't': |
| | | case 'u': |
| | | case 'v': |
| | | case 'w': |
| | | case 'x': |
| | | case 'y': |
| | | case 'z': |
| | | // These will always be allowed. |
| | | attributeName.append((char) b); |
| | | break; |
| | | |
| | | |
| | | default: |
| | | // This is not allowed in an attribute name or any character |
| | | // immediately following it. |
| | | msgID = MSGID_ATTR_SYNTAX_DN_ATTR_ILLEGAL_CHAR; |
| | | message = getMessage(msgID, new String(dnBytes), |
| | | (char) b, pos); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | |
| | | |
| | | if (endOfName) |
| | | { |
| | | break; |
| | | } |
| | | |
| | | pos++; |
| | | } |
| | | |
| | | |
| | | // We should now have the full attribute name. However, we may |
| | | // still need to perform some validation, particularly if the name |
| | | // contains a period or starts with a digit. It must also have at |
| | | // least one character. |
| | | if (attributeName.length() == 0) |
| | | { |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_ATTR_NO_NAME; |
| | | String message = getMessage(msgID, new String(dnBytes)); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | else if (checkForOID) |
| | | { |
| | | boolean validOID = true; |
| | | |
| | | int namePos = 0; |
| | | int nameLength = attributeName.length(); |
| | | char ch = attributeName.charAt(0); |
| | | if ((ch == 'o') || (ch == 'O')) |
| | | { |
| | | if (nameLength <= 4) |
| | | { |
| | | validOID = false; |
| | | } |
| | | else |
| | | { |
| | | if ((((ch = attributeName.charAt(1)) == 'i') || |
| | | (ch == 'I')) && |
| | | (((ch = attributeName.charAt(2)) == 'd') || |
| | | (ch == 'D')) && |
| | | (attributeName.charAt(3) == '.')) |
| | | { |
| | | attributeName.delete(0, 4); |
| | | nameLength -= 4; |
| | | } |
| | | else |
| | | { |
| | | validOID = false; |
| | | } |
| | | } |
| | | } |
| | | |
| | | while (validOID && (namePos < nameLength)) |
| | | { |
| | | ch = attributeName.charAt(namePos++); |
| | | if (isDigit(ch)) |
| | | { |
| | | while (validOID && (namePos < nameLength) && |
| | | isDigit(attributeName.charAt(namePos))) |
| | | { |
| | | namePos++; |
| | | } |
| | | |
| | | if ((namePos < nameLength) && |
| | | (attributeName.charAt(namePos) != '.')) |
| | | { |
| | | validOID = false; |
| | | } |
| | | } |
| | | else if (ch == '.') |
| | | { |
| | | if ((namePos == 1) || |
| | | (attributeName.charAt(namePos-2) == '.')) |
| | | { |
| | | validOID = false; |
| | | } |
| | | } |
| | | else |
| | | { |
| | | validOID = false; |
| | | } |
| | | } |
| | | |
| | | |
| | | if (validOID && (attributeName.charAt(nameLength-1) == '.')) |
| | | { |
| | | validOID = false; |
| | | } |
| | | |
| | | |
| | | if (! validOID) |
| | | { |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_ATTR_ILLEGAL_PERIOD; |
| | | String message = getMessage(msgID, new String(dnBytes), |
| | | attributeName.toString()); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | } |
| | | else if (isDigit(attributeName.charAt(0)) && (! allowExceptions)) |
| | | { |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_ATTR_ILLEGAL_INITIAL_DIGIT; |
| | | String message = getMessage(msgID, new String(dnBytes), |
| | | attributeName.charAt(0), |
| | | ATTR_ALLOW_ATTRIBUTE_NAME_EXCEPTIONS); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | |
| | | |
| | | return pos; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Parses an attribute name from the provided DN string starting at |
| | | * the specified location. |
| | | * |
| | | * @param dnString The DN string to be parsed. |
| | | * @param pos The position at which to start parsing |
| | | * the attribute name. |
| | | * @param attributeName The buffer to which to append the parsed |
| | | * attribute name. |
| | | * @param allowExceptions Indicates whether to allow certain |
| | | * exceptions to the strict requirements |
| | | * for attribute names. |
| | | * |
| | | * @return The position of the first character that is not part of |
| | | * the attribute name. |
| | | * |
| | | * @throws DirectoryException If it was not possible to parse a |
| | | * valid attribute name from the |
| | | * provided DN string. |
| | | */ |
| | | public static int parseAttributeName(String dnString, int pos, |
| | | StringBuilder attributeName, |
| | | boolean allowExceptions) |
| | | throws DirectoryException |
| | | { |
| | | assert debugEnter(CLASS_NAME, "parseAttributeName", |
| | | String.valueOf(dnString), String.valueOf(pos), |
| | | "java.lang.StringBuilder"); |
| | | |
| | | int length = dnString.length(); |
| | | |
| | | |
| | | // Skip over any leading spaces. |
| | | if (pos < length) |
| | | { |
| | | while (dnString.charAt(pos) == ' ') |
| | | { |
| | | pos++; |
| | | if (pos == length) |
| | | { |
| | | // This means that the remainder of the DN was completely |
| | | // comprised of spaces. If we have gotten here, then we |
| | | // know that there is at least one RDN component, and |
| | | // therefore the last non-space character of the DN must |
| | | // have been a comma. This is not acceptable. |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_END_WITH_COMMA; |
| | | String message = getMessage(msgID, dnString); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | } |
| | | } |
| | | |
| | | // Next, we should find the attribute name for this RDN component. |
| | | // It may either be a name (with only letters, digits, and dashes |
| | | // and starting with a letter) or an OID (with only digits and |
| | | // periods, optionally prefixed with "oid."), and there is also a |
| | | // special case in which we will allow underscores. Because of |
| | | // the complexity involved, read the entire name first with |
| | | // minimal validation and then do more thorough validation later. |
| | | boolean checkForOID = false; |
| | | boolean endOfName = false; |
| | | while (pos < length) |
| | | { |
| | | // To make the switch more efficient, we'll include all ASCII |
| | | // characters in the range of allowed values and then reject the |
| | | // ones that aren't allowed. |
| | | char c = dnString.charAt(pos); |
| | | switch (c) |
| | | { |
| | | case ' ': |
| | | // This should denote the end of the attribute name. |
| | | endOfName = true; |
| | | break; |
| | | |
| | | |
| | | case '!': |
| | | case '"': |
| | | case '#': |
| | | case '$': |
| | | case '%': |
| | | case '&': |
| | | case '\'': |
| | | case '(': |
| | | case ')': |
| | | case '*': |
| | | case '+': |
| | | case ',': |
| | | // None of these are allowed in an attribute name or any |
| | | // character immediately following it. |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_ATTR_ILLEGAL_CHAR; |
| | | String message = getMessage(msgID, dnString, c, pos); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | |
| | | |
| | | case '-': |
| | | // This will be allowed as long as it isn't the first |
| | | // character in the attribute name. |
| | | if (attributeName.length() > 0) |
| | | { |
| | | attributeName.append(c); |
| | | } |
| | | else |
| | | { |
| | | msgID = MSGID_ATTR_SYNTAX_DN_ATTR_ILLEGAL_INITIAL_DASH; |
| | | message = getMessage(msgID, dnString, c); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | break; |
| | | |
| | | |
| | | case '.': |
| | | // The period could be allowed if the attribute name is |
| | | // actually expressed as an OID. We'll accept it for now, |
| | | // but make sure to check it later. |
| | | attributeName.append(c); |
| | | checkForOID = true; |
| | | break; |
| | | |
| | | |
| | | case '/': |
| | | // This is not allowed in an attribute name or any character |
| | | // immediately following it. |
| | | msgID = MSGID_ATTR_SYNTAX_DN_ATTR_ILLEGAL_CHAR; |
| | | message = getMessage(msgID, dnString, c, pos); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | |
| | | |
| | | case '0': |
| | | case '1': |
| | | case '2': |
| | | case '3': |
| | | case '4': |
| | | case '5': |
| | | case '6': |
| | | case '7': |
| | | case '8': |
| | | case '9': |
| | | // Digits are always allowed if they are not the first |
| | | // character. However, they may be allowed if they are the |
| | | // first character if the valid is an OID or if the |
| | | // attribute name exceptions option is enabled. Therefore, |
| | | // we'll accept it now and check it later. |
| | | attributeName.append(c); |
| | | break; |
| | | |
| | | |
| | | case ':': |
| | | case ';': // NOTE: attribute options are not allowed in a DN. |
| | | case '<': |
| | | // None of these are allowed in an attribute name or any |
| | | // character immediately following it. |
| | | msgID = MSGID_ATTR_SYNTAX_DN_ATTR_ILLEGAL_CHAR; |
| | | message = getMessage(msgID, dnString, c, pos); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | |
| | | |
| | | case '=': |
| | | // This should denote the end of the attribute name. |
| | | endOfName = true; |
| | | break; |
| | | |
| | | |
| | | case '>': |
| | | case '?': |
| | | case '@': |
| | | // None of these are allowed in an attribute name or any |
| | | // character immediately following it. |
| | | msgID = MSGID_ATTR_SYNTAX_DN_ATTR_ILLEGAL_CHAR; |
| | | message = getMessage(msgID, dnString, c, pos); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | |
| | | |
| | | case 'A': |
| | | case 'B': |
| | | case 'C': |
| | | case 'D': |
| | | case 'E': |
| | | case 'F': |
| | | case 'G': |
| | | case 'H': |
| | | case 'I': |
| | | case 'J': |
| | | case 'K': |
| | | case 'L': |
| | | case 'M': |
| | | case 'N': |
| | | case 'O': |
| | | case 'P': |
| | | case 'Q': |
| | | case 'R': |
| | | case 'S': |
| | | case 'T': |
| | | case 'U': |
| | | case 'V': |
| | | case 'W': |
| | | case 'X': |
| | | case 'Y': |
| | | case 'Z': |
| | | // These will always be allowed. |
| | | attributeName.append(c); |
| | | break; |
| | | |
| | | |
| | | case '[': |
| | | case '\\': |
| | | case ']': |
| | | case '^': |
| | | // None of these are allowed in an attribute name or any |
| | | // character immediately following it. |
| | | msgID = MSGID_ATTR_SYNTAX_DN_ATTR_ILLEGAL_CHAR; |
| | | message = getMessage(msgID, dnString, c, pos); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | |
| | | |
| | | case '_': |
| | | // This will never be allowed as the first character. It |
| | | // may be allowed for subsequent characters if the attribute |
| | | // name exceptions option is enabled. |
| | | if (attributeName.length() == 0) |
| | | { |
| | | msgID = |
| | | MSGID_ATTR_SYNTAX_DN_ATTR_ILLEGAL_INITIAL_UNDERSCORE; |
| | | message = getMessage(msgID, dnString, |
| | | ATTR_ALLOW_ATTRIBUTE_NAME_EXCEPTIONS); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | else if (allowExceptions) |
| | | { |
| | | attributeName.append(c); |
| | | } |
| | | else |
| | | { |
| | | msgID = MSGID_ATTR_SYNTAX_DN_ATTR_ILLEGAL_UNDERSCORE_CHAR; |
| | | message = getMessage(msgID, dnString, |
| | | ATTR_ALLOW_ATTRIBUTE_NAME_EXCEPTIONS); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | break; |
| | | |
| | | |
| | | case '`': |
| | | // This is not allowed in an attribute name or any character |
| | | // immediately following it. |
| | | msgID = MSGID_ATTR_SYNTAX_DN_ATTR_ILLEGAL_CHAR; |
| | | message = getMessage(msgID, dnString, c, pos); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | |
| | | |
| | | case 'a': |
| | | case 'b': |
| | | case 'c': |
| | | case 'd': |
| | | case 'e': |
| | | case 'f': |
| | | case 'g': |
| | | case 'h': |
| | | case 'i': |
| | | case 'j': |
| | | case 'k': |
| | | case 'l': |
| | | case 'm': |
| | | case 'n': |
| | | case 'o': |
| | | case 'p': |
| | | case 'q': |
| | | case 'r': |
| | | case 's': |
| | | case 't': |
| | | case 'u': |
| | | case 'v': |
| | | case 'w': |
| | | case 'x': |
| | | case 'y': |
| | | case 'z': |
| | | // These will always be allowed. |
| | | attributeName.append(c); |
| | | break; |
| | | |
| | | |
| | | default: |
| | | // This is not allowed in an attribute name or any character |
| | | // immediately following it. |
| | | msgID = MSGID_ATTR_SYNTAX_DN_ATTR_ILLEGAL_CHAR; |
| | | message = getMessage(msgID, dnString, c, pos); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | |
| | | |
| | | if (endOfName) |
| | | { |
| | | break; |
| | | } |
| | | |
| | | pos++; |
| | | } |
| | | |
| | | |
| | | // We should now have the full attribute name. However, we may |
| | | // still need to perform some validation, particularly if the |
| | | // name contains a period or starts with a digit. It must also |
| | | // have at least one character. |
| | | if (attributeName.length() == 0) |
| | | { |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_ATTR_NO_NAME; |
| | | String message = getMessage(msgID, dnString); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | else if (checkForOID) |
| | | { |
| | | boolean validOID = true; |
| | | |
| | | int namePos = 0; |
| | | int nameLength = attributeName.length(); |
| | | char ch = attributeName.charAt(0); |
| | | if ((ch == 'o') || (ch == 'O')) |
| | | { |
| | | if (nameLength <= 4) |
| | | { |
| | | validOID = false; |
| | | } |
| | | else |
| | | { |
| | | if ((((ch = attributeName.charAt(1)) == 'i') || |
| | | (ch == 'I')) && |
| | | (((ch = attributeName.charAt(2)) == 'd') || |
| | | (ch == 'D')) && |
| | | (attributeName.charAt(3) == '.')) |
| | | { |
| | | attributeName.delete(0, 4); |
| | | nameLength -= 4; |
| | | } |
| | | else |
| | | { |
| | | validOID = false; |
| | | } |
| | | } |
| | | } |
| | | |
| | | while (validOID && (namePos < nameLength)) |
| | | { |
| | | ch = attributeName.charAt(namePos++); |
| | | if (isDigit(ch)) |
| | | { |
| | | while (validOID && (namePos < nameLength) && |
| | | isDigit(attributeName.charAt(namePos))) |
| | | { |
| | | namePos++; |
| | | } |
| | | |
| | | if ((namePos < nameLength) && |
| | | (attributeName.charAt(namePos) != '.')) |
| | | { |
| | | validOID = false; |
| | | } |
| | | } |
| | | else if (ch == '.') |
| | | { |
| | | if ((namePos == 1) || |
| | | (attributeName.charAt(namePos-2) == '.')) |
| | | { |
| | | validOID = false; |
| | | } |
| | | } |
| | | else |
| | | { |
| | | validOID = false; |
| | | } |
| | | } |
| | | |
| | | |
| | | if (validOID && (attributeName.charAt(nameLength-1) == '.')) |
| | | { |
| | | validOID = false; |
| | | } |
| | | |
| | | |
| | | if (! validOID) |
| | | { |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_ATTR_ILLEGAL_PERIOD; |
| | | String message = getMessage(msgID, dnString, |
| | | attributeName.toString()); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | } |
| | | else if (isDigit(attributeName.charAt(0)) && |
| | | (! allowExceptions)) |
| | | { |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_ATTR_ILLEGAL_INITIAL_DIGIT; |
| | | String message = getMessage(msgID, dnString, |
| | | attributeName.charAt(0), |
| | | ATTR_ALLOW_ATTRIBUTE_NAME_EXCEPTIONS); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | |
| | | |
| | | return pos; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Parses the attribute value from the provided DN string starting |
| | | * at the specified location. When the value has been parsed, it |
| | | * will be assigned to the provided ASN.1 octet string. |
| | | * |
| | | * @param dnBytes The byte array containing the DN to be |
| | | * parsed. |
| | | * @param pos The position of the first character in |
| | | * the attribute value to parse. |
| | | * @param attributeValue The ASN.1 octet string whose value should |
| | | * be set to the parsed attribute value when |
| | | * this method completes successfully. |
| | | * |
| | | * @return The position of the first character that is not part of |
| | | * the attribute value. |
| | | * |
| | | * @throws DirectoryException If it was not possible to parse a |
| | | * valid attribute value from the |
| | | * provided DN string. |
| | | */ |
| | | public static int parseAttributeValue(byte[] dnBytes, int pos, |
| | | ByteString attributeValue) |
| | | throws DirectoryException |
| | | { |
| | | assert debugEnter(CLASS_NAME, "parseAttributeValue", |
| | | String.valueOf(dnBytes), String.valueOf(pos), |
| | | "java.lang.StringBuilder"); |
| | | |
| | | |
| | | // All leading spaces have already been stripped so we can start |
| | | // reading the value. However, it may be empty so check for that. |
| | | int length = dnBytes.length; |
| | | if (pos >= length) |
| | | { |
| | | attributeValue.setValue(""); |
| | | return pos; |
| | | } |
| | | |
| | | |
| | | // Look at the first character. If it is an octothorpe (#), then |
| | | // that means that the value should be a hex string. |
| | | byte b = dnBytes[pos++]; |
| | | if (b == '#') |
| | | { |
| | | // The first two characters must be hex characters. |
| | | StringBuilder hexString = new StringBuilder(); |
| | | if ((pos+2) > length) |
| | | { |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_HEX_VALUE_TOO_SHORT; |
| | | String message = getMessage(msgID, new String(dnBytes)); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | |
| | | for (int i=0; i < 2; i++) |
| | | { |
| | | b = dnBytes[pos++]; |
| | | if (isHexDigit(b)) |
| | | { |
| | | hexString.append((char) b); |
| | | } |
| | | else |
| | | { |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_INVALID_HEX_DIGIT; |
| | | String message = getMessage(msgID, new String(dnBytes), |
| | | (char) b); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | } |
| | | |
| | | |
| | | // The rest of the value must be a multiple of two hex |
| | | // characters. The end of the value may be designated by the |
| | | // end of the DN, a comma or semicolon, a plus sign, or a space. |
| | | while (pos < length) |
| | | { |
| | | b = dnBytes[pos++]; |
| | | if (isHexDigit(b)) |
| | | { |
| | | hexString.append((char) b); |
| | | |
| | | if (pos < length) |
| | | { |
| | | b = dnBytes[pos++]; |
| | | if (isHexDigit(b)) |
| | | { |
| | | hexString.append((char) b); |
| | | } |
| | | else |
| | | { |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_INVALID_HEX_DIGIT; |
| | | String message = getMessage(msgID, new String(dnBytes), |
| | | (char) b); |
| | | throw new DirectoryException( |
| | | ResultCode.INVALID_DN_SYNTAX, message, |
| | | msgID); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_HEX_VALUE_TOO_SHORT; |
| | | String message = getMessage(msgID, new String(dnBytes)); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | } |
| | | else if ((b == ' ') || (b == ',') || (b == ';') || (b == '+')) |
| | | { |
| | | // This denotes the end of the value. |
| | | pos--; |
| | | break; |
| | | } |
| | | else |
| | | { |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_INVALID_HEX_DIGIT; |
| | | String message = getMessage(msgID, new String(dnBytes), |
| | | (char) b); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | } |
| | | |
| | | |
| | | // At this point, we should have a valid hex string. Convert it |
| | | // to a byte array and set that as the value of the provided |
| | | // octet string. |
| | | try |
| | | { |
| | | attributeValue.setValue(hexStringToByteArray( |
| | | hexString.toString())); |
| | | return pos; |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | assert debugException(CLASS_NAME, "parseAttributeValue", e); |
| | | |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_ATTR_VALUE_DECODE_FAILURE; |
| | | String message = getMessage(msgID, new String(dnBytes), |
| | | String.valueOf(e)); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | } |
| | | |
| | | |
| | | // If the first character is a quotation mark, then the value |
| | | // should continue until the corresponding closing quotation mark. |
| | | else if (b == '"') |
| | | { |
| | | int valueStartPos = pos; |
| | | |
| | | // Keep reading until we find a closing quotation mark. |
| | | while (true) |
| | | { |
| | | if (pos >= length) |
| | | { |
| | | // We hit the end of the DN before the closing quote. |
| | | // That's an error. |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_UNMATCHED_QUOTE; |
| | | String message = getMessage(msgID, new String(dnBytes)); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | |
| | | if (dnBytes[pos++] == '"') |
| | | { |
| | | // This is the end of the value. |
| | | break; |
| | | } |
| | | } |
| | | |
| | | byte[] valueBytes = new byte[pos - valueStartPos - 1]; |
| | | System.arraycopy(dnBytes, valueStartPos, valueBytes, 0, |
| | | valueBytes.length); |
| | | |
| | | try |
| | | { |
| | | attributeValue.setValue(valueBytes); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | assert debugException(CLASS_NAME, "parseAttributeValue", e); |
| | | |
| | | // This should never happen. Just in case, work around it by |
| | | // converting to a string and back. |
| | | String valueStr = new String(valueBytes); |
| | | attributeValue.setValue(valueStr); |
| | | } |
| | | return pos; |
| | | } |
| | | |
| | | |
| | | // Otherwise, use general parsing to find the end of the value. |
| | | else |
| | | { |
| | | // Keep reading until we find a comma/semicolon, a plus sign, or |
| | | // the end of the DN. |
| | | int valueStartPos = pos - 1; |
| | | |
| | | while (true) |
| | | { |
| | | if (pos >= length) |
| | | { |
| | | // This is the end of the DN and therefore the end of the |
| | | // value. |
| | | break; |
| | | } |
| | | |
| | | b = dnBytes[pos++]; |
| | | if ((b == ',') || (b == ';') || (b == '+')) |
| | | { |
| | | pos--; |
| | | break; |
| | | } |
| | | } |
| | | |
| | | |
| | | // Convert the byte buffer to an array. |
| | | byte[] valueBytes = new byte[pos - valueStartPos]; |
| | | System.arraycopy(dnBytes, valueStartPos, valueBytes, 0, |
| | | valueBytes.length); |
| | | |
| | | |
| | | // Strip off any unescaped spaces that may be at the end of the |
| | | // value. |
| | | boolean extraSpaces = false; |
| | | int lastPos = valueBytes.length - 1; |
| | | while (lastPos > 0) |
| | | { |
| | | if (valueBytes[lastPos] == ' ') |
| | | { |
| | | extraSpaces = true; |
| | | lastPos--; |
| | | } |
| | | else |
| | | { |
| | | break; |
| | | } |
| | | } |
| | | |
| | | if (extraSpaces) |
| | | { |
| | | byte[] newValueBytes = new byte[lastPos+1]; |
| | | System.arraycopy(valueBytes, 0, newValueBytes, 0, lastPos+1); |
| | | valueBytes = newValueBytes; |
| | | } |
| | | |
| | | |
| | | try |
| | | { |
| | | attributeValue.setValue(valueBytes); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | assert debugException(CLASS_NAME, "parseAttributeValue", e); |
| | | |
| | | // This should never happen. Just in case, work around it by |
| | | // converting to a string and back. |
| | | String valueStr = new String(valueBytes); |
| | | attributeValue.setValue(valueStr); |
| | | } |
| | | return pos; |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Parses the attribute value from the provided DN string starting |
| | | * at the specified location. When the value has been parsed, it |
| | | * will be assigned to the provided ASN.1 octet string. |
| | | * |
| | | * @param dnString The DN string to be parsed. |
| | | * @param pos The position of the first character in |
| | | * the attribute value to parse. |
| | | * @param attributeValue The ASN.1 octet string whose value should |
| | | * be set to the parsed attribute value when |
| | | * this method completes successfully. |
| | | * |
| | | * @return The position of the first character that is not part of |
| | | * the attribute value. |
| | | * |
| | | * @throws DirectoryException If it was not possible to parse a |
| | | * valid attribute value from the |
| | | * provided DN string. |
| | | */ |
| | | public static int parseAttributeValue(String dnString, int pos, |
| | | ByteString attributeValue) |
| | | throws DirectoryException |
| | | { |
| | | assert debugEnter(CLASS_NAME, "parseAttributeValue", |
| | | String.valueOf(dnString), String.valueOf(pos), |
| | | "java.lang.StringBuilder"); |
| | | |
| | | |
| | | // All leading spaces have already been stripped so we can start |
| | | // reading the value. However, it may be empty so check for that. |
| | | int length = dnString.length(); |
| | | if (pos >= length) |
| | | { |
| | | attributeValue.setValue(""); |
| | | return pos; |
| | | } |
| | | |
| | | |
| | | // Look at the first character. If it is an octothorpe (#), then |
| | | // that means that the value should be a hex string. |
| | | char c = dnString.charAt(pos++); |
| | | if (c == '#') |
| | | { |
| | | // The first two characters must be hex characters. |
| | | StringBuilder hexString = new StringBuilder(); |
| | | if ((pos+2) > length) |
| | | { |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_HEX_VALUE_TOO_SHORT; |
| | | String message = getMessage(msgID, dnString); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | |
| | | for (int i=0; i < 2; i++) |
| | | { |
| | | c = dnString.charAt(pos++); |
| | | if (isHexDigit(c)) |
| | | { |
| | | hexString.append(c); |
| | | } |
| | | else |
| | | { |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_INVALID_HEX_DIGIT; |
| | | String message = getMessage(msgID, dnString, c); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | } |
| | | |
| | | |
| | | // The rest of the value must be a multiple of two hex |
| | | // characters. The end of the value may be designated by the |
| | | // end of the DN, a comma or semicolon, or a space. |
| | | while (pos < length) |
| | | { |
| | | c = dnString.charAt(pos++); |
| | | if (isHexDigit(c)) |
| | | { |
| | | hexString.append(c); |
| | | |
| | | if (pos < length) |
| | | { |
| | | c = dnString.charAt(pos++); |
| | | if (isHexDigit(c)) |
| | | { |
| | | hexString.append(c); |
| | | } |
| | | else |
| | | { |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_INVALID_HEX_DIGIT; |
| | | String message = getMessage(msgID, dnString, c); |
| | | throw new DirectoryException( |
| | | ResultCode.INVALID_DN_SYNTAX, message, |
| | | msgID); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_HEX_VALUE_TOO_SHORT; |
| | | String message = getMessage(msgID, dnString); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | } |
| | | else if ((c == ' ') || (c == ',') || (c == ';')) |
| | | { |
| | | // This denotes the end of the value. |
| | | pos--; |
| | | break; |
| | | } |
| | | else |
| | | { |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_INVALID_HEX_DIGIT; |
| | | String message = getMessage(msgID, dnString, c); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | } |
| | | |
| | | |
| | | // At this point, we should have a valid hex string. Convert it |
| | | // to a byte array and set that as the value of the provided |
| | | // octet string. |
| | | try |
| | | { |
| | | attributeValue.setValue(hexStringToByteArray( |
| | | hexString.toString())); |
| | | return pos; |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | assert debugException(CLASS_NAME, "parseAttributeValue", e); |
| | | |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_ATTR_VALUE_DECODE_FAILURE; |
| | | String message = getMessage(msgID, dnString, |
| | | String.valueOf(e)); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | } |
| | | |
| | | |
| | | // If the first character is a quotation mark, then the value |
| | | // should continue until the corresponding closing quotation mark. |
| | | else if (c == '"') |
| | | { |
| | | // Keep reading until we find an unescaped closing quotation |
| | | // mark. |
| | | boolean escaped = false; |
| | | StringBuilder valueString = new StringBuilder(); |
| | | while (true) |
| | | { |
| | | if (pos >= length) |
| | | { |
| | | // We hit the end of the DN before the closing quote. |
| | | // That's an error. |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_UNMATCHED_QUOTE; |
| | | String message = getMessage(msgID, dnString); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | |
| | | c = dnString.charAt(pos++); |
| | | if (escaped) |
| | | { |
| | | // The previous character was an escape, so we'll take this |
| | | // one no matter what. |
| | | valueString.append(c); |
| | | escaped = false; |
| | | } |
| | | else if (c == '\\') |
| | | { |
| | | // The next character is escaped. Set a flag to denote |
| | | // this, but don't include the backslash. |
| | | escaped = true; |
| | | } |
| | | else if (c == '"') |
| | | { |
| | | // This is the end of the value. |
| | | break; |
| | | } |
| | | else |
| | | { |
| | | // This is just a regular character that should be in the |
| | | // value. |
| | | valueString.append(c); |
| | | } |
| | | } |
| | | |
| | | attributeValue.setValue(valueString.toString()); |
| | | return pos; |
| | | } |
| | | |
| | | |
| | | // Otherwise, use general parsing to find the end of the value. |
| | | else |
| | | { |
| | | boolean escaped; |
| | | StringBuilder valueString = new StringBuilder(); |
| | | StringBuilder hexChars = new StringBuilder(); |
| | | |
| | | if (c == '\\') |
| | | { |
| | | escaped = true; |
| | | } |
| | | else |
| | | { |
| | | escaped = false; |
| | | valueString.append(c); |
| | | } |
| | | |
| | | |
| | | // Keep reading until we find an unescaped comma or plus sign or |
| | | // the end of the DN. |
| | | while (true) |
| | | { |
| | | if (pos >= length) |
| | | { |
| | | // This is the end of the DN and therefore the end of the |
| | | // value. If there are any hex characters, then we need to |
| | | // deal with them accordingly. |
| | | appendHexChars(dnString, valueString, hexChars); |
| | | break; |
| | | } |
| | | |
| | | c = dnString.charAt(pos++); |
| | | if (escaped) |
| | | { |
| | | // The previous character was an escape, so we'll take this |
| | | // one. However, this could be a hex digit, and if that's |
| | | // the case then the escape would actually be in front of |
| | | // two hex digits that should be treated as a special |
| | | // character. |
| | | if (isHexDigit(c)) |
| | | { |
| | | // It is a hexadecimal digit, so the next digit must be |
| | | // one too. However, this could be just one in a series |
| | | // of escaped hex pairs that is used in a string |
| | | // containing one or more multi-byte UTF-8 characters so |
| | | // we can't just treat this byte in isolation. Collect |
| | | // all the bytes together and make sure to take care of |
| | | // these hex bytes before appending anything else to the |
| | | // value. |
| | | if (pos >= length) |
| | | { |
| | | int msgID = |
| | | MSGID_ATTR_SYNTAX_DN_ESCAPED_HEX_VALUE_INVALID; |
| | | String message = getMessage(msgID, dnString); |
| | | throw new DirectoryException( |
| | | ResultCode.INVALID_DN_SYNTAX, message, |
| | | msgID); |
| | | } |
| | | else |
| | | { |
| | | char c2 = dnString.charAt(pos++); |
| | | if (isHexDigit(c2)) |
| | | { |
| | | hexChars.append(c); |
| | | hexChars.append(c2); |
| | | } |
| | | else |
| | | { |
| | | int msgID = |
| | | MSGID_ATTR_SYNTAX_DN_ESCAPED_HEX_VALUE_INVALID; |
| | | String message = getMessage(msgID, dnString); |
| | | throw new DirectoryException( |
| | | ResultCode.INVALID_DN_SYNTAX, message, |
| | | msgID); |
| | | } |
| | | } |
| | | } |
| | | else |
| | | { |
| | | appendHexChars(dnString, valueString, hexChars); |
| | | valueString.append(c); |
| | | } |
| | | |
| | | escaped = false; |
| | | } |
| | | else if (c == '\\') |
| | | { |
| | | escaped = true; |
| | | } |
| | | else if ((c == ',') || (c == ';')) |
| | | { |
| | | appendHexChars(dnString, valueString, hexChars); |
| | | pos--; |
| | | break; |
| | | } |
| | | else if (c == '+') |
| | | { |
| | | appendHexChars(dnString, valueString, hexChars); |
| | | pos--; |
| | | break; |
| | | } |
| | | else |
| | | { |
| | | appendHexChars(dnString, valueString, hexChars); |
| | | valueString.append(c); |
| | | } |
| | | } |
| | | |
| | | |
| | | // Strip off any unescaped spaces that may be at the end of the |
| | | // value. |
| | | if (pos > 2 && dnString.charAt(pos-1) == ' ' && |
| | | dnString.charAt(pos-2) != '\\') |
| | | { |
| | | int lastPos = valueString.length() - 1; |
| | | while (lastPos > 0) |
| | | { |
| | | if (valueString.charAt(lastPos) == ' ') |
| | | { |
| | | valueString.delete(lastPos, lastPos+1); |
| | | lastPos--; |
| | | } |
| | | else |
| | | { |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | attributeValue.setValue(valueString.toString()); |
| | | return pos; |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Decodes a hexadecimal string from the provided |
| | | * <CODE>hexChars</CODE> buffer, converts it to a byte array, and |
| | | * then converts that to a UTF-8 string. The resulting UTF-8 string |
| | | * will be appended to the provided <CODE>valueString</CODE> buffer, |
| | | * and the <CODE>hexChars</CODE> buffer will be cleared. |
| | | * |
| | | * @param dnString The DN string that is being decoded. |
| | | * @param valueString The buffer containing the value to which the |
| | | * decoded string should be appended. |
| | | * @param hexChars The buffer containing the hexadecimal |
| | | * characters to decode to a UTF-8 string. |
| | | * |
| | | * @throws DirectoryException If any problem occurs during the |
| | | * decoding process. |
| | | */ |
| | | public static void appendHexChars(String dnString, |
| | | StringBuilder valueString, |
| | | StringBuilder hexChars) |
| | | throws DirectoryException |
| | | { |
| | | try |
| | | { |
| | | byte[] hexBytes = hexStringToByteArray(hexChars.toString()); |
| | | valueString.append(new String(hexBytes, "UTF-8")); |
| | | hexChars.delete(0, hexChars.length()); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | assert debugException(CLASS_NAME, "appendHexChars", e); |
| | | |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_ATTR_VALUE_DECODE_FAILURE; |
| | | String message = getMessage(msgID, dnString, String.valueOf(e)); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a duplicate of this DN that can be modified without |
| | | * impacting this DN. |
| | | * |
| | | * @return A duplicate of this DN that can be modified without |
| | | * impacting this DN. |
| | | */ |
| | | public DN duplicate() |
| | | { |
| | | assert debugEnter(CLASS_NAME, "duplicate"); |
| | | |
| | | RDN[] rdnCopy = new RDN[numComponents]; |
| | | for (int i=0; i < numComponents; i++) |
| | | { |
| | | rdnCopy[i] = rdnComponents[i].duplicate(); |
| | | } |
| | | |
| | | return new DN(rdnCopy); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether the provided object is equal to this DN. In |
| | | * order for the object to be considered equal, it must be a DN with |
| | | * the same number of RDN components and each corresponding RDN |
| | | * component must be equal. |
| | | * |
| | | * @param o The object for which to make the determination. |
| | | * |
| | | * @return <CODE>true</CODE> if the provided object is a DN that is |
| | | * equal to this DN, or <CODE>false</CODE> if it is not. |
| | | * @param o |
| | | * The object for which to make the determination. |
| | | * @return <code>true</code> if the provided object is a DN that |
| | | * is equal to this DN, or <code>false</code> if it is |
| | | * not. |
| | | */ |
| | | public boolean equals(Object o) |
| | | { |
| | | public boolean equals(Object o) { |
| | | assert debugEnter(CLASS_NAME, "equals", String.valueOf(o)); |
| | | |
| | | if (this == o) |
| | | { |
| | | if (this == o) { |
| | | return true; |
| | | } |
| | | |
| | | if (o == null) |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | try |
| | | { |
| | | return (normalizedDN.equals(((DN) o).normalizedDN)); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | // This most likely means that the object was null or wasn't a |
| | | // DN. In either case, it's faster to assume that it is and |
| | | // return false on an exception than to perform the checks to |
| | | // see if it meets the appropriate |
| | | // conditions. |
| | | assert debugException(CLASS_NAME, "equals", e); |
| | | |
| | | } else if (o instanceof DN) { |
| | | DN other = (DN) o; |
| | | return normalizedDN.equals(other.normalizedDN); |
| | | } else { |
| | | return false; |
| | | } |
| | | } |
| | |
| | | * |
| | | * @return The hash code for this DN. |
| | | */ |
| | | public int hashCode() |
| | | { |
| | | public int hashCode() { |
| | | assert debugEnter(CLASS_NAME, "hashCode"); |
| | | |
| | | return normalizedDN.hashCode(); |
| | |
| | | * |
| | | * @return A string representation of this DN. |
| | | */ |
| | | public String toString() |
| | | { |
| | | public String toString() { |
| | | assert debugEnter(CLASS_NAME, "toString"); |
| | | |
| | | if (dnString == null) |
| | | { |
| | | if (numComponents == 0) |
| | | { |
| | | dnString = ""; |
| | | } |
| | | else |
| | | { |
| | | StringBuilder buffer = new StringBuilder(); |
| | | rdnComponents[0].toString(buffer); |
| | | |
| | | for (int i=1; i < numComponents; i++) |
| | | { |
| | | buffer.append(","); |
| | | rdnComponents[i].toString(buffer); |
| | | } |
| | | |
| | | dnString = buffer.toString(); |
| | | } |
| | | } |
| | | |
| | | return dnString; |
| | | StringBuilder builder = new StringBuilder(); |
| | | toString(builder); |
| | | return builder.toString(); |
| | | } |
| | | |
| | | |
| | |
| | | * Appends a string representation of this DN to the provided |
| | | * buffer. |
| | | * |
| | | * @param buffer The buffer to which the information should be |
| | | * appended. |
| | | * @param buffer |
| | | * The buffer to which the information should be appended. |
| | | */ |
| | | public void toString(StringBuilder buffer) |
| | | { |
| | | public void toString(StringBuilder buffer) { |
| | | assert debugEnter(CLASS_NAME, "toString", |
| | | "java.lang.StringBuilder"); |
| | | |
| | | buffer.append(toString()); |
| | | ensureNotNull(buffer); |
| | | |
| | | if (numComponents != 0) { |
| | | getRDN(0).toString(buffer); |
| | | |
| | | for (int i = 1; i < numComponents; i++) { |
| | | buffer.append(","); |
| | | getRDN(i).toString(buffer); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | |
| | | * |
| | | * @return A normalized string representation of this DN. |
| | | */ |
| | | public String toNormalizedString() |
| | | { |
| | | public String toNormalizedString() { |
| | | assert debugEnter(CLASS_NAME, "toNormalizedString"); |
| | | |
| | | if (normalizedDN == null) |
| | | { |
| | | if (numComponents == 0) |
| | | { |
| | | normalizedDN = ""; |
| | | } |
| | | else |
| | | { |
| | | StringBuilder buffer = new StringBuilder(); |
| | | rdnComponents[0].toNormalizedString(buffer); |
| | | |
| | | for (int i=1; i < numComponents; i++) |
| | | { |
| | | buffer.append(','); |
| | | rdnComponents[i].toNormalizedString(buffer); |
| | | } |
| | | |
| | | normalizedDN = buffer.toString(); |
| | | } |
| | | } |
| | | |
| | | return normalizedDN; |
| | | } |
| | | |
| | |
| | | * Appends a normalized string representation of this DN to the |
| | | * provided buffer. |
| | | * |
| | | * @param buffer The buffer to which the information should be |
| | | * appended. |
| | | * @param buffer |
| | | * The buffer to which the information should be appended. |
| | | */ |
| | | public void toNormalizedString(StringBuilder buffer) |
| | | { |
| | | public void toNormalizedString(StringBuilder buffer) { |
| | | assert debugEnter(CLASS_NAME, "toNormalizedString", |
| | | "java.lang.StringBuilder"); |
| | | |
| | | buffer.append(toNormalizedString()); |
| | | ensureNotNull(buffer); |
| | | |
| | | buffer.append(normalizedDN); |
| | | } |
| | | |
| | | |
| | |
| | | * This order will be first hierarchical (ancestors will come before |
| | | * descendants) and then alphabetical by attribute name(s) and |
| | | * value(s). |
| | | * <p> |
| | | * NOTE: the implementation of this method does not perform a |
| | | * lexicographic comparison of the DN's normalized form. Instead, |
| | | * each individual RDN is compared using ordering matching rules |
| | | * where possible. |
| | | * |
| | | * @param dn The DN against which to compare this DN. |
| | | * |
| | | * @param dn |
| | | * The DN against which to compare this DN. |
| | | * @return A negative integer if this DN should come before the |
| | | * provided DN, a positive integer if this DN should come |
| | | * after the provided DN, or zero if there is no difference |
| | | * with regard to ordering. |
| | | */ |
| | | public int compareTo(DN dn) |
| | | { |
| | | assert debugEnter(CLASS_NAME, "compareTo", String.valueOf(dn)); |
| | | public int compareTo(DN dn) { |
| | | assert debugEnter(CLASS_NAME, "compareTo", String.valueOf(this), |
| | | String.valueOf(dn)); |
| | | |
| | | if (equals(dn)) |
| | | { |
| | | return 0; |
| | | ensureNotNull(dn); |
| | | |
| | | int index1 = numComponents - 1; |
| | | int index2 = dn.numComponents - 1; |
| | | |
| | | while (true) { |
| | | if (index1 >= 0) { |
| | | if (index2 >= 0) { |
| | | int value = getRDN(index1).compareTo(dn.getRDN(index2)); |
| | | if (value != 0) { |
| | | return value; |
| | | } |
| | | else if (isNullDN()) |
| | | { |
| | | return -1; |
| | | } |
| | | else if (dn.isNullDN()) |
| | | { |
| | | } else { |
| | | return 1; |
| | | } |
| | | else if (isAncestorOf(dn)) |
| | | { |
| | | } else if (index2 >= 0) { |
| | | return -1; |
| | | } |
| | | else if (isDescendantOf(dn)) |
| | | { |
| | | return 1; |
| | | } |
| | | else |
| | | { |
| | | int minComps = Math.min(numComponents, dn.numComponents); |
| | | for (int i=0; i < minComps; i++) |
| | | { |
| | | RDN r1 = rdnComponents[rdnComponents.length-1-i]; |
| | | RDN r2 = dn.rdnComponents[dn.rdnComponents.length-1-i]; |
| | | int result = r1.compareTo(r2); |
| | | if (result != 0) |
| | | { |
| | | return result; |
| | | } |
| | | } |
| | | |
| | | } else { |
| | | return 0; |
| | | } |
| | | |
| | | index1--; |
| | | index2--; |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Construct the normalized form of this DN. |
| | | * |
| | | * @return Returns the normalized string representation of this DN. |
| | | */ |
| | | private String normalize() { |
| | | if (numComponents == 0) { |
| | | return ""; |
| | | } else { |
| | | StringBuilder buffer = new StringBuilder(); |
| | | getRDN(0).toNormalizedString(buffer); |
| | | |
| | | for (int i = 1; i < numComponents; i++) { |
| | | buffer.append(','); |
| | | getRDN(i).toNormalizedString(buffer); |
| | | } |
| | | |
| | | return buffer.toString(); |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | if (dn == null) |
| | | { |
| | | this.dn = new DN(new ArrayList<RDN>(0)); |
| | | this.dn = DN.nullDN(); |
| | | } |
| | | else |
| | | { |
| | |
| | | |
| | | if (dn == null) |
| | | { |
| | | this.dn = new DN(new ArrayList<RDN>(0)); |
| | | this.dn = DN.nullDN(); |
| | | } |
| | | else |
| | | { |
| | |
| | | } |
| | | |
| | | // Make sure that all attributes in the RDN are allowed. |
| | | for (AttributeType t : rdn.getAttributeTypes()) |
| | | int numAVAs = rdn.getNumValues(); |
| | | for (int i = 0; i < numAVAs; i++) |
| | | { |
| | | AttributeType t = rdn.getAttributeType(i); |
| | | if (! nameForm.isRequiredOrOptional(t)) |
| | | { |
| | | int msgID = MSGID_ENTRY_SCHEMA_RDN_DISALLOWED_ATTR; |
| | |
| | | else |
| | | { |
| | | // Get the DN of the parent entry if possible. |
| | | DN parentDN = dn.getParent(); |
| | | DN parentDN = dn.getParentDNInSuffix(); |
| | | if (parentDN != null) |
| | | { |
| | | // Get the parent entry and check its structural |
| | |
| | | { |
| | | assert debugEnter(CLASS_NAME, "duplicate"); |
| | | |
| | | DN dnCopy = dn.duplicate(); |
| | | |
| | | HashMap<ObjectClass,String> objectClassesCopy = |
| | | new HashMap<ObjectClass,String>(objectClasses); |
| | | |
| | |
| | | operationalAttributes.size()); |
| | | deepCopy(operationalAttributes, operationalAttrsCopy, false); |
| | | |
| | | return new Entry(dnCopy, objectClassesCopy, userAttrsCopy, |
| | | return new Entry(dn, objectClassesCopy, userAttrsCopy, |
| | | operationalAttrsCopy); |
| | | } |
| | | |
| | |
| | | { |
| | | assert debugEnter(CLASS_NAME, "duplicate"); |
| | | |
| | | DN dnCopy = dn.duplicate(); |
| | | |
| | | HashMap<ObjectClass,String> objectClassesCopy; |
| | | if (typesOnly) |
| | | { |
| | |
| | | HashMap<AttributeType,List<Attribute>> operationalAttrsCopy = |
| | | new HashMap<AttributeType,List<Attribute>>(0); |
| | | |
| | | return new Entry(dnCopy, objectClassesCopy, userAttrsCopy, |
| | | return new Entry(dn, objectClassesCopy, userAttrsCopy, |
| | | operationalAttrsCopy); |
| | | } |
| | | |
| | |
| | | { |
| | | assert debugEnter(CLASS_NAME, "duplicate"); |
| | | |
| | | DN dnCopy = dn.duplicate(); |
| | | |
| | | HashMap<ObjectClass,String> objectClassesCopy = |
| | | new HashMap<ObjectClass,String>(objectClasses.size()); |
| | | |
| | |
| | | new HashMap<AttributeType,List<Attribute>>( |
| | | operationalAttributes.size()); |
| | | |
| | | return new Entry(dnCopy, objectClassesCopy, userAttrsCopy, |
| | | return new Entry(dn, objectClassesCopy, userAttrsCopy, |
| | | operationalAttrsCopy); |
| | | } |
| | | |
| | |
| | | |
| | | case SINGLE_LEVEL: |
| | | // The parent DN for this entry must equal the base DN. |
| | | return baseDN.equals(dn.getParent()); |
| | | return baseDN.equals(dn.getParentDNInSuffix()); |
| | | |
| | | case WHOLE_SUBTREE: |
| | | // The base DN must be an ancestor of the entry DN. |
| | |
| | | /** |
| | | * The default base DN that will be used if none is provided. |
| | | */ |
| | | public static final DN DEFAULT_BASE_DN = new DN(); |
| | | public static final DN DEFAULT_BASE_DN = DN.nullDN(); |
| | | |
| | | |
| | | |
| | |
| | | |
| | | |
| | | |
| | | import static org.opends.server.config.ConfigConstants.*; |
| | | import static org.opends.server.loggers.Debug.*; |
| | | import static org.opends.server.messages.CoreMessages.*; |
| | | import static org.opends.server.messages.MessageHandler.getMessage; |
| | | import static org.opends.server.messages.SchemaMessages.*; |
| | | import static org.opends.server.util.StaticUtils.*; |
| | | import static org.opends.server.util.Validator.ensureNotNull; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.Iterator; |
| | | import java.util.List; |
| | | import java.util.TreeSet; |
| | | import java.util.TreeMap; |
| | | |
| | | import org.opends.server.api.OrderingMatchingRule; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.protocols.asn1.ASN1OctetString; |
| | | |
| | | import static org.opends.server.loggers.Debug.*; |
| | | import static org.opends.server.messages.CoreMessages.*; |
| | | import static org.opends.server.messages.MessageHandler.*; |
| | | import static org.opends.server.util.StaticUtils.*; |
| | | import org.opends.server.util.StaticUtils; |
| | | |
| | | |
| | | |
| | |
| | | * This class defines a data structure for storing and interacting |
| | | * with the relative distinguished names associated with entries in |
| | | * the Directory Server. |
| | | * <p> |
| | | * All the methods in this class will throw a |
| | | * <code>NullPointerException</code> when provided with |
| | | * <code>null</code> reference parameters unless otherwise stated. |
| | | */ |
| | | public class RDN |
| | | implements Comparable<RDN> |
| | | { |
| | | public final class RDN implements Comparable<RDN> { |
| | | // TODO: per-thread cache of common RDNs? |
| | | |
| | | // TODO: implement pimpl idiom and provide a "singleton" |
| | | // implementation for common case where the RDN only has a single |
| | | // type and value. This would result in less memory being used. |
| | | |
| | | /** |
| | | * The fully-qualified name of this class for debugging purposes. |
| | | */ |
| | | private static final String CLASS_NAME = |
| | | "org.opends.server.types.RDN"; |
| | | |
| | | |
| | | |
| | | // The set of attribute types for the elements in this RDN. |
| | | private AttributeType[] attributeTypes; |
| | | |
| | | // The set of values for the elements in this RDN. |
| | | private AttributeValue[] attributeValues; |
| | | |
| | | // The number of values for this RDN. |
| | | private int numValues; |
| | | |
| | | // The string representation of the normalized form of this RDN. |
| | | private String normalizedRDN; |
| | | |
| | | // The string representation of this RDN. |
| | | private String rdnString; |
| | | private final AttributeType[] attributeTypes; |
| | | |
| | | // The set of user-provided names for the attributes in this RDN. |
| | | private String[] attributeNames; |
| | | private final String[] attributeNames; |
| | | |
| | | // The set of values for the elements in this RDN. |
| | | private final AttributeValue[] attributeValues; |
| | | |
| | | /** |
| | | * The cached normalized string representation of this RDN. |
| | | * |
| | | * This non-final field will default to null. The Java memory model |
| | | * guarantees that it will be initialized to null before being |
| | | * visible to other threads. |
| | | */ |
| | | private String normalizedRDN; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new RDN with the provided information. |
| | | * |
| | | * @param attributeType The attribute type for this RDN. |
| | | * @param attributeValue The value for this RDN. |
| | | * @param type |
| | | * The attribute type for this RDN. |
| | | * @param value |
| | | * The value for this RDN. |
| | | * @return Returns the new RDN. |
| | | */ |
| | | public RDN(AttributeType attributeType, |
| | | AttributeValue attributeValue) |
| | | { |
| | | assert debugConstructor(CLASS_NAME, String.valueOf(attributeType), |
| | | String.valueOf(attributeValue)); |
| | | |
| | | attributeTypes = new AttributeType[] { attributeType }; |
| | | attributeNames = new String[] { attributeType.getPrimaryName() }; |
| | | attributeValues = new AttributeValue[] { attributeValue }; |
| | | |
| | | numValues = 1; |
| | | rdnString = null; |
| | | normalizedRDN = null; |
| | | public static RDN create(AttributeType type, AttributeValue value) { |
| | | return create(type, type.getNameOrOID(), value); |
| | | } |
| | | |
| | | |
| | |
| | | /** |
| | | * Creates a new RDN with the provided information. |
| | | * |
| | | * @param attributeType The attribute type for this RDN. |
| | | * @param attributeName The user-provided name for this RDN. |
| | | * @param attributeValue The value for this RDN. |
| | | * @param type |
| | | * The attribute type for this RDN. |
| | | * @param name |
| | | * The user-provided name for this RDN. |
| | | * @param value |
| | | * The value for this RDN. |
| | | * @return Returns the new RDN. |
| | | */ |
| | | public RDN(AttributeType attributeType, String attributeName, |
| | | AttributeValue attributeValue) |
| | | { |
| | | assert debugConstructor(CLASS_NAME, String.valueOf(attributeType), |
| | | String.valueOf(attributeName), |
| | | String.valueOf(attributeValue)); |
| | | public static RDN create(AttributeType type, String name, |
| | | AttributeValue value) { |
| | | ensureNotNull(type, name, value); |
| | | |
| | | attributeTypes = new AttributeType[] { attributeType }; |
| | | attributeNames = new String[] { attributeName }; |
| | | attributeValues = new AttributeValue[] { attributeValue }; |
| | | AttributeType[] types = new AttributeType[] { type }; |
| | | String[] names = new String[] { name }; |
| | | AttributeValue[] values = new AttributeValue[] { value }; |
| | | |
| | | numValues = 1; |
| | | rdnString = null; |
| | | normalizedRDN = null; |
| | | return new RDN(types, names, values); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new RDN with the provided information. The number of |
| | | * type, name, and value elements must be nonzero and equal. |
| | | * Create a new RDN builder which can be used to incrementally build |
| | | * a new RDN. |
| | | * |
| | | * @param attributeTypes The set of attribute types for this RDN. |
| | | * @param attributeNames The set of user-provided names for this |
| | | * RDN. |
| | | * @param attributeValues The set of values for this RDN. |
| | | * @return Returns the new RDN builder. |
| | | */ |
| | | public RDN(List<AttributeType> attributeTypes, |
| | | List<String> attributeNames, |
| | | List<AttributeValue> attributeValues) |
| | | { |
| | | assert debugConstructor(CLASS_NAME, |
| | | String.valueOf(attributeTypes), |
| | | String.valueOf(attributeNames), |
| | | String.valueOf(attributeValues)); |
| | | |
| | | this.attributeTypes = new AttributeType[attributeTypes.size()]; |
| | | this.attributeNames = new String[attributeNames.size()]; |
| | | this.attributeValues = new AttributeValue[attributeValues.size()]; |
| | | |
| | | attributeTypes.toArray(this.attributeTypes); |
| | | attributeNames.toArray(this.attributeNames); |
| | | attributeValues.toArray(this.attributeValues); |
| | | |
| | | numValues = attributeTypes.size(); |
| | | rdnString = null; |
| | | normalizedRDN = null; |
| | | public static Builder createBuilder() { |
| | | return new Builder(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new RDN with the provided information. The number of |
| | | * type, name, and value elements must be nonzero and equal. |
| | | * |
| | | * @param attributeTypes The set of attribute types for this RDN. |
| | | * @param attributeNames The set of user-provided names for this |
| | | * RDN. |
| | | * @param attributeValues The set of values for this RDN. |
| | | * This class provides an interface for constructing RDNs |
| | | * incrementally. |
| | | * <p> |
| | | * Typically, an application will construct a new |
| | | * <code>Builder</code> and append attribute value assertions |
| | | * (AVAs) using the <code>append</code> method. When the RDN is |
| | | * fully constructed, it can be retrieved using the |
| | | * <code>getInstance</code> method. |
| | | */ |
| | | public RDN(AttributeType[] attributeTypes, String[] attributeNames, |
| | | AttributeValue[] attributeValues) |
| | | { |
| | | assert debugConstructor(CLASS_NAME, |
| | | String.valueOf(attributeTypes), |
| | | String.valueOf(attributeNames), |
| | | String.valueOf(attributeValues)); |
| | | public static final class Builder { |
| | | // The list of attribute types. |
| | | private List<AttributeType> attributeTypes; |
| | | |
| | | this.numValues = attributeTypes.length; |
| | | this.attributeTypes = attributeTypes; |
| | | this.attributeNames = attributeNames; |
| | | this.attributeValues = attributeValues; |
| | | // The list of user-provided attribute names. |
| | | private List<String> attributeNames; |
| | | |
| | | rdnString = null; |
| | | normalizedRDN = null; |
| | | // The list of attribute values. |
| | | private List<AttributeValue> attributeValues; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Create the new empty RDN builder. |
| | | */ |
| | | private Builder() { |
| | | clear(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Appends the provided attribute value assertion to the RDN. |
| | | * |
| | | * @param type |
| | | * The attribute type. |
| | | * @param value |
| | | * The attribute value. |
| | | * @throws IllegalArgumentException |
| | | * If the RDN being constructed already contains an |
| | | * attribute value assertion for this attribute type. |
| | | */ |
| | | public void append(AttributeType type, AttributeValue value) |
| | | throws IllegalArgumentException { |
| | | append(type, type.getNameOrOID(), value); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Appends the provided attribute value assertion to the RDN. |
| | | * |
| | | * @param type |
| | | * The attribute type. |
| | | * @param name |
| | | * The user-provided attribute name. |
| | | * @param value |
| | | * The attribute value. |
| | | * @throws IllegalArgumentException |
| | | * If the RDN being constructed already contains an |
| | | * attribute value assertion for this attribute type. |
| | | */ |
| | | public void append(AttributeType type, String name, |
| | | AttributeValue value) throws IllegalArgumentException { |
| | | ensureNotNull(type, name, value); |
| | | |
| | | if (attributeTypes.contains(type)) { |
| | | throw new IllegalArgumentException( |
| | | "Builder already contains the attribute type " |
| | | + type.getNameOrOID()); |
| | | } |
| | | |
| | | attributeTypes.add(type); |
| | | attributeNames.add(name); |
| | | attributeValues.add(value); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Parses an RDN from the provided string starting at the |
| | | * specified location, appending any AVAs to this RDN builder. |
| | | * <p> |
| | | * This method is package visible so that it can be used by |
| | | * the DN decoder. It is not intended for use elsewhere. |
| | | * |
| | | * @param s |
| | | * The string to be parsed. |
| | | * @param pos |
| | | * The position of the first character in the string to |
| | | * parse. |
| | | * @param allowEmpty |
| | | * Flag indicating whether or not the parsed RDN can be |
| | | * empty or not. |
| | | * @return Returns <code>-1</code> if decoding was successful |
| | | * and parsing consumed the remainder of the string |
| | | * (including trailing space), or the position of the next |
| | | * RDN separator character (i.e. a ',' or ';'). |
| | | * @throws DirectoryException |
| | | * If it was not possible to parse a valid RDN from the |
| | | * provided string. |
| | | */ |
| | | int parse(String s, int pos, boolean allowEmpty) |
| | | throws DirectoryException { |
| | | assert debugEnter(CLASS_NAME, "parse", String.valueOf(s), |
| | | String.valueOf(pos)); |
| | | |
| | | // There must be at least one AVA. |
| | | int count = attributeTypes.size(); |
| | | pos = parseAVA(s, pos); |
| | | |
| | | if (pos == -1 && !allowEmpty) { |
| | | if (count == attributeTypes.size()) { |
| | | // Nothing was parsed. |
| | | int msgID = MSGID_RDN_DECODE_NULL; |
| | | String message = getMessage(msgID); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | } |
| | | |
| | | // Parse any remaining AVAs. |
| | | while (pos != -1 && s.charAt(pos) == '+') { |
| | | count = attributeTypes.size(); |
| | | pos = parseAVA(s, pos + 1); |
| | | |
| | | if (pos == -1 && count == attributeTypes.size()) { |
| | | // Nothing was parsed. |
| | | int msgID = MSGID_RDN_UNEXPECTED_COMMA; |
| | | String message = getMessage(msgID, s, pos); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | } |
| | | |
| | | return pos; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Parse a single AVA. |
| | | * |
| | | * @param s |
| | | * The string to be parsed. |
| | | * @param pos |
| | | * The position of the first character in the string to |
| | | * parse. |
| | | * @return Returns <code>-1</code> if decoding was successful |
| | | * and parsing consumed the remainder of the possibly |
| | | * empty string (including trailing space), or the |
| | | * position of the next AVA separator character (i.e. a |
| | | * '+', ',' or ';'). |
| | | * @throws DirectoryException |
| | | * If it was not possible to parse a valid AVA from the |
| | | * provided string. |
| | | */ |
| | | private int parseAVA(String s, int pos) |
| | | throws DirectoryException { |
| | | int length = s.length(); |
| | | |
| | | // Skip over any spaces that may follow it |
| | | // before the next attribute name. |
| | | char c; |
| | | while ((pos < length) && ((c = s.charAt(pos)) == ' ')) { |
| | | pos++; |
| | | } |
| | | |
| | | // Reached the end of the string - let the caller handle this. |
| | | if (pos >= length) { |
| | | return -1; |
| | | } |
| | | |
| | | // Parse the attribute name. |
| | | StringBuilder attributeName = new StringBuilder(); |
| | | pos = parseAttributeName(s, pos, attributeName); |
| | | |
| | | // Make sure we're not at the end of the RDN. |
| | | if (pos >= length) { |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_END_WITH_ATTR_NAME; |
| | | String message = getMessage(msgID, s, attributeName |
| | | .toString()); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | |
| | | // Skip over any spaces between the attribute name and the |
| | | // equal sign. |
| | | c = s.charAt(pos); |
| | | while (c == ' ') { |
| | | pos++; |
| | | if (pos >= length) { |
| | | // This means that we hit the end of the string before |
| | | // finding a '='. This is illegal because there is no |
| | | // attribute-value separator. |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_END_WITH_ATTR_NAME; |
| | | String message = getMessage(msgID, s, attributeName |
| | | .toString()); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } else { |
| | | c = s.charAt(pos); |
| | | } |
| | | } |
| | | |
| | | // The next character must be an equal sign. |
| | | if (c == '=') { |
| | | pos++; |
| | | } else { |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_NO_EQUAL; |
| | | String message = getMessage(msgID, s, attributeName |
| | | .toString(), c, pos); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | |
| | | // Skip over any spaces after the equal sign. |
| | | while ((pos < length) && ((c = s.charAt(pos)) == ' ')) { |
| | | pos++; |
| | | } |
| | | |
| | | // If we are at the end of the RDN string, then that must mean |
| | | // that the attribute value was empty. This will probably |
| | | // never happen in a real-world environment, but technically |
| | | // isn't illegal. If it does happen, then go ahead and return |
| | | // the RDN. |
| | | if (pos >= length) { |
| | | String name = attributeName.toString(); |
| | | String lowerName = toLowerCase(name); |
| | | AttributeType attrType = DirectoryServer |
| | | .getAttributeType(lowerName); |
| | | |
| | | if (attrType == null) { |
| | | // This must be an attribute type that we don't know |
| | | // about. |
| | | // In that case, we'll create a new attribute using the |
| | | // default syntax. If this is a problem, it will be caught |
| | | // later either by not finding the target entry or by not |
| | | // allowing the entry to be added. |
| | | attrType = DirectoryServer.getDefaultAttributeType(name); |
| | | } |
| | | |
| | | AttributeValue value = new AttributeValue( |
| | | new ASN1OctetString(), new ASN1OctetString()); |
| | | append(attrType, name, value); |
| | | return -1; |
| | | } |
| | | |
| | | // Parse the value for this RDN component. |
| | | ByteString parsedValue = new ASN1OctetString(); |
| | | pos = parseAttributeValue(s, pos, parsedValue); |
| | | |
| | | // Update the RDN to include the new attribute/value. |
| | | String name = attributeName.toString(); |
| | | String lowerName = toLowerCase(name); |
| | | AttributeType attrType = DirectoryServer |
| | | .getAttributeType(lowerName); |
| | | if (attrType == null) { |
| | | // This must be an attribute type that we don't know about. |
| | | // In that case, we'll create a new attribute using the |
| | | // default syntax. If this is a problem, it will be caught |
| | | // later either by not finding the target entry or by not |
| | | // allowing the entry to be added. |
| | | attrType = DirectoryServer.getDefaultAttributeType(name); |
| | | } |
| | | |
| | | AttributeValue value = new AttributeValue(attrType, |
| | | parsedValue); |
| | | append(attrType, name, value); |
| | | |
| | | // Skip over any spaces that might be after the attribute |
| | | // value. |
| | | while ((pos < length) && ((c = s.charAt(pos)) == ' ')) { |
| | | pos++; |
| | | } |
| | | |
| | | // If we're at the end of the string, then return the RDN. |
| | | if (pos >= length) { |
| | | return -1; |
| | | } |
| | | |
| | | // If the next character is a comma or semicolon, then that is |
| | | // not allowed. It would be legal for a DN but not an RDN. |
| | | if ((c == ',') || (c == ';')) { |
| | | return pos; |
| | | } |
| | | |
| | | // If the next character is anything but a plus sign, then it |
| | | // is illegal. |
| | | if (c != '+') { |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_INVALID_CHAR; |
| | | String message = getMessage(msgID, s, c, pos); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | |
| | | return pos; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Removes all the attribute value assertions from this RDN |
| | | * builder. |
| | | */ |
| | | public void clear() { |
| | | attributeTypes = new ArrayList<AttributeType>(3); |
| | | attributeValues = new ArrayList<AttributeValue>(3); |
| | | attributeNames = new ArrayList<String>(3); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Returns <code>true</code> if this RDN builder is empty. |
| | | * |
| | | * @return Returns <code>true</code> if this RDN builder is |
| | | * empty. |
| | | */ |
| | | public boolean isEmpty() { |
| | | return attributeTypes.isEmpty(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new RDN instance based on the current contents of |
| | | * this RDN builder. Subsequent changes to this RDN builder do not |
| | | * affect the contents of the returned <code>RDN</code>. |
| | | * |
| | | * @return Returns a new RDN instance based on the current |
| | | * contents of this RDN builder. |
| | | * @throws IllegalStateException |
| | | * If a new RDN could not be created because this RDN |
| | | * builder is emtpy. |
| | | */ |
| | | public RDN getInstance() throws IllegalStateException { |
| | | int sz = attributeTypes.size(); |
| | | |
| | | if (sz == 0) { |
| | | throw new IllegalStateException("RDN builder is empty"); |
| | | } |
| | | |
| | | AttributeType[] types = new AttributeType[sz]; |
| | | String[] names = new String[sz]; |
| | | AttributeValue[] values = new AttributeValue[sz]; |
| | | |
| | | attributeTypes.toArray(types); |
| | | attributeNames.toArray(names); |
| | | attributeValues.toArray(values); |
| | | |
| | | return new RDN(types, names, values); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new RDN with the provided information. |
| | | * |
| | | * @param types |
| | | * The attribute types for this RDN. |
| | | * @param names |
| | | * The user-provided names for this RDN. |
| | | * @param values |
| | | * The values for this RDN. |
| | | */ |
| | | private RDN(AttributeType[] types, String[] names, |
| | | AttributeValue[] values) { |
| | | assert debugConstructor(CLASS_NAME, String.valueOf(types), String |
| | | .valueOf(names), String.valueOf(values)); |
| | | |
| | | this.attributeTypes = types; |
| | | this.attributeNames = names; |
| | | this.attributeValues = values; |
| | | } |
| | | |
| | | |
| | |
| | | * @return The number of attribute-value pairs contained in this |
| | | * RDN. |
| | | */ |
| | | public int getNumValues() |
| | | { |
| | | public int getNumValues() { |
| | | assert debugEnter(CLASS_NAME, "getNumValues"); |
| | | |
| | | return numValues; |
| | | return attributeTypes.length; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the set of attribute types for this RDN. The returned |
| | | * array must not be modified by the caller. |
| | | * Retrieves the attribute type at the specified AVA in this RDN. |
| | | * |
| | | * @return The set of attribute types for this RDN. |
| | | * @param index |
| | | * The index of the AVA in this RDN. |
| | | * @return Returns the attribute type at the specified AVA in this |
| | | * RDN. |
| | | * @throws IndexOutOfBoundsException |
| | | * If <code>index</code> is out of range |
| | | * <code>(index < 0 || index >= getNumValues()</code>. |
| | | */ |
| | | public AttributeType[] getAttributeTypes() |
| | | { |
| | | assert debugEnter(CLASS_NAME, "getAttributeTypes"); |
| | | public AttributeType getAttributeType(int index) |
| | | throws IndexOutOfBoundsException { |
| | | assert debugEnter(CLASS_NAME, "getAttributeType"); |
| | | |
| | | return attributeTypes; |
| | | if (index < 0 || index >= attributeTypes.length) { |
| | | throw new IndexOutOfBoundsException("Index: " + index |
| | | + ", Size: " + attributeTypes.length); |
| | | } |
| | | return attributeTypes[index]; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the user-defined attribute name at the specified AVA in |
| | | * this RDN. |
| | | * |
| | | * @param index |
| | | * The index of the AVA in this RDN. |
| | | * @return Returns the user-defined attribute name at the specified |
| | | * AVA in this RDN. |
| | | * @throws IndexOutOfBoundsException |
| | | * If <code>index</code> is out of range |
| | | * <code>(index < 0 || index >= getNumValues()</code>. |
| | | */ |
| | | public String getAttributeName(int index) |
| | | throws IndexOutOfBoundsException { |
| | | assert debugEnter(CLASS_NAME, "getAttributeName"); |
| | | |
| | | if (index < 0 || index >= attributeTypes.length) { |
| | | throw new IndexOutOfBoundsException("Index: " + index |
| | | + ", Size: " + attributeTypes.length); |
| | | } |
| | | return attributeNames[index]; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the attribute value at the specified AVA in this RDN. |
| | | * <p> |
| | | * Applications <b>must not</b> modify the contents of the returned |
| | | * attribute value. |
| | | * |
| | | * @param index |
| | | * The index of the AVA in this RDN. |
| | | * @return Returns the attribute value at the specified AVA in this |
| | | * RDN. |
| | | * @throws IndexOutOfBoundsException |
| | | * If <code>index</code> is out of range |
| | | * <code>(index < 0 || index >= getNumValues()</code>. |
| | | */ |
| | | public AttributeValue getAttributeValue(int index) |
| | | throws IndexOutOfBoundsException { |
| | | assert debugEnter(CLASS_NAME, "getAttributeValue"); |
| | | |
| | | if (index < 0 || index >= attributeTypes.length) { |
| | | throw new IndexOutOfBoundsException("Index: " + index |
| | | + ", Size: " + attributeTypes.length); |
| | | } |
| | | return attributeValues[index]; |
| | | } |
| | | |
| | | |
| | |
| | | /** |
| | | * Indicates whether this RDN includes the specified attribute type. |
| | | * |
| | | * @param attributeType The attribute type for which to make the |
| | | * determination. |
| | | * |
| | | * @return <CODE>true</CODE> if the RDN includes the specified |
| | | * attribute type, or <CODE>false</CODE> if not. |
| | | * @param attributeType |
| | | * The attribute type for which to make the determination. |
| | | * @return <code>true</code> if the RDN includes the specified |
| | | * attribute type, or <code>false</code> if not. |
| | | */ |
| | | public boolean hasAttributeType(AttributeType attributeType) |
| | | { |
| | | assert debugEnter(CLASS_NAME, "hasAttributeType", |
| | | String.valueOf(attributeType)); |
| | | public boolean hasAttributeType(AttributeType attributeType) { |
| | | assert debugEnter(CLASS_NAME, "hasAttributeType", String |
| | | .valueOf(attributeType)); |
| | | |
| | | for (AttributeType t : attributeTypes) |
| | | { |
| | | if (t.equals(attributeType)) |
| | | { |
| | | ensureNotNull(attributeType); |
| | | |
| | | for (AttributeType t : attributeTypes) { |
| | | if (t.equals(attributeType)) { |
| | | return true; |
| | | } |
| | | } |
| | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether this RDN includes the specified attribute type. |
| | | * |
| | | * @param lowerName The name or OID for the attribute type for |
| | | * which to make the determination, formatted in |
| | | * all lowercase characters. |
| | | * |
| | | * @return <CODE>true</CODE> if the RDN includes the specified |
| | | * attribute type, or <CODE>false</CODE> if not. |
| | | */ |
| | | public boolean hasAttributeType(String lowerName) |
| | | { |
| | | assert debugEnter(CLASS_NAME, "hasAttributeType", |
| | | String.valueOf(lowerName)); |
| | | |
| | | for (AttributeType t : attributeTypes) |
| | | { |
| | | if (t.hasNameOrOID(lowerName)) |
| | | { |
| | | return true; |
| | | } |
| | | } |
| | | |
| | | for (String s : attributeNames) |
| | | { |
| | | if (s.equalsIgnoreCase(lowerName)) |
| | | { |
| | | return true; |
| | | } |
| | | } |
| | | |
| | | return false; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the set of user-provided names for this RDN. The |
| | | * returned array must not be modified by the caller. |
| | | * |
| | | * @return The set of user-provided names for this RDN. |
| | | */ |
| | | public String[] getAttributeNames() |
| | | { |
| | | assert debugEnter(CLASS_NAME, "getAttributeNames"); |
| | | |
| | | return attributeNames; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the set of attribute values for this RDN. The returned |
| | | * list must not be modified by the caller. |
| | | * |
| | | * @return The set of attribute values for this RDN. |
| | | */ |
| | | public AttributeValue[] getAttributeValues() |
| | | { |
| | | assert debugEnter(CLASS_NAME, "getAttributeValues"); |
| | | |
| | | return attributeValues; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the attribute value that is associated with the |
| | | * specified attribute type. |
| | | * <p> |
| | | * Applications <b>must not</b> modify the contents of the returned |
| | | * attribute value. |
| | | * |
| | | * @param attributeType The attribute type for which to retrieve |
| | | * the corresponding value. |
| | | * |
| | | * @param attributeType |
| | | * The attribute type for which to retrieve the |
| | | * corresponding value. |
| | | * @return The value for the requested attribute type, or |
| | | * <CODE>null</CODE> if the specified attribute type is not |
| | | * present in the RDN. |
| | | * <code>null</code> if the specified attribute type is |
| | | * not present in the RDN. |
| | | */ |
| | | public AttributeValue getAttributeValue(AttributeType attributeType) |
| | | { |
| | | assert debugEnter(CLASS_NAME, "getAttributeValue", |
| | | String.valueOf(attributeType)); |
| | | public AttributeValue getAttributeValue( |
| | | AttributeType attributeType) { |
| | | assert debugEnter(CLASS_NAME, "getAttributeValue", String |
| | | .valueOf(attributeType)); |
| | | |
| | | for (int i=0; i < numValues; i++) |
| | | { |
| | | if (attributeTypes[i].equals(attributeType)) |
| | | { |
| | | ensureNotNull(attributeType); |
| | | |
| | | for (int i = 0; i < attributeTypes.length; i++) { |
| | | if (attributeTypes[i].equals(attributeType)) { |
| | | return attributeValues[i]; |
| | | } |
| | | } |
| | |
| | | /** |
| | | * Indicates whether this RDN is multivalued. |
| | | * |
| | | * @return <CODE>true</CODE> if this RDN is multivalued, or |
| | | * <CODE>false</CODE> if not. |
| | | * @return <code>true</code> if this RDN is multivalued, or |
| | | * <code>false</code> if not. |
| | | */ |
| | | public boolean isMultiValued() |
| | | { |
| | | public boolean isMultiValued() { |
| | | assert debugEnter(CLASS_NAME, "isMultiValued"); |
| | | |
| | | return (numValues > 1); |
| | | return (attributeTypes.length > 1); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether this RDN contains the specified type-value |
| | | * pair. |
| | | * Returns an <code>RDN</code> object holding the value of the |
| | | * specified <code>String</code>. The argument is interpreted as |
| | | * representing the LDAP string representation of an RDN. |
| | | * <p> |
| | | * This method is identical to {@link #decode(String)}. |
| | | * |
| | | * @param type The attribute type for which to make the |
| | | * determination. |
| | | * @param value The value for which to make the determination. |
| | | * |
| | | * @return <CODE>true</CODE> if this RDN contains the specified |
| | | * attribute value, or <CODE>false</CODE> if not. |
| | | * @param s |
| | | * The string to be parsed. |
| | | * @return Returns a <code>RDN</code> holding the value |
| | | * represented by the <code>string</code> argument. |
| | | * @throws DirectoryException |
| | | * If a problem occurs while trying to decode the provided |
| | | * string as a RDN. |
| | | */ |
| | | public boolean hasValue(AttributeType type, AttributeValue value) |
| | | { |
| | | assert debugEnter(CLASS_NAME, "hasValue", String.valueOf(type), |
| | | String.valueOf(value)); |
| | | |
| | | for (int i=0; i < numValues; i++) |
| | | { |
| | | if (attributeTypes[i].equals(type) && |
| | | attributeValues[i].equals(value)) |
| | | { |
| | | return true; |
| | | } |
| | | } |
| | | |
| | | return false; |
| | | public static RDN valueOf(String s) throws DirectoryException { |
| | | return decode(s); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Adds the provided type-value pair from this RDN. |
| | | * Decodes the provided ASN.1 octet string as a RDN. |
| | | * |
| | | * @param type The attribute type of the pair to add. |
| | | * @param name The user-provided name of the pair to add. |
| | | * @param value The attribute value of the pair to add. |
| | | * |
| | | * @return <CODE>true</CODE> if the type-value pair was added to |
| | | * this RDN, or <CODE>false</CODE> if it was not (e.g., it |
| | | * was already present). |
| | | * @param rdnString |
| | | * The ASN.1 octet string to decode as a RDN. |
| | | * @return The decoded RDN. |
| | | * @throws DirectoryException |
| | | * If a problem occurs while trying to decode the provided |
| | | * ASN.1 octet string as a RDN. |
| | | */ |
| | | public boolean addValue(AttributeType type, String name, |
| | | AttributeValue value) |
| | | { |
| | | assert debugEnter(CLASS_NAME, "addValue", String.valueOf(type), |
| | | String.valueOf(name), String.valueOf(value)); |
| | | public static RDN decode(ByteString rdnString) |
| | | throws DirectoryException { |
| | | assert debugEnter(CLASS_NAME, "decode", |
| | | String.valueOf(rdnString)); |
| | | |
| | | for (int i=0; i < numValues; i++) |
| | | { |
| | | if (attributeTypes[i].equals(type) && |
| | | attributeValues[i].equals(value)) |
| | | { |
| | | return false; |
| | | } |
| | | } |
| | | ensureNotNull(rdnString); |
| | | |
| | | numValues++; |
| | | |
| | | AttributeType[] newTypes = new AttributeType[numValues]; |
| | | System.arraycopy(attributeTypes, 0, newTypes, 0, |
| | | attributeTypes.length); |
| | | newTypes[attributeTypes.length] = type; |
| | | attributeTypes = newTypes; |
| | | |
| | | String[] newNames = new String[numValues]; |
| | | System.arraycopy(attributeNames, 0, newNames, 0, |
| | | attributeNames.length); |
| | | newNames[attributeNames.length] = name; |
| | | attributeNames = newNames; |
| | | |
| | | AttributeValue[] newValues = new AttributeValue[numValues]; |
| | | System.arraycopy(attributeValues, 0, newValues, 0, |
| | | attributeValues.length); |
| | | newValues[attributeValues.length] = value; |
| | | attributeValues = newValues; |
| | | |
| | | rdnString = null; |
| | | normalizedRDN = null; |
| | | |
| | | return true; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Removes the provided type-value pair from this RDN. |
| | | * |
| | | * @param type The attribute type of the pair to remove. |
| | | * @param value The attribute value of the pair to remove. |
| | | * |
| | | * @return <CODE>true</CODE> if the type-value pair was found and |
| | | * removed from this RDN, or <CODE>false</CODE> if it was |
| | | * not. |
| | | */ |
| | | public boolean removeValue(AttributeType type, AttributeValue value) |
| | | { |
| | | assert debugEnter(CLASS_NAME, "removeValue", String.valueOf(type), |
| | | String.valueOf(value)); |
| | | |
| | | for (int i=0; i < numValues; i++) |
| | | { |
| | | if (attributeTypes[i].equals(type) && |
| | | attributeValues[i].equals(value)) |
| | | { |
| | | numValues--; |
| | | |
| | | if (numValues == 0) |
| | | { |
| | | attributeTypes = new AttributeType[0]; |
| | | attributeNames = new String[0]; |
| | | attributeValues = new AttributeValue[0]; |
| | | } |
| | | else if (i == 0) |
| | | { |
| | | AttributeType[] newTypes = new AttributeType[numValues]; |
| | | System.arraycopy(attributeTypes, 1, newTypes, 0, numValues); |
| | | attributeTypes = newTypes; |
| | | |
| | | String[] newNames = new String[numValues]; |
| | | System.arraycopy(attributeNames, 1, newNames, 0, numValues); |
| | | attributeNames = newNames; |
| | | |
| | | AttributeValue[] newValues = new AttributeValue[numValues]; |
| | | System.arraycopy(attributeValues, 1, newValues, 0, |
| | | numValues); |
| | | attributeValues = newValues; |
| | | } |
| | | else if (i == numValues) |
| | | { |
| | | AttributeType[] newTypes = new AttributeType[numValues]; |
| | | System.arraycopy(attributeTypes, 0, newTypes, 0, numValues); |
| | | attributeTypes = newTypes; |
| | | |
| | | String[] newNames = new String[numValues]; |
| | | System.arraycopy(attributeNames, 0, newNames, 0, numValues); |
| | | attributeNames = newNames; |
| | | |
| | | AttributeValue[] newValues = new AttributeValue[numValues]; |
| | | System.arraycopy(attributeValues, 0, newValues, 0, |
| | | numValues); |
| | | attributeValues = newValues; |
| | | } |
| | | else |
| | | { |
| | | int remaining = numValues - i; |
| | | |
| | | AttributeType[] newTypes = new AttributeType[numValues]; |
| | | System.arraycopy(attributeTypes, 0, newTypes, 0, i); |
| | | System.arraycopy(attributeTypes, i+1, newTypes, i, |
| | | remaining); |
| | | attributeTypes = newTypes; |
| | | |
| | | String[] newNames = new String[numValues]; |
| | | System.arraycopy(attributeNames, 0, newNames, 0, i); |
| | | System.arraycopy(attributeNames, i+1, newNames, i, |
| | | remaining); |
| | | attributeNames = newNames; |
| | | |
| | | AttributeValue[] newValues = new AttributeValue[numValues]; |
| | | System.arraycopy(attributeValues, 0, newValues, 0, i); |
| | | System.arraycopy(attributeValues, i+1, newValues, i, |
| | | remaining); |
| | | attributeValues = newValues; |
| | | } |
| | | |
| | | rdnString = null; |
| | | normalizedRDN = null; |
| | | |
| | | return true; |
| | | } |
| | | } |
| | | |
| | | return false; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Replaces the set of values for this RDN with the provided |
| | | * name-value pair. |
| | | * |
| | | * @param type The attribute type for this RDN. |
| | | * @param name The user-provided name for this RDN. |
| | | * @param value The attribute value for this RDN. |
| | | */ |
| | | public void replaceValues(AttributeType type, String name, |
| | | AttributeValue value) |
| | | { |
| | | assert debugEnter(CLASS_NAME, "replaceValues", |
| | | String.valueOf(type), String.valueOf(name), |
| | | String.valueOf(value)); |
| | | |
| | | attributeTypes = new AttributeType[] { type }; |
| | | attributeNames = new String[] { name }; |
| | | attributeValues = new AttributeValue[] { value }; |
| | | |
| | | numValues = 1; |
| | | rdnString = null; |
| | | normalizedRDN = null; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Replaces the set of values for this RDN with the provided set of |
| | | * name-value pairs. The number of elements in each list must be |
| | | * equal and greater than one. |
| | | * |
| | | * @param attributeTypes The set of attribute types for this RDN. |
| | | * @param attributeNames The set of user-provided names for this |
| | | * RDN. |
| | | * @param attributeValues The set of values for this RDN. |
| | | */ |
| | | public void replaceValues(ArrayList<AttributeType> attributeTypes, |
| | | ArrayList<String> attributeNames, |
| | | ArrayList<AttributeValue> attributeValues) |
| | | { |
| | | assert debugEnter(CLASS_NAME, "replaceValues", |
| | | String.valueOf(attributeTypes), |
| | | String.valueOf(attributeNames), |
| | | String.valueOf(attributeValues)); |
| | | |
| | | this.attributeTypes = new AttributeType[attributeTypes.size()]; |
| | | attributeTypes.toArray(this.attributeTypes); |
| | | |
| | | this.attributeNames = new String[attributeNames.size()]; |
| | | attributeNames.toArray(this.attributeNames); |
| | | |
| | | this.attributeValues = new AttributeValue[attributeValues.size()]; |
| | | attributeValues.toArray(this.attributeValues); |
| | | |
| | | numValues = attributeTypes.size(); |
| | | rdnString = null; |
| | | normalizedRDN = null; |
| | | // Use string-based decoder. |
| | | return decode(rdnString.stringValue()); |
| | | } |
| | | |
| | | |
| | |
| | | /** |
| | | * Decodes the provided string as an RDN. |
| | | * |
| | | * @param rdnString The string to decode as an RDN. |
| | | * |
| | | * @param rdnString |
| | | * The string to decode as an RDN. |
| | | * @return The decoded RDN. |
| | | * |
| | | * @throws DirectoryException If a problem occurs while trying to |
| | | * decode the provided string as a RDN. |
| | | * @throws DirectoryException |
| | | * If a problem occurs while trying to decode the provided |
| | | * string as a RDN. |
| | | */ |
| | | public static RDN decode(String rdnString) |
| | | throws DirectoryException |
| | | { |
| | | throws DirectoryException { |
| | | assert debugEnter(CLASS_NAME, "decode", |
| | | String.valueOf(rdnString)); |
| | | |
| | | ensureNotNull(rdnString); |
| | | |
| | | // A null or empty RDN is not acceptable. |
| | | if (rdnString == null) |
| | | { |
| | | int msgID = MSGID_RDN_DECODE_NULL; |
| | | String message = getMessage(msgID); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | // Use an RDN builder to parse the string. |
| | | Builder builder = createBuilder(); |
| | | int pos = builder.parse(rdnString, 0, false); |
| | | |
| | | int length = rdnString.length(); |
| | | if (length == 0) |
| | | { |
| | | int msgID = MSGID_RDN_DECODE_NULL; |
| | | String message = getMessage(msgID); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | |
| | | |
| | | // Iterate through the RDN string. The first thing to do is to |
| | | // get rid of any leading spaces. |
| | | int pos = 0; |
| | | char c = rdnString.charAt(pos); |
| | | while (c == ' ') |
| | | { |
| | | pos++; |
| | | if (pos == length) |
| | | { |
| | | // This means that the RDN was completely comprised of spaces, |
| | | // which is not valid. |
| | | int msgID = MSGID_RDN_DECODE_NULL; |
| | | String message = getMessage(msgID); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | else |
| | | { |
| | | c = rdnString.charAt(pos); |
| | | } |
| | | } |
| | | |
| | | |
| | | // We know that it's not an empty RDN, so we can do the real |
| | | // processing. First, parse the attribute name. We can borrow |
| | | // the DN code for this. |
| | | boolean allowExceptions = |
| | | DirectoryServer.allowAttributeNameExceptions(); |
| | | StringBuilder attributeName = new StringBuilder(); |
| | | pos = DN.parseAttributeName(rdnString, pos, attributeName, |
| | | allowExceptions); |
| | | |
| | | |
| | | // Make sure that we're not at the end of the RDN string because |
| | | // that would be invalid. |
| | | if (pos >= length) |
| | | { |
| | | int msgID = MSGID_RDN_END_WITH_ATTR_NAME; |
| | | String message = getMessage(msgID, |
| | | rdnString, attributeName.toString()); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | |
| | | |
| | | // Skip over any spaces between the attribute name and its value. |
| | | c = rdnString.charAt(pos); |
| | | while (c == ' ') |
| | | { |
| | | pos++; |
| | | if (pos >= length) |
| | | { |
| | | // This means that we hit the end of the string before |
| | | // finding a '='. This is illegal because there is no |
| | | // attribute-value separator. |
| | | int msgID = MSGID_RDN_END_WITH_ATTR_NAME; |
| | | String message = getMessage(msgID, |
| | | rdnString, attributeName.toString()); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | else |
| | | { |
| | | c = rdnString.charAt(pos); |
| | | } |
| | | } |
| | | |
| | | |
| | | // The next character must be an equal sign. If it is not, then |
| | | // that's an error. |
| | | if (c == '=') |
| | | { |
| | | pos++; |
| | | } |
| | | else |
| | | { |
| | | int msgID = MSGID_RDN_NO_EQUAL; |
| | | String message = getMessage(msgID, rdnString, |
| | | attributeName.toString(), c, pos); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | |
| | | |
| | | // Skip over any spaces between the equal sign and the value. |
| | | while ((pos < length) && ((c = rdnString.charAt(pos)) == ' ')) |
| | | { |
| | | pos++; |
| | | } |
| | | |
| | | |
| | | // If we are at the end of the RDN string, then that must mean |
| | | // that the attribute value was empty. This will probably never |
| | | // happen in a real-world environment, but technically isn't |
| | | // illegal. If it does happen, then go ahead and return the RDN. |
| | | if (pos >= length) |
| | | { |
| | | String name = attributeName.toString(); |
| | | String lowerName = toLowerCase(name); |
| | | AttributeType attrType = |
| | | DirectoryServer.getAttributeType(lowerName); |
| | | |
| | | if (attrType == null) |
| | | { |
| | | // This must be an attribute type that we don't know about. |
| | | // In that case, we'll create a new attribute using the |
| | | // default syntax. If this is a problem, it will be caught |
| | | // later either by not finding the target entry or by not |
| | | // allowing the entry to be added. |
| | | attrType = DirectoryServer.getDefaultAttributeType(name); |
| | | } |
| | | |
| | | AttributeValue value = new AttributeValue(new ASN1OctetString(), |
| | | new ASN1OctetString()); |
| | | return new RDN(attrType, name, value); |
| | | } |
| | | |
| | | |
| | | // Parse the value for this RDN component. This can be done using |
| | | // the DN code. |
| | | ByteString parsedValue = new ASN1OctetString(); |
| | | pos = DN.parseAttributeValue(rdnString, pos, parsedValue); |
| | | |
| | | |
| | | // Create the new RDN with the provided information. However, |
| | | // don't return it yet because this could be a multi-valued RDN. |
| | | String name = attributeName.toString(); |
| | | String lowerName = toLowerCase(name); |
| | | AttributeType attrType = |
| | | DirectoryServer.getAttributeType(lowerName); |
| | | if (attrType == null) |
| | | { |
| | | // This must be an attribute type that we don't know about. |
| | | // In that case, we'll create a new attribute using the default |
| | | // syntax. If this is a problem, it will be caught later either |
| | | // by not finding the target entry or by not allowing the entry |
| | | // to be added. |
| | | attrType = DirectoryServer.getDefaultAttributeType(name); |
| | | } |
| | | |
| | | AttributeValue value = new AttributeValue(attrType, parsedValue); |
| | | RDN rdn = new RDN(attrType, name, value); |
| | | |
| | | |
| | | // Skip over any spaces that might be after the attribute value. |
| | | while ((pos < length) && ((c = rdnString.charAt(pos)) == ' ')) |
| | | { |
| | | pos++; |
| | | } |
| | | |
| | | |
| | | // Most likely, this is the end of the RDN. If so, then return |
| | | // it. |
| | | if (pos >= length) |
| | | { |
| | | return rdn; |
| | | } |
| | | |
| | | |
| | | // If the next character is a comma or semicolon, then that is not |
| | | // allowed. It would be legal for a DN but not an RDN. |
| | | if ((c == ',') || (c == ';')) |
| | | { |
| | | // Make sure that the string did not contain any trailing RDNs. |
| | | if (pos != -1) { |
| | | int msgID = MSGID_RDN_UNEXPECTED_COMMA; |
| | | String message = getMessage(msgID, rdnString, pos); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | |
| | | |
| | | // If the next character is anything but a plus sign, then it is |
| | | // illegal. |
| | | if (c != '+') |
| | | { |
| | | int msgID = MSGID_RDN_ILLEGAL_CHARACTER; |
| | | String message = getMessage(msgID, rdnString, c, pos); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | |
| | | |
| | | // If we have gotten here, then it is a multi-valued RDN. Parse |
| | | // the remaining attribute/value pairs and add them to the RDN |
| | | // that we've already created. |
| | | while (true) |
| | | { |
| | | // Skip over the plus sign and any spaces that may follow it |
| | | // before the next attribute name. |
| | | pos++; |
| | | while ((pos < length) && ((c = rdnString.charAt(pos)) == ' ')) |
| | | { |
| | | pos++; |
| | | } |
| | | |
| | | |
| | | // Parse the attribute name. |
| | | attributeName = new StringBuilder(); |
| | | pos = DN.parseAttributeName(rdnString, pos, attributeName, |
| | | allowExceptions); |
| | | |
| | | |
| | | // Make sure we're not at the end of the RDN. |
| | | if (pos >= length) |
| | | { |
| | | int msgID = MSGID_RDN_END_WITH_ATTR_NAME; |
| | | String message = getMessage(msgID, rdnString, |
| | | attributeName.toString()); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | |
| | | |
| | | // Skip over any spaces between the attribute name and the equal |
| | | // sign. |
| | | c = rdnString.charAt(pos); |
| | | while (c == ' ') |
| | | { |
| | | pos++; |
| | | if (pos >= length) |
| | | { |
| | | // This means that we hit the end of the string before |
| | | // finding a '='. This is illegal because there is no |
| | | // attribute-value separator. |
| | | int msgID = MSGID_RDN_END_WITH_ATTR_NAME; |
| | | String message = getMessage(msgID, rdnString, |
| | | attributeName.toString()); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | else |
| | | { |
| | | c = rdnString.charAt(pos); |
| | | } |
| | | } |
| | | |
| | | |
| | | // The next character must be an equal sign. |
| | | if (c == '=') |
| | | { |
| | | pos++; |
| | | } |
| | | else |
| | | { |
| | | int msgID = MSGID_RDN_NO_EQUAL; |
| | | String message = getMessage(msgID, rdnString, |
| | | attributeName.toString(), c, pos); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | |
| | | |
| | | // Skip over any spaces after the equal sign. |
| | | while ((pos < length) && ((c = rdnString.charAt(pos)) == ' ')) |
| | | { |
| | | pos++; |
| | | } |
| | | |
| | | |
| | | // If we are at the end of the RDN string, then that must mean |
| | | // that the attribute value was empty. This will probably never |
| | | // happen in a real-world environment, but technically isn't |
| | | // illegal. If it does happen, then go ahead and return the |
| | | // RDN. |
| | | if (pos >= length) |
| | | { |
| | | name = attributeName.toString(); |
| | | lowerName = toLowerCase(name); |
| | | attrType = DirectoryServer.getAttributeType(lowerName); |
| | | |
| | | if (attrType == null) |
| | | { |
| | | // This must be an attribute type that we don't know about. |
| | | // In that case, we'll create a new attribute using the |
| | | // default syntax. If this is a problem, it will be caught |
| | | // later either by not finding the target entry or by not |
| | | // allowing the entry to be added. |
| | | attrType = DirectoryServer.getDefaultAttributeType(name); |
| | | } |
| | | |
| | | value = new AttributeValue(new ASN1OctetString(), |
| | | new ASN1OctetString()); |
| | | rdn.addValue(attrType, name, value); |
| | | return rdn; |
| | | } |
| | | |
| | | |
| | | // Parse the value for this RDN component. |
| | | parsedValue = new ASN1OctetString(); |
| | | pos = DN.parseAttributeValue(rdnString, pos, parsedValue); |
| | | |
| | | |
| | | // Update the RDN to include the new attribute/value. |
| | | name = attributeName.toString(); |
| | | lowerName = toLowerCase(name); |
| | | attrType = DirectoryServer.getAttributeType(lowerName); |
| | | if (attrType == null) |
| | | { |
| | | // This must be an attribute type that we don't know about. |
| | | // In that case, we'll create a new attribute using the |
| | | // default syntax. If this is a problem, it will be caught |
| | | // later either by not finding the target entry or by not |
| | | // allowing the entry to be added. |
| | | attrType = DirectoryServer.getDefaultAttributeType(name); |
| | | } |
| | | |
| | | value = new AttributeValue(attrType, parsedValue); |
| | | rdn.addValue(attrType, name, value); |
| | | |
| | | |
| | | // Skip over any spaces that might be after the attribute value. |
| | | while ((pos < length) && ((c = rdnString.charAt(pos)) == ' ')) |
| | | { |
| | | pos++; |
| | | } |
| | | |
| | | |
| | | // If we're at the end of the string, then return the RDN. |
| | | if (pos >= length) |
| | | { |
| | | return rdn; |
| | | } |
| | | |
| | | |
| | | // If the next character is a comma or semicolon, then that is |
| | | // not allowed. It would be legal for a DN but not an RDN. |
| | | if ((c == ',') || (c == ';')) |
| | | { |
| | | int msgID = MSGID_RDN_UNEXPECTED_COMMA; |
| | | String message = getMessage(msgID, rdnString, pos); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | |
| | | |
| | | // If the next character is anything but a plus sign, then it is |
| | | // illegal. |
| | | if (c != '+') |
| | | { |
| | | int msgID = MSGID_RDN_ILLEGAL_CHARACTER; |
| | | String message = getMessage(msgID, rdnString, c, pos); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a duplicate of this RDN that can be modified without |
| | | * impacting this RDN. |
| | | * |
| | | * @return A duplicate of this RDN that can be modified without |
| | | * impacting this RDN. |
| | | */ |
| | | public RDN duplicate() |
| | | { |
| | | assert debugEnter(CLASS_NAME, "duplicate"); |
| | | |
| | | AttributeType[] newTypes = new AttributeType[numValues]; |
| | | System.arraycopy(attributeTypes, 0, newTypes, 0, numValues); |
| | | |
| | | String[] newNames = new String[numValues]; |
| | | System.arraycopy(attributeNames, 0, newNames, 0, numValues); |
| | | |
| | | AttributeValue[] newValues = new AttributeValue[numValues]; |
| | | System.arraycopy(attributeValues, 0, newValues, 0, numValues); |
| | | |
| | | return new RDN(newTypes, newNames, newValues); |
| | | // Return the parsed RDN instance. |
| | | return builder.getInstance(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether the provided object is equal to this RDN. It |
| | | * will only be considered equal if it is an RDN object that |
| | | * contains the same number of elements in the same order with the |
| | | * same types and normalized values. |
| | | * will only be considered equal if it is an RDN object containing |
| | | * the same attribute value assertions as this RDN (the order does |
| | | * not matter). |
| | | * |
| | | * @param o The object for which to make the determination. |
| | | * |
| | | * @return <CODE>true</CODE> if it is determined that the provided |
| | | * object is equal to this RDN, or <CODE>false</CODE> if |
| | | * @param o |
| | | * The object for which to make the determination. |
| | | * @return <code>true</code> if it is determined that the provided |
| | | * object is equal to this RDN, or <code>false</code> if |
| | | * not. |
| | | */ |
| | | public boolean equals(Object o) |
| | | { |
| | | public boolean equals(Object o) { |
| | | assert debugEnter(CLASS_NAME, "equals", String.valueOf(o)); |
| | | |
| | | if (this == o) |
| | | { |
| | | if (this == o) { |
| | | return true; |
| | | } |
| | | } else if (o instanceof RDN) { |
| | | RDN other = (RDN) o; |
| | | |
| | | if ((o == null) || (! (o instanceof RDN))) |
| | | { |
| | | String nvalue1 = toNormalizedString(); |
| | | String nvalue2 = other.toNormalizedString(); |
| | | return nvalue1.equals(nvalue2); |
| | | } else { |
| | | return false; |
| | | } |
| | | |
| | | RDN rdn = (RDN) o; |
| | | if (numValues != rdn.numValues) |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | for (int i=0; i < numValues; i++) |
| | | { |
| | | if ((! attributeTypes[i].equals(rdn.attributeTypes[i])) || |
| | | (! attributeValues[i].equals(rdn.attributeValues[i]))) |
| | | { |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | return true; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the hash code for this RDN. It will be calculated as |
| | | * the sum of the hash codes of the types and values. |
| | | * the hash code of the RDN's normalized string representation. |
| | | * |
| | | * @return The hash code for this RDN. |
| | | */ |
| | | public int hashCode() |
| | | { |
| | | public int hashCode() { |
| | | assert debugEnter(CLASS_NAME, "hashCode"); |
| | | |
| | | int hashCode = 0; |
| | | |
| | | for (int i=0; i < numValues; i++) |
| | | { |
| | | hashCode += attributeTypes[i].hashCode() + |
| | | attributeValues[i].hashCode(); |
| | | } |
| | | |
| | | return hashCode; |
| | | return toNormalizedString().hashCode(); |
| | | } |
| | | |
| | | |
| | |
| | | * |
| | | * @return A string representation of this RDN. |
| | | */ |
| | | public String toString() |
| | | { |
| | | if (rdnString == null) |
| | | { |
| | | public String toString() { |
| | | assert debugEnter(CLASS_NAME, "toString"); |
| | | |
| | | StringBuilder buffer = new StringBuilder(); |
| | | |
| | | buffer.append(attributeNames[0]); |
| | | buffer.append("="); |
| | | buffer.append(attributeValues[0].getDNStringValue()); |
| | | |
| | | for (int i=1; i < numValues; i++) |
| | | { |
| | | buffer.append("+"); |
| | | buffer.append(attributeNames[i]); |
| | | buffer.append("="); |
| | | buffer.append(attributeValues[i].getDNStringValue()); |
| | | } |
| | | |
| | | rdnString = buffer.toString(); |
| | | } |
| | | |
| | | return rdnString; |
| | | toString(buffer); |
| | | return buffer.toString(); |
| | | } |
| | | |
| | | |
| | |
| | | * Appends a string representation of this RDN to the provided |
| | | * buffer. |
| | | * |
| | | * @param buffer The buffer to which the string representation |
| | | * should be appended. |
| | | * @param buffer |
| | | * The buffer to which the string representation should be |
| | | * appended. |
| | | */ |
| | | public void toString(StringBuilder buffer) |
| | | { |
| | | public void toString(StringBuilder buffer) { |
| | | assert debugEnter(CLASS_NAME, "toString", |
| | | "java.lang.StringBuilder"); |
| | | |
| | | buffer.append(toString()); |
| | | ensureNotNull(buffer); |
| | | |
| | | buffer.append(attributeNames[0]); |
| | | buffer.append("="); |
| | | String value = attributeValues[0].getStringValue(); |
| | | quoteAttributeValue(buffer, value); |
| | | |
| | | for (int i = 1; i < attributeTypes.length; i++) { |
| | | buffer.append("+"); |
| | | buffer.append(attributeNames[i]); |
| | | buffer.append("="); |
| | | |
| | | value = attributeValues[i].getStringValue(); |
| | | quoteAttributeValue(buffer, value); |
| | | } |
| | | } |
| | | |
| | | |
| | |
| | | * |
| | | * @return A normalized string representation of this RDN. |
| | | */ |
| | | public String toNormalizedString() |
| | | { |
| | | if (normalizedRDN == null) |
| | | { |
| | | StringBuilder buffer = new StringBuilder(); |
| | | toNormalizedString(buffer); |
| | | public String toNormalizedString() { |
| | | if (normalizedRDN == null) { |
| | | StringBuilder builder = new StringBuilder(); |
| | | |
| | | if (attributeNames.length == 1) { |
| | | // Optimize for the common case of a single AVA. |
| | | appendNormalizedAVA(builder, attributeTypes[0], |
| | | attributeValues[0]); |
| | | } else { |
| | | // Multiple AVAs require sorting. |
| | | TreeMap<String, Integer> map; |
| | | |
| | | map = new TreeMap<String, Integer>(); |
| | | for (int i = 0; i < attributeTypes.length; i++) { |
| | | map.put(attributeTypes[i].getNameOrOID(), i); |
| | | } |
| | | |
| | | boolean isFirst = true; |
| | | for (Integer i : map.values()) { |
| | | if (!isFirst) { |
| | | builder.append('+'); |
| | | } else { |
| | | isFirst = false; |
| | | } |
| | | appendNormalizedAVA(builder, attributeTypes[i], |
| | | attributeValues[i]); |
| | | } |
| | | } |
| | | |
| | | normalizedRDN = builder.toString(); |
| | | } |
| | | |
| | | return normalizedRDN; |
| | |
| | | * Appends a normalized string representation of this RDN to the |
| | | * provided buffer. |
| | | * |
| | | * @param buffer The buffer to which to append the information. |
| | | * @param buffer |
| | | * The buffer to which to append the information. |
| | | */ |
| | | public void toNormalizedString(StringBuilder buffer) |
| | | { |
| | | public void toNormalizedString(StringBuilder buffer) { |
| | | assert debugEnter(CLASS_NAME, "toNormalizedString", |
| | | "java.lang.StringBuilder"); |
| | | |
| | | if (normalizedRDN != null) |
| | | { |
| | | buffer.append(normalizedRDN); |
| | | return; |
| | | ensureNotNull(buffer); |
| | | |
| | | buffer.append(toNormalizedString()); |
| | | } |
| | | |
| | | boolean bufferEmpty = (buffer.length() == 0); |
| | | |
| | | if (attributeNames.length == 1) |
| | | { |
| | | toLowerCase(attributeNames[0], buffer); |
| | | buffer.append('='); |
| | | |
| | | try |
| | | { |
| | | buffer.append( |
| | | attributeValues[0].getNormalizedDNStringValue()); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | assert debugException(CLASS_NAME, "toNormalizedString", e); |
| | | /** |
| | | * Compares this RDN with the provided RDN. |
| | | * <p> |
| | | * The comparison will be done in order of the sorted RDN |
| | | * components. It will attempt to use an ordering matching rule for |
| | | * the associated attributes (if one is provided), but will fall |
| | | * back on a bytewise comparison of the normalized values if |
| | | * necessary. |
| | | * |
| | | * @param rdn |
| | | * The RDN against which to compare this RDN. |
| | | * @return A negative integer if this RDN should come before the |
| | | * provided RDN, a positive integer if this RDN should come |
| | | * after the provided RDN, or zero if there is no difference |
| | | * with regard to ordering. |
| | | */ |
| | | public int compareTo(RDN rdn) { |
| | | assert debugEnter(CLASS_NAME, "compareTo", String.valueOf(rdn)); |
| | | |
| | | buffer.append(attributeValues[0].getStringValue()); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | TreeSet<String> rdnElementStrings = new TreeSet<String>(); |
| | | ensureNotNull(rdn); |
| | | |
| | | for (int i=0; i < attributeNames.length; i++) |
| | | { |
| | | StringBuilder b2 = new StringBuilder(); |
| | | toLowerCase(attributeNames[i], b2); |
| | | b2.append('='); |
| | | // Handle the common case efficiently. |
| | | if (attributeTypes.length == 1 |
| | | && rdn.attributeTypes.length == 1) { |
| | | AttributeType type1 = attributeTypes[0]; |
| | | AttributeType type2 = rdn.attributeTypes[0]; |
| | | |
| | | try |
| | | { |
| | | b2.append(attributeValues[i].getNormalizedStringValue()); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | assert debugException(CLASS_NAME, "toNormalizedString", e); |
| | | AttributeValue value1 = attributeValues[0]; |
| | | AttributeValue value2 = rdn.attributeValues[0]; |
| | | |
| | | b2.append(attributeValues[i].getStringValue()); |
| | | return compareAVA(type1, value1, type2, value2); |
| | | } |
| | | |
| | | rdnElementStrings.add(b2.toString()); |
| | | // We have at least one multi-valued RDNs, so we need to sort. |
| | | TreeMap<String, Integer> map1; |
| | | TreeMap<String, Integer> map2; |
| | | |
| | | map1 = new TreeMap<String, Integer>(); |
| | | map2 = new TreeMap<String, Integer>(); |
| | | |
| | | for (int i = 0; i < attributeTypes.length; i++) { |
| | | map1.put(attributeTypes[i].getNameOrOID(), i); |
| | | } |
| | | |
| | | Iterator<String> iterator = rdnElementStrings.iterator(); |
| | | buffer.append(iterator.next()); |
| | | for (int i = 0; i < rdn.attributeTypes.length; i++) { |
| | | map2.put(rdn.attributeTypes[i].getNameOrOID(), i); |
| | | } |
| | | |
| | | while (iterator.hasNext()) |
| | | { |
| | | buffer.append('+'); |
| | | buffer.append(iterator.next()); |
| | | // Now compare the sorted AVAs. |
| | | Iterator<Integer> i1= map1.values().iterator(); |
| | | Iterator<Integer> i2 = map2.values().iterator(); |
| | | |
| | | while (i1.hasNext() && i2.hasNext()) { |
| | | int int1 = i1.next(); |
| | | int int2 = i2.next(); |
| | | |
| | | AttributeType type1 = attributeTypes[int1]; |
| | | AttributeType type2 = rdn.attributeTypes[int2]; |
| | | |
| | | AttributeValue value1 = attributeValues[int1]; |
| | | AttributeValue value2 = rdn.attributeValues[int2]; |
| | | |
| | | int rc = compareAVA(type1, value1, type2, value2); |
| | | if (rc != 0) { |
| | | return rc; |
| | | } |
| | | } |
| | | |
| | | if (bufferEmpty) |
| | | { |
| | | normalizedRDN = buffer.toString(); |
| | | // At least one of the iterators has finished. |
| | | if (i1.hasNext() == false && i2.hasNext() == false) { |
| | | return 0; |
| | | } else if (i1.hasNext() == false) { |
| | | return -1; |
| | | } else { |
| | | return 1; |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Compares this RDN with the provided RDN based on an alphabetic |
| | | * comparison of the attribute names and values. |
| | | * Compare two AVAs for order. |
| | | * |
| | | * @param rdn The RDN against which to compare this RDN. |
| | | * |
| | | * @return A negative integer if this RDN should come before the |
| | | * provided RDN, a positive integer if this RDN should come |
| | | * after the provided RDN, or zero if there is no |
| | | * difference with regard to ordering. |
| | | * @param type1 |
| | | * The attribute type of the first AVA. |
| | | * @param value1 |
| | | * The attribute value of the first AVA. |
| | | * @param type2 |
| | | * The attribute type of the second AVA. |
| | | * @param value2 |
| | | * The attribute value of the second AVA. |
| | | * @return Returns a negative integer, zero, or a positive integer |
| | | * if the first AVA is less than, equal to, or greater than |
| | | * the second. |
| | | */ |
| | | public int compareTo(RDN rdn) |
| | | { |
| | | assert debugEnter(CLASS_NAME, "compareTo", String.valueOf(rdn)); |
| | | private int compareAVA(AttributeType type1, AttributeValue value1, |
| | | AttributeType type2, AttributeValue value2) { |
| | | if (type1.equals(type2)) { |
| | | OrderingMatchingRule rule = type1.getOrderingMatchingRule(); |
| | | |
| | | if (equals(rdn)) |
| | | { |
| | | return 0; |
| | | try { |
| | | if (rule != null) { |
| | | byte[] b1 = value1.getNormalizedValueBytes(); |
| | | byte[] b2 = value2.getNormalizedValueBytes(); |
| | | |
| | | return rule.compare(b1, b2); |
| | | } else { |
| | | byte[] b1 = value1.getNormalizedValue().value(); |
| | | byte[] b2 = value2.getNormalizedValue().value(); |
| | | |
| | | return StaticUtils.compare(b1, b2); |
| | | } |
| | | } catch (Exception e) { |
| | | assert debugException(CLASS_NAME, "compareAVA", e); |
| | | |
| | | int minValues = Math.min(numValues, rdn.numValues); |
| | | for (int i=0; i < minValues; i++) |
| | | { |
| | | String n1 = attributeNames[i].toLowerCase(); |
| | | String n2 = rdn.attributeNames[i].toLowerCase(); |
| | | // Just get the raw values and do a comparison between them. |
| | | byte[] b1 = value1.getValue().value(); |
| | | byte[] b2 = value2.getValue().value(); |
| | | |
| | | int result = n1.compareTo(n2); |
| | | if (result != 0) |
| | | { |
| | | return result; |
| | | return StaticUtils.compare(b1, b2); |
| | | } |
| | | } else { |
| | | String name1 = toLowerCase(type1.getNameOrOID()); |
| | | String name2 = toLowerCase(type2.getNameOrOID()); |
| | | |
| | | try |
| | | { |
| | | String v1 = attributeValues[i].getNormalizedStringValue(); |
| | | String v2 = rdn.attributeValues[i].getNormalizedStringValue(); |
| | | |
| | | result = v1.compareTo(v2); |
| | | if (result != 0) |
| | | { |
| | | return result; |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | assert debugException(CLASS_NAME, "compareTo", e); |
| | | |
| | | return 0; |
| | | return name1.compareTo(name2); |
| | | } |
| | | } |
| | | |
| | | if (numValues > minValues) |
| | | { |
| | | return 1; |
| | | |
| | | |
| | | /** |
| | | * Normalize and append the provided attribute type and value to the |
| | | * provided buffer. |
| | | * |
| | | * @param buffer |
| | | * The string buffer. |
| | | * @param type |
| | | * The attribute type. |
| | | * @param value |
| | | * The attribute value. |
| | | */ |
| | | private void appendNormalizedAVA(StringBuilder buffer, |
| | | AttributeType type, AttributeValue value) { |
| | | toLowerCase(type.getNameOrOID(), buffer); |
| | | buffer.append('='); |
| | | |
| | | try { |
| | | quoteAttributeValue(buffer, value.getNormalizedStringValue()); |
| | | } catch (Exception e) { |
| | | assert debugException(CLASS_NAME, "toNormalizedString", e); |
| | | quoteAttributeValue(buffer, value.getStringValue()); |
| | | } |
| | | else if (rdn.numValues > minValues) |
| | | { |
| | | return -1; |
| | | } |
| | | else |
| | | { |
| | | return 0; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Encode an attribute value according to the DN string encoding |
| | | * rules, and append it to the provided buffer. |
| | | * |
| | | * @param buffer |
| | | * Append the attribtue value to this buffer. |
| | | * @param value |
| | | * The value to be represented in a DN-safe form. |
| | | */ |
| | | private void quoteAttributeValue(StringBuilder buffer, |
| | | String value) { |
| | | assert debugEnter(CLASS_NAME, "quoteAttributeValue", String |
| | | .valueOf(value)); |
| | | |
| | | // Do nothing if the value is empty. |
| | | int length = value.length(); |
| | | if (length == 0) { |
| | | return; |
| | | } |
| | | |
| | | // Assume 1-byte UTF8 and that no quoting will be required. |
| | | buffer.ensureCapacity(buffer.length() + length); |
| | | |
| | | // Quote leading space or #. |
| | | char c = value.charAt(0); |
| | | if (c == ' ' || c == '#') { |
| | | buffer.append('\\'); |
| | | buffer.append(c); |
| | | } else { |
| | | quoteChar(buffer, c); |
| | | } |
| | | |
| | | // Process the remainder of the string. |
| | | for (int i = 1; i < (length - 1); i++) { |
| | | quoteChar(buffer, value.charAt(i)); |
| | | } |
| | | |
| | | // Quote trailing space. |
| | | if (length > 1) { |
| | | c = value.charAt(length - 1); |
| | | if (c == ' ') { |
| | | buffer.append('\\'); |
| | | buffer.append(c); |
| | | } else { |
| | | quoteChar(buffer, c); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Encode a single attribute value from an RDN according to the DN |
| | | * string encoding rules. |
| | | * |
| | | * @param buffer |
| | | * Append the character to this buffer. |
| | | * @param c |
| | | * The character to be encoded. |
| | | */ |
| | | private void quoteChar(StringBuilder buffer, char c) { |
| | | if ((c < ' ') || (c > '~')) { |
| | | for (byte b : getBytes(String.valueOf(c))) { |
| | | buffer.append('\\'); |
| | | buffer.append(byteToLowerHex(b)); |
| | | } |
| | | } else { |
| | | switch (c) { |
| | | case ',': |
| | | case '+': |
| | | case '"': |
| | | case '\\': |
| | | case '<': |
| | | case '>': |
| | | case ';': |
| | | buffer.append('\\'); |
| | | } |
| | | |
| | | buffer.append(c); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Parses an attribute name from the provided DN string starting at |
| | | * the specified location. |
| | | * |
| | | * @param dnString |
| | | * The DN string to be parsed. |
| | | * @param pos |
| | | * The position at which to start parsing the attribute |
| | | * name. |
| | | * @param attributeName |
| | | * The buffer to which to append the parsed attribute name. |
| | | * @return The position of the first character that is not part of |
| | | * the attribute name. |
| | | * @throws DirectoryException |
| | | * If it was not possible to parse a valid attribute name |
| | | * from the provided DN string. |
| | | */ |
| | | private static int parseAttributeName(String dnString, int pos, |
| | | StringBuilder attributeName) throws DirectoryException { |
| | | assert debugEnter(CLASS_NAME, "parseAttributeName", String |
| | | .valueOf(dnString), String.valueOf(pos), |
| | | "java.lang.StringBuilder"); |
| | | boolean allowExceptions = DirectoryServer |
| | | .allowAttributeNameExceptions(); |
| | | |
| | | int length = dnString.length(); |
| | | |
| | | // Skip over any leading spaces. |
| | | if (pos < length) { |
| | | while (dnString.charAt(pos) == ' ') { |
| | | pos++; |
| | | if (pos == length) { |
| | | // This means that the remainder of the DN was completely |
| | | // comprised of spaces. If we have gotten here, then we |
| | | // know that there is at least one RDN component, and |
| | | // therefore the last non-space character of the DN must |
| | | // have been a comma. This is not acceptable. |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_END_WITH_COMMA; |
| | | String message = getMessage(msgID, dnString); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | } |
| | | } |
| | | |
| | | // Next, we should find the attribute name for this RDN component. |
| | | // It may either be a name (with only letters, digits, and dashes |
| | | // and starting with a letter) or an OID (with only digits and |
| | | // periods, optionally prefixed with "oid."), and there is also a |
| | | // special case in which we will allow underscores. Because of |
| | | // the complexity involved, read the entire name first with |
| | | // minimal validation and then do more thorough validation later. |
| | | boolean checkForOID = false; |
| | | boolean endOfName = false; |
| | | while (pos < length) { |
| | | // To make the switch more efficient, we'll include all ASCII |
| | | // characters in the range of allowed values and then reject the |
| | | // ones that aren't allowed. |
| | | char c = dnString.charAt(pos); |
| | | switch (c) { |
| | | case ' ': |
| | | // This should denote the end of the attribute name. |
| | | endOfName = true; |
| | | break; |
| | | |
| | | case '!': |
| | | case '"': |
| | | case '#': |
| | | case '$': |
| | | case '%': |
| | | case '&': |
| | | case '\'': |
| | | case '(': |
| | | case ')': |
| | | case '*': |
| | | case '+': |
| | | case ',': |
| | | // None of these are allowed in an attribute name or any |
| | | // character immediately following it. |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_ATTR_ILLEGAL_CHAR; |
| | | String message = getMessage(msgID, dnString, c, pos); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | |
| | | case '-': |
| | | // This will be allowed as long as it isn't the first |
| | | // character in the attribute name. |
| | | if (attributeName.length() > 0) { |
| | | attributeName.append(c); |
| | | } else { |
| | | msgID = MSGID_ATTR_SYNTAX_DN_ATTR_ILLEGAL_INITIAL_DASH; |
| | | message = getMessage(msgID, dnString, c); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | break; |
| | | |
| | | case '.': |
| | | // The period could be allowed if the attribute name is |
| | | // actually expressed as an OID. We'll accept it for now, |
| | | // but make sure to check it later. |
| | | attributeName.append(c); |
| | | checkForOID = true; |
| | | break; |
| | | |
| | | case '/': |
| | | // This is not allowed in an attribute name or any character |
| | | // immediately following it. |
| | | msgID = MSGID_ATTR_SYNTAX_DN_ATTR_ILLEGAL_CHAR; |
| | | message = getMessage(msgID, dnString, c, pos); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | |
| | | case '0': |
| | | case '1': |
| | | case '2': |
| | | case '3': |
| | | case '4': |
| | | case '5': |
| | | case '6': |
| | | case '7': |
| | | case '8': |
| | | case '9': |
| | | // Digits are always allowed if they are not the first |
| | | // character. However, they may be allowed if they are the |
| | | // first character if the valid is an OID or if the |
| | | // attribute name exceptions option is enabled. Therefore, |
| | | // we'll accept it now and check it later. |
| | | attributeName.append(c); |
| | | break; |
| | | |
| | | case ':': |
| | | case ';': // NOTE: attribute options are not allowed in a DN. |
| | | case '<': |
| | | // None of these are allowed in an attribute name or any |
| | | // character immediately following it. |
| | | msgID = MSGID_ATTR_SYNTAX_DN_ATTR_ILLEGAL_CHAR; |
| | | message = getMessage(msgID, dnString, c, pos); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | |
| | | case '=': |
| | | // This should denote the end of the attribute name. |
| | | endOfName = true; |
| | | break; |
| | | |
| | | case '>': |
| | | case '?': |
| | | case '@': |
| | | // None of these are allowed in an attribute name or any |
| | | // character immediately following it. |
| | | msgID = MSGID_ATTR_SYNTAX_DN_ATTR_ILLEGAL_CHAR; |
| | | message = getMessage(msgID, dnString, c, pos); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | |
| | | case 'A': |
| | | case 'B': |
| | | case 'C': |
| | | case 'D': |
| | | case 'E': |
| | | case 'F': |
| | | case 'G': |
| | | case 'H': |
| | | case 'I': |
| | | case 'J': |
| | | case 'K': |
| | | case 'L': |
| | | case 'M': |
| | | case 'N': |
| | | case 'O': |
| | | case 'P': |
| | | case 'Q': |
| | | case 'R': |
| | | case 'S': |
| | | case 'T': |
| | | case 'U': |
| | | case 'V': |
| | | case 'W': |
| | | case 'X': |
| | | case 'Y': |
| | | case 'Z': |
| | | // These will always be allowed. |
| | | attributeName.append(c); |
| | | break; |
| | | |
| | | case '[': |
| | | case '\\': |
| | | case ']': |
| | | case '^': |
| | | // None of these are allowed in an attribute name or any |
| | | // character immediately following it. |
| | | msgID = MSGID_ATTR_SYNTAX_DN_ATTR_ILLEGAL_CHAR; |
| | | message = getMessage(msgID, dnString, c, pos); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | |
| | | case '_': |
| | | // This will never be allowed as the first character. It |
| | | // may be allowed for subsequent characters if the attribute |
| | | // name exceptions option is enabled. |
| | | if (attributeName.length() == 0) { |
| | | msgID = |
| | | MSGID_ATTR_SYNTAX_DN_ATTR_ILLEGAL_INITIAL_UNDERSCORE; |
| | | message = getMessage(msgID, dnString, |
| | | ATTR_ALLOW_ATTRIBUTE_NAME_EXCEPTIONS); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } else if (allowExceptions) { |
| | | attributeName.append(c); |
| | | } else { |
| | | msgID = MSGID_ATTR_SYNTAX_DN_ATTR_ILLEGAL_UNDERSCORE_CHAR; |
| | | message = getMessage(msgID, dnString, |
| | | ATTR_ALLOW_ATTRIBUTE_NAME_EXCEPTIONS); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | break; |
| | | |
| | | case '`': |
| | | // This is not allowed in an attribute name or any character |
| | | // immediately following it. |
| | | msgID = MSGID_ATTR_SYNTAX_DN_ATTR_ILLEGAL_CHAR; |
| | | message = getMessage(msgID, dnString, c, pos); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | |
| | | case 'a': |
| | | case 'b': |
| | | case 'c': |
| | | case 'd': |
| | | case 'e': |
| | | case 'f': |
| | | case 'g': |
| | | case 'h': |
| | | case 'i': |
| | | case 'j': |
| | | case 'k': |
| | | case 'l': |
| | | case 'm': |
| | | case 'n': |
| | | case 'o': |
| | | case 'p': |
| | | case 'q': |
| | | case 'r': |
| | | case 's': |
| | | case 't': |
| | | case 'u': |
| | | case 'v': |
| | | case 'w': |
| | | case 'x': |
| | | case 'y': |
| | | case 'z': |
| | | // These will always be allowed. |
| | | attributeName.append(c); |
| | | break; |
| | | |
| | | default: |
| | | // This is not allowed in an attribute name or any character |
| | | // immediately following it. |
| | | msgID = MSGID_ATTR_SYNTAX_DN_ATTR_ILLEGAL_CHAR; |
| | | message = getMessage(msgID, dnString, c, pos); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | |
| | | if (endOfName) { |
| | | break; |
| | | } |
| | | |
| | | pos++; |
| | | } |
| | | |
| | | // We should now have the full attribute name. However, we may |
| | | // still need to perform some validation, particularly if the |
| | | // name contains a period or starts with a digit. It must also |
| | | // have at least one character. |
| | | if (attributeName.length() == 0) { |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_ATTR_NO_NAME; |
| | | String message = getMessage(msgID, dnString); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } else if (checkForOID) { |
| | | boolean validOID = true; |
| | | |
| | | int namePos = 0; |
| | | int nameLength = attributeName.length(); |
| | | char ch = attributeName.charAt(0); |
| | | if ((ch == 'o') || (ch == 'O')) { |
| | | if (nameLength <= 4) { |
| | | validOID = false; |
| | | } else { |
| | | if ((((ch = attributeName.charAt(1)) == 'i') || (ch == 'I')) |
| | | && (((ch = attributeName.charAt(2)) == 'd') |
| | | || (ch == 'D')) |
| | | && (attributeName.charAt(3) == '.')) { |
| | | attributeName.delete(0, 4); |
| | | nameLength -= 4; |
| | | } else { |
| | | validOID = false; |
| | | } |
| | | } |
| | | } |
| | | |
| | | while (validOID && (namePos < nameLength)) { |
| | | ch = attributeName.charAt(namePos++); |
| | | if (isDigit(ch)) { |
| | | while (validOID && (namePos < nameLength) |
| | | && isDigit(attributeName.charAt(namePos))) { |
| | | namePos++; |
| | | } |
| | | |
| | | if ((namePos < nameLength) |
| | | && (attributeName.charAt(namePos) != '.')) { |
| | | validOID = false; |
| | | } |
| | | } else if (ch == '.') { |
| | | if ((namePos == 1) |
| | | || (attributeName.charAt(namePos - 2) == '.')) { |
| | | validOID = false; |
| | | } |
| | | } else { |
| | | validOID = false; |
| | | } |
| | | } |
| | | |
| | | if (validOID && (attributeName.charAt(nameLength - 1) == '.')) { |
| | | validOID = false; |
| | | } |
| | | |
| | | if (!validOID) { |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_ATTR_ILLEGAL_PERIOD; |
| | | String message = getMessage(msgID, dnString, attributeName |
| | | .toString()); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | } else if (isDigit(attributeName.charAt(0)) |
| | | && (!allowExceptions)) { |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_ATTR_ILLEGAL_INITIAL_DIGIT; |
| | | String message = getMessage(msgID, dnString, attributeName |
| | | .charAt(0), ATTR_ALLOW_ATTRIBUTE_NAME_EXCEPTIONS); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | |
| | | return pos; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Parses the attribute value from the provided DN string starting |
| | | * at the specified location. When the value has been parsed, it |
| | | * will be assigned to the provided ASN.1 octet string. |
| | | * |
| | | * @param dnString |
| | | * The DN string to be parsed. |
| | | * @param pos |
| | | * The position of the first character in the attribute |
| | | * value to parse. |
| | | * @param attributeValue |
| | | * The ASN.1 octet string whose value should be set to the |
| | | * parsed attribute value when this method completes |
| | | * successfully. |
| | | * @return The position of the first character that is not part of |
| | | * the attribute value. |
| | | * @throws DirectoryException |
| | | * If it was not possible to parse a valid attribute value |
| | | * from the provided DN string. |
| | | */ |
| | | private static int parseAttributeValue(String dnString, int pos, |
| | | ByteString attributeValue) throws DirectoryException { |
| | | assert debugEnter(CLASS_NAME, "parseAttributeValue", String |
| | | .valueOf(dnString), String.valueOf(pos), |
| | | "java.lang.StringBuilder"); |
| | | |
| | | // All leading spaces have already been stripped so we can start |
| | | // reading the value. However, it may be empty so check for that. |
| | | int length = dnString.length(); |
| | | if (pos >= length) { |
| | | attributeValue.setValue(""); |
| | | return pos; |
| | | } |
| | | |
| | | // Look at the first character. If it is an octothorpe (#), then |
| | | // that means that the value should be a hex string. |
| | | char c = dnString.charAt(pos++); |
| | | if (c == '#') { |
| | | // The first two characters must be hex characters. |
| | | StringBuilder hexString = new StringBuilder(); |
| | | if ((pos + 2) > length) { |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_HEX_VALUE_TOO_SHORT; |
| | | String message = getMessage(msgID, dnString); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | |
| | | for (int i = 0; i < 2; i++) { |
| | | c = dnString.charAt(pos++); |
| | | if (isHexDigit(c)) { |
| | | hexString.append(c); |
| | | } else { |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_INVALID_HEX_DIGIT; |
| | | String message = getMessage(msgID, dnString, c); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | } |
| | | |
| | | // The rest of the value must be a multiple of two hex |
| | | // characters. The end of the value may be designated by the |
| | | // end of the DN, a comma or semicolon, or a space. |
| | | while (pos < length) { |
| | | c = dnString.charAt(pos++); |
| | | if (isHexDigit(c)) { |
| | | hexString.append(c); |
| | | |
| | | if (pos < length) { |
| | | c = dnString.charAt(pos++); |
| | | if (isHexDigit(c)) { |
| | | hexString.append(c); |
| | | } else { |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_INVALID_HEX_DIGIT; |
| | | String message = getMessage(msgID, dnString, c); |
| | | throw new DirectoryException( |
| | | ResultCode.INVALID_DN_SYNTAX, message, msgID); |
| | | } |
| | | } else { |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_HEX_VALUE_TOO_SHORT; |
| | | String message = getMessage(msgID, dnString); |
| | | throw new DirectoryException( |
| | | ResultCode.INVALID_DN_SYNTAX, message, msgID); |
| | | } |
| | | } else if ((c == ' ') || (c == ',') || (c == ';') |
| | | || (c == '+')) { |
| | | // This denotes the end of the value. |
| | | pos--; |
| | | break; |
| | | } else { |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_INVALID_HEX_DIGIT; |
| | | String message = getMessage(msgID, dnString, c); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | } |
| | | |
| | | // At this point, we should have a valid hex string. Convert it |
| | | // to a byte array and set that as the value of the provided |
| | | // octet string. |
| | | try { |
| | | attributeValue.setValue(hexStringToByteArray(hexString |
| | | .toString())); |
| | | return pos; |
| | | } catch (Exception e) { |
| | | assert debugException(CLASS_NAME, "parseAttributeValue", e); |
| | | |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_ATTR_VALUE_DECODE_FAILURE; |
| | | String message = getMessage(msgID, dnString, String |
| | | .valueOf(e)); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | } |
| | | |
| | | // If the first character is a quotation mark, then the value |
| | | // should continue until the corresponding closing quotation mark. |
| | | else if (c == '"') { |
| | | // Keep reading until we find an unescaped closing quotation |
| | | // mark. |
| | | boolean escaped = false; |
| | | StringBuilder valueString = new StringBuilder(); |
| | | while (true) { |
| | | if (pos >= length) { |
| | | // We hit the end of the DN before the closing quote. |
| | | // That's an error. |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_UNMATCHED_QUOTE; |
| | | String message = getMessage(msgID, dnString); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | |
| | | c = dnString.charAt(pos++); |
| | | if (escaped) { |
| | | // The previous character was an escape, so we'll take this |
| | | // one no matter what. |
| | | valueString.append(c); |
| | | escaped = false; |
| | | } else if (c == '\\') { |
| | | // The next character is escaped. Set a flag to denote |
| | | // this, but don't include the backslash. |
| | | escaped = true; |
| | | } else if (c == '"') { |
| | | // This is the end of the value. |
| | | break; |
| | | } else { |
| | | // This is just a regular character that should be in the |
| | | // value. |
| | | valueString.append(c); |
| | | } |
| | | } |
| | | |
| | | attributeValue.setValue(valueString.toString()); |
| | | return pos; |
| | | } |
| | | |
| | | // Otherwise, use general parsing to find the end of the value. |
| | | else { |
| | | boolean escaped; |
| | | StringBuilder valueString = new StringBuilder(); |
| | | StringBuilder hexChars = new StringBuilder(); |
| | | |
| | | if (c == '\\') { |
| | | escaped = true; |
| | | } else { |
| | | escaped = false; |
| | | valueString.append(c); |
| | | } |
| | | |
| | | // Keep reading until we find an unescaped comma or plus sign or |
| | | // the end of the DN. |
| | | while (true) { |
| | | if (pos >= length) { |
| | | // This is the end of the DN and therefore the end of the |
| | | // value. If there are any hex characters, then we need to |
| | | // deal with them accordingly. |
| | | appendHexChars(dnString, valueString, hexChars); |
| | | break; |
| | | } |
| | | |
| | | c = dnString.charAt(pos++); |
| | | if (escaped) { |
| | | // The previous character was an escape, so we'll take this |
| | | // one. However, this could be a hex digit, and if that's |
| | | // the case then the escape would actually be in front of |
| | | // two hex digits that should be treated as a special |
| | | // character. |
| | | if (isHexDigit(c)) { |
| | | // It is a hexadecimal digit, so the next digit must be |
| | | // one too. However, this could be just one in a series |
| | | // of escaped hex pairs that is used in a string |
| | | // containing one or more multi-byte UTF-8 characters so |
| | | // we can't just treat this byte in isolation. Collect |
| | | // all the bytes together and make sure to take care of |
| | | // these hex bytes before appending anything else to the |
| | | // value. |
| | | if (pos >= length) { |
| | | int msgID = |
| | | MSGID_ATTR_SYNTAX_DN_ESCAPED_HEX_VALUE_INVALID; |
| | | String message = getMessage(msgID, dnString); |
| | | throw new DirectoryException( |
| | | ResultCode.INVALID_DN_SYNTAX, message, msgID); |
| | | } else { |
| | | char c2 = dnString.charAt(pos++); |
| | | if (isHexDigit(c2)) { |
| | | hexChars.append(c); |
| | | hexChars.append(c2); |
| | | } else { |
| | | int msgID = |
| | | MSGID_ATTR_SYNTAX_DN_ESCAPED_HEX_VALUE_INVALID; |
| | | String message = getMessage(msgID, dnString); |
| | | throw new DirectoryException( |
| | | ResultCode.INVALID_DN_SYNTAX, message, msgID); |
| | | } |
| | | } |
| | | } else { |
| | | appendHexChars(dnString, valueString, hexChars); |
| | | valueString.append(c); |
| | | } |
| | | |
| | | escaped = false; |
| | | } else if (c == '\\') { |
| | | escaped = true; |
| | | } else if ((c == ',') || (c == ';') || (c == '+')) { |
| | | appendHexChars(dnString, valueString, hexChars); |
| | | pos--; |
| | | break; |
| | | } else { |
| | | appendHexChars(dnString, valueString, hexChars); |
| | | valueString.append(c); |
| | | } |
| | | } |
| | | |
| | | // Strip off any unescaped spaces that may be at the end of the |
| | | // value. |
| | | if (pos > 2 && dnString.charAt(pos - 1) == ' ' |
| | | && dnString.charAt(pos - 2) != '\\') { |
| | | int lastPos = valueString.length() - 1; |
| | | while (lastPos > 0) { |
| | | if (valueString.charAt(lastPos) == ' ') { |
| | | valueString.delete(lastPos, lastPos + 1); |
| | | lastPos--; |
| | | } else { |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | |
| | | attributeValue.setValue(valueString.toString()); |
| | | return pos; |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Decodes a hexadecimal string from the provided |
| | | * <code>hexChars</code> buffer, converts it to a byte array, and |
| | | * then converts that to a UTF-8 string. The resulting UTF-8 string |
| | | * will be appended to the provided <code>valueString</code> |
| | | * buffer, and the <code>hexChars</code> buffer will be cleared. |
| | | * |
| | | * @param dnString |
| | | * The DN string that is being decoded. |
| | | * @param valueString |
| | | * The buffer containing the value to which the decoded |
| | | * string should be appended. |
| | | * @param hexChars |
| | | * The buffer containing the hexadecimal characters to |
| | | * decode to a UTF-8 string. |
| | | * @throws DirectoryException |
| | | * If any problem occurs during the decoding process. |
| | | */ |
| | | private static void appendHexChars(String dnString, |
| | | StringBuilder valueString, StringBuilder hexChars) |
| | | throws DirectoryException { |
| | | try { |
| | | byte[] hexBytes = hexStringToByteArray(hexChars.toString()); |
| | | valueString.append(new String(hexBytes, "UTF-8")); |
| | | hexChars.delete(0, hexChars.length()); |
| | | } catch (Exception e) { |
| | | assert debugException(CLASS_NAME, "appendHexChars", e); |
| | | |
| | | int msgID = MSGID_ATTR_SYNTAX_DN_ATTR_VALUE_DECODE_FAILURE; |
| | | String message = getMessage(msgID, dnString, String.valueOf(e)); |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | } |
| | | |
| | | } |
| | |
| | | // attributes, then do so. |
| | | if (dnAttributes) |
| | | { |
| | | for (RDN rdn : entry.getDN().getRDNComponents()) |
| | | DN entryDN = entry.getDN(); |
| | | int count = entryDN.getNumComponents(); |
| | | for (int rdnIndex = 0; rdnIndex < count; rdnIndex++) |
| | | { |
| | | AttributeType[] types = rdn.getAttributeTypes(); |
| | | AttributeValue[] values = rdn.getAttributeValues(); |
| | | |
| | | for (int i=0; i < types.length; i++) |
| | | RDN rdn = entryDN.getRDN(rdnIndex); |
| | | int numAVAs = rdn.getNumValues(); |
| | | for (int i=0; i < numAVAs; i++) |
| | | { |
| | | try |
| | | { |
| | | if ((attributeType == null) || |
| | | attributeType.equals(types[i])) |
| | | attributeType.equals(rdn.getAttributeType(i))) |
| | | { |
| | | |
| | | AttributeValue v = rdn.getAttributeValue(i); |
| | | ByteString nv = |
| | | matchingRule.normalizeValue(values[i].getValue()); |
| | | matchingRule.normalizeValue(v.getValue()); |
| | | ConditionResult r = |
| | | matchingRule.valuesMatch(nv, normalizedValue); |
| | | switch (r) |
| | |
| | | int length = line.length(); |
| | | if (colonPos == (length-1)) |
| | | { |
| | | return new DN(new ArrayList<RDN>(0)); |
| | | return DN.nullDN(); |
| | | } |
| | | |
| | | if (line.charAt(colonPos+1) == ':') |
| | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether the two array lists are equal. They will be considered |
| | | * equal if they have the same number of elements, and the corresponding |
| | | * elements between them are equal (in the same order). |
| | | * Compare two byte arrays for order. Returns a negative integer, |
| | | * zero, or a positive integer as the first argument is less than, |
| | | * equal to, or greater than the second. |
| | | * |
| | | * @param list1 The first list for which to make the determination. |
| | | * @param list2 The second list for which to make the determination. |
| | | * @param a |
| | | * The first byte array to be compared. |
| | | * @param a2 |
| | | * The second byte array to be compared. |
| | | * @return Returns a negative integer, zero, or a positive integer |
| | | * if the first byte array is less than, equal to, or greater |
| | | * than the second. |
| | | */ |
| | | public static int compare(byte[] a, byte[] a2) { |
| | | if (a == a2) { |
| | | return 0; |
| | | } |
| | | |
| | | if (a == null) { |
| | | return -1; |
| | | } |
| | | |
| | | if (a2 == null) { |
| | | return 1; |
| | | } |
| | | |
| | | int minLength = Math.min(a.length, a2.length); |
| | | for (int i = 0; i < minLength; i++) { |
| | | if (a[i] != a2[i]) { |
| | | if (a[i] < a2[i]) { |
| | | return -1; |
| | | } else if (a[i] > a2[i]) { |
| | | return 1; |
| | | } |
| | | } |
| | | } |
| | | |
| | | return (a.length - a2.length); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether the two array lists are equal. They will be |
| | | * considered equal if they have the same number of elements, and |
| | | * the corresponding elements between them are equal (in the same |
| | | * order). |
| | | * |
| | | * @param list1 |
| | | * The first list for which to make the determination. |
| | | * @param list2 |
| | | * The second list for which to make the determination. |
| | | * @return <CODE>true</CODE> if the two array lists are equal, or |
| | | * <CODE>false</CODE> if they are not. |
| | | */ |
| | |
| | | |
| | | // Get the information about the RDN attributes. |
| | | RDN rdn = dn.getRDN(); |
| | | AttributeType[] rdnTypes = rdn.getAttributeTypes(); |
| | | String[] rdnNames = rdn.getAttributeNames(); |
| | | AttributeValue[] rdnValues = rdn.getAttributeValues(); |
| | | |
| | | int numAVAs = rdn.getNumValues(); |
| | | |
| | | // If there is only one RDN attribute, then see which objectclass we should |
| | | // use. |
| | | ObjectClass structuralClass; |
| | | if (rdnTypes.length == 1) |
| | | if (numAVAs == 1) |
| | | { |
| | | if (rdnTypes[0].hasName(ATTR_C)) |
| | | AttributeType attrType = rdn.getAttributeType(0); |
| | | |
| | | if (attrType.hasName(ATTR_C)) |
| | | { |
| | | structuralClass = DirectoryServer.getObjectClass(OC_COUNTRY, true); |
| | | } |
| | | else if (rdnTypes[0].hasName(ATTR_DC)) |
| | | else if (attrType.hasName(ATTR_DC)) |
| | | { |
| | | structuralClass = DirectoryServer.getObjectClass(OC_DOMAIN, true); |
| | | } |
| | | else if (rdnTypes[0].hasName(ATTR_O)) |
| | | else if (attrType.hasName(ATTR_O)) |
| | | { |
| | | structuralClass = DirectoryServer.getObjectClass(OC_ORGANIZATION, true); |
| | | } |
| | | else if (rdnTypes[0].hasName(ATTR_OU)) |
| | | else if (attrType.hasName(ATTR_OU)) |
| | | { |
| | | structuralClass = |
| | | DirectoryServer.getObjectClass(OC_ORGANIZATIONAL_UNIT_LC, true); |
| | |
| | | new LinkedHashMap<AttributeType,List<Attribute>>(); |
| | | |
| | | boolean extensibleObjectAdded = false; |
| | | for (int i=0; i < rdnTypes.length; i++) |
| | | for (int i=0; i < numAVAs; i++) |
| | | { |
| | | AttributeType attrType = rdn.getAttributeType(i); |
| | | AttributeValue attrValue = rdn.getAttributeValue(i); |
| | | String attrName = rdn.getAttributeName(i); |
| | | |
| | | // First, see if this type is allowed by the untypedObject class. If not, |
| | | // then we'll need to include the extensibleObject class. |
| | | if ((! structuralClass.isRequiredOrOptional(rdnTypes[i])) && |
| | | if ((! structuralClass.isRequiredOrOptional(attrType)) && |
| | | (! extensibleObjectAdded)) |
| | | { |
| | | ObjectClass extensibleObjectOC = |
| | |
| | | // Create the attribute and add it to the appropriate map. |
| | | LinkedHashSet<AttributeValue> valueSet = |
| | | new LinkedHashSet<AttributeValue>(1); |
| | | valueSet.add(rdnValues[i]); |
| | | valueSet.add(attrValue); |
| | | |
| | | if (rdnTypes[i].isOperational()) |
| | | if (attrType.isOperational()) |
| | | { |
| | | List<Attribute> attrList = operationalAttributes.get(rdnTypes[i]); |
| | | List<Attribute> attrList = operationalAttributes.get(attrType); |
| | | if ((attrList == null) || attrList.isEmpty()) |
| | | { |
| | | attrList = new ArrayList<Attribute>(1); |
| | | attrList.add(new Attribute(rdnTypes[i], rdnNames[i], valueSet)); |
| | | operationalAttributes.put(rdnTypes[i], attrList); |
| | | attrList.add(new Attribute(attrType, attrName, valueSet)); |
| | | operationalAttributes.put(attrType, attrList); |
| | | } |
| | | else |
| | | { |
| | | Attribute attr = attrList.get(0); |
| | | attr.getValues().add(rdnValues[i]); |
| | | attr.getValues().add(attrValue); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | List<Attribute> attrList = userAttributes.get(rdnTypes[i]); |
| | | List<Attribute> attrList = userAttributes.get(attrType); |
| | | if ((attrList == null) || attrList.isEmpty()) |
| | | { |
| | | attrList = new ArrayList<Attribute>(1); |
| | | attrList.add(new Attribute(rdnTypes[i], rdnNames[i], valueSet)); |
| | | userAttributes.put(rdnTypes[i], attrList); |
| | | attrList.add(new Attribute(attrType, attrName, valueSet)); |
| | | userAttributes.put(attrType, attrList); |
| | | } |
| | | else |
| | | { |
| | | Attribute attr = attrList.get(0); |
| | | attr.getValues().add(rdnValues[i]); |
| | | attr.getValues().add(attrValue); |
| | | } |
| | | } |
| | | } |
| | |
| | | import org.opends.server.tools.makeldif.MakeLDIFInputStream; |
| | | import org.opends.server.tools.makeldif.TemplateFile; |
| | | import org.opends.server.types.DN; |
| | | import org.opends.server.types.DNComparator; |
| | | import org.opends.server.types.LDIFImportConfig; |
| | | import org.opends.server.types.ResultCode; |
| | | import org.opends.server.DirectoryServerTestCase; |
| | |
| | | */ |
| | | @Test(groups = { "precommit", "jeb" }) |
| | | public abstract class JebTestCase extends DirectoryServerTestCase { |
| | | private DNComparator comparator = new DNComparator(); |
| | | private TreeMap<DN,Entry> entryTreeMap = new TreeMap<DN,Entry>(comparator); |
| | | private TreeMap<DN,Entry> entryTreeMap = new TreeMap<DN,Entry>(); |
| | | int numEntries; |
| | | |
| | | /** |
| | |
| | | noControls, new ASN1OctetString("cn=Directory Manager"), |
| | | new ASN1OctetString("password")), |
| | | new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(), |
| | | null, new DN(), new ASN1OctetString()), |
| | | null, DN.nullDN(), new ASN1OctetString()), |
| | | new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(), |
| | | noControls, new DN(), new ASN1OctetString()), |
| | | noControls, DN.nullDN(), new ASN1OctetString()), |
| | | new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(), |
| | | null, nullDN, new ASN1OctetString()), |
| | | new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(), |
| | | noControls, nullDN, new ASN1OctetString()), |
| | | new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(), |
| | | null, new DN(), nullOS), |
| | | null, DN.nullDN(), nullOS), |
| | | new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(), |
| | | noControls, new DN(), nullOS), |
| | | noControls, DN.nullDN(), nullOS), |
| | | new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(), |
| | | null, nullDN, nullOS), |
| | | new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(), |
| | |
| | | noControls, nullOS, "PLAIN", |
| | | new ASN1OctetString("\u0000u:test.user\u0000password")), |
| | | new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(), |
| | | null, new DN(), "EXTERNAL", null), |
| | | null, DN.nullDN(), "EXTERNAL", null), |
| | | new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(), |
| | | noControls, new DN(), "EXTERNAL", null), |
| | | noControls, DN.nullDN(), "EXTERNAL", null), |
| | | new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(), |
| | | null, nullDN, "EXTERNAL", null), |
| | | new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(), |
| | | noControls, nullDN, "EXTERNAL", null), |
| | | new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(), |
| | | null, new DN(), "PLAIN", |
| | | null, DN.nullDN(), "PLAIN", |
| | | new ASN1OctetString("\u0000u:test.user\u0000password")), |
| | | new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(), |
| | | noControls, new DN(), "PLAIN", |
| | | noControls, DN.nullDN(), "PLAIN", |
| | | new ASN1OctetString("\u0000u:test.user\u0000password")), |
| | | new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(), |
| | | null, nullDN, "PLAIN", |
| | |
| | | new ASN1OctetString("\u0000dn:cn=Directory Manager\u0000password"); |
| | | |
| | | BindOperation bindOperation = |
| | | conn.processSASLBind(new DN(), "PLAIN", saslCreds); |
| | | conn.processSASLBind(DN.nullDN(), "PLAIN", saslCreds); |
| | | assertEquals(bindOperation.getResultCode(), ResultCode.SUCCESS); |
| | | assertNotNull(bindOperation.getSASLAuthUserEntry()); |
| | | } |
| | |
| | | new ASN1OctetString("\u0000dn:cn=Directory Manager\u0000password"); |
| | | |
| | | BindOperation bindOperation = |
| | | conn.processSASLBind(new DN(), "PLAIN", saslCreds); |
| | | conn.processSASLBind(DN.nullDN(), "PLAIN", saslCreds); |
| | | assertEquals(bindOperation.getResultCode(), ResultCode.SUCCESS); |
| | | assertNotNull(bindOperation.getUserEntryDN()); |
| | | } |
| | |
| | | new ASN1OctetString("\u0000dn:cn=Directory Manager\u0000password"); |
| | | |
| | | BindOperation bindOperation = |
| | | conn.processSASLBind(new DN(), "PLAIN", saslCreds); |
| | | conn.processSASLBind(DN.nullDN(), "PLAIN", saslCreds); |
| | | assertEquals(bindOperation.getResultCode(), ResultCode.SUCCESS); |
| | | assertTrue(bindOperation.getProcessingStartTime() > 0); |
| | | assertTrue(bindOperation.getProcessingStopTime() >= |
| | |
| | | new ASN1OctetString("\u0000dn:cn=Directory Manager\u0000password"); |
| | | |
| | | BindOperation bindOperation = |
| | | conn.processSASLBind(new DN(), "PLAIN", saslCreds); |
| | | conn.processSASLBind(DN.nullDN(), "PLAIN", saslCreds); |
| | | assertEquals(bindOperation.getResultCode(), ResultCode.SUCCESS); |
| | | assertNotNull(bindOperation.getResponseLogElements()); |
| | | assertTrue(bindOperation.getResponseLogElements().length > 0); |
| | |
| | | new ASN1OctetString("\u0000dn:cn=Directory Manager\u0000password"); |
| | | |
| | | BindOperation bindOperation = |
| | | conn.processSASLBind(new DN(), "PLAIN", saslCreds); |
| | | conn.processSASLBind(DN.nullDN(), "PLAIN", saslCreds); |
| | | assertEquals(bindOperation.getResultCode(), ResultCode.SUCCESS); |
| | | |
| | | assertTrue(InvocationCounterPlugin.getPreParseCount() > 0); |
| | |
| | | |
| | | BindOperation bindOperation = |
| | | new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(), |
| | | requestControls, new DN(), new ASN1OctetString()); |
| | | requestControls, DN.nullDN(), new ASN1OctetString()); |
| | | bindOperation.run(); |
| | | assertEquals(bindOperation.getResultCode(), |
| | | ResultCode.UNAVAILABLE_CRITICAL_EXTENSION); |
| | |
| | | |
| | | BindOperation bindOperation = |
| | | new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(), |
| | | requestControls, new DN(), "PLAIN", saslCreds); |
| | | requestControls, DN.nullDN(), "PLAIN", saslCreds); |
| | | bindOperation.run(); |
| | | assertEquals(bindOperation.getResultCode(), |
| | | ResultCode.UNAVAILABLE_CRITICAL_EXTENSION); |
| | |
| | | |
| | | BindOperation bindOperation = |
| | | new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(), |
| | | requestControls, new DN(), new ASN1OctetString()); |
| | | requestControls, DN.nullDN(), new ASN1OctetString()); |
| | | bindOperation.run(); |
| | | assertEquals(bindOperation.getResultCode(), ResultCode.SUCCESS); |
| | | } |
| | |
| | | |
| | | BindOperation bindOperation = |
| | | new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(), |
| | | requestControls, new DN(), "PLAIN", saslCreds); |
| | | requestControls, DN.nullDN(), "PLAIN", saslCreds); |
| | | bindOperation.run(); |
| | | assertEquals(bindOperation.getResultCode(), ResultCode.SUCCESS); |
| | | } |
| | |
| | | new DeleteOperation(conn, conn.nextOperationID(), conn.nextMessageID(), |
| | | null, new ASN1OctetString("o=test")), |
| | | new DeleteOperation(conn, conn.nextOperationID(), conn.nextMessageID(), |
| | | new ArrayList<Control>(), new DN()), |
| | | new ArrayList<Control>(), DN.nullDN()), |
| | | new DeleteOperation(conn, conn.nextOperationID(), conn.nextMessageID(), |
| | | null, new DN()), |
| | | null, DN.nullDN()), |
| | | new DeleteOperation(conn, conn.nextOperationID(), conn.nextMessageID(), |
| | | new ArrayList<Control>(), DN.decode("o=test")), |
| | | new DeleteOperation(conn, conn.nextOperationID(), conn.nextMessageID(), |
| | |
| | | new Attribute("description", "foo"))); |
| | | |
| | | opList.add(new ModifyOperation(conn, conn.nextOperationID(), |
| | | conn.nextMessageID(), null, new DN(), mods)); |
| | | conn.nextMessageID(), null, DN.nullDN(), mods)); |
| | | opList.add(new ModifyOperation(conn, conn.nextOperationID(), |
| | | conn.nextMessageID(), noControls, new DN(), |
| | | conn.nextMessageID(), noControls, DN.nullDN(), |
| | | mods)); |
| | | opList.add(new ModifyOperation(conn, conn.nextOperationID(), |
| | | conn.nextMessageID(), null, |
| | |
| | | new Attribute("description", "foo"))); |
| | | |
| | | opList.add(new ModifyOperation(conn, conn.nextOperationID(), |
| | | conn.nextMessageID(), null, new DN(), mods)); |
| | | conn.nextMessageID(), null, DN.nullDN(), mods)); |
| | | opList.add(new ModifyOperation(conn, conn.nextOperationID(), |
| | | conn.nextMessageID(), noControls, new DN(), |
| | | conn.nextMessageID(), noControls, DN.nullDN(), |
| | | mods)); |
| | | opList.add(new ModifyOperation(conn, conn.nextOperationID(), |
| | | conn.nextMessageID(), null, |
| | |
| | | new Attribute("description", "foo"))); |
| | | |
| | | opList.add(new ModifyOperation(conn, conn.nextOperationID(), |
| | | conn.nextMessageID(), null, new DN(), mods)); |
| | | conn.nextMessageID(), null, DN.nullDN(), mods)); |
| | | opList.add(new ModifyOperation(conn, conn.nextOperationID(), |
| | | conn.nextMessageID(), noControls, new DN(), |
| | | conn.nextMessageID(), noControls, DN.nullDN(), |
| | | mods)); |
| | | opList.add(new ModifyOperation(conn, conn.nextOperationID(), |
| | | conn.nextMessageID(), null, |
| | |
| | | new Attribute("description", "bar"))); |
| | | |
| | | opList.add(new ModifyOperation(conn, conn.nextOperationID(), |
| | | conn.nextMessageID(), null, new DN(), mods)); |
| | | conn.nextMessageID(), null, DN.nullDN(), mods)); |
| | | opList.add(new ModifyOperation(conn, conn.nextOperationID(), |
| | | conn.nextMessageID(), noControls, new DN(), |
| | | conn.nextMessageID(), noControls, DN.nullDN(), |
| | | mods)); |
| | | opList.add(new ModifyOperation(conn, conn.nextOperationID(), |
| | | conn.nextMessageID(), null, |
| | |
| | | new Attribute("cn", "bar"))); |
| | | |
| | | opList.add(new ModifyOperation(conn, conn.nextOperationID(), |
| | | conn.nextMessageID(), null, new DN(), mods)); |
| | | conn.nextMessageID(), null, DN.nullDN(), mods)); |
| | | opList.add(new ModifyOperation(conn, conn.nextOperationID(), |
| | | conn.nextMessageID(), noControls, new DN(), |
| | | conn.nextMessageID(), noControls, DN.nullDN(), |
| | | mods)); |
| | | opList.add(new ModifyOperation(conn, conn.nextOperationID(), |
| | | conn.nextMessageID(), null, |
| | |
| | | new Attribute("description", "foo"))); |
| | | ModifyOperation modifyOperation = |
| | | new ModifyOperation(conn, conn.nextOperationID(), conn.nextMessageID(), |
| | | null, new DN(), mods); |
| | | null, DN.nullDN(), mods); |
| | | assertNotNull(modifyOperation.getEntryDN()); |
| | | } |
| | | |
| | |
| | | new Attribute("description", "foo"))); |
| | | ModifyOperation modifyOperation = |
| | | new ModifyOperation(conn, conn.nextOperationID(), conn.nextMessageID(), |
| | | null, new DN(), mods); |
| | | null, DN.nullDN(), mods); |
| | | assertNotNull(modifyOperation.getEntryDN()); |
| | | |
| | | modifyOperation.setRawEntryDN(new ASN1OctetString("ou=Users,o=test")); |
| | |
| | | Entry newEntry = DirectoryServer.getEntry(DN.decode( |
| | | "uid=user.test0,ou=People,dc=example,dc=com")); |
| | | assertNotNull(newEntry); |
| | | for(AttributeType attribute : newEntry.getDN().getRDN().getAttributeTypes()) |
| | | RDN rdn = newEntry.getDN().getRDN(); |
| | | for (int i = 0; i < rdn.getNumValues(); i++) |
| | | { |
| | | AttributeType attribute = rdn.getAttributeType(i); |
| | | assertTrue(newEntry.hasValue(attribute, null, new AttributeValue(attribute, "user.0"))); |
| | | assertTrue(newEntry.hasValue(attribute, null, new AttributeValue(attribute, "user.test0"))); |
| | | } |
| | |
| | | newEntry = DirectoryServer.getEntry(DN.decode( |
| | | "uid=user.0,ou=People,dc=example,dc=com")); |
| | | assertNotNull(newEntry); |
| | | for(AttributeType attribute : newEntry.getDN().getRDN().getAttributeTypes()) |
| | | rdn = newEntry.getDN().getRDN(); |
| | | for (int i = 0; i < rdn.getNumValues(); i++) |
| | | { |
| | | AttributeType attribute = rdn.getAttributeType(i); |
| | | assertTrue(newEntry.hasValue(attribute, null, new AttributeValue(attribute, "user.0"))); |
| | | assertFalse(newEntry.hasValue(attribute, null, new AttributeValue(attribute, "user.test0"))); |
| | | } |
| | |
| | | Entry newEntry = DirectoryServer.getEntry(DN.decode( |
| | | "uid=user.test0,ou=People,dc=example,dc=com")); |
| | | assertNotNull(newEntry); |
| | | for(AttributeType attribute : newEntry.getDN().getRDN().getAttributeTypes()) |
| | | RDN rdn = newEntry.getDN().getRDN(); |
| | | for (int i = 0; i < rdn.getNumValues(); i++) |
| | | { |
| | | AttributeType attribute = rdn.getAttributeType(i); |
| | | assertTrue(newEntry.hasValue(attribute, null, new AttributeValue(attribute, "user.0"))); |
| | | assertTrue(newEntry.hasValue(attribute, null, new AttributeValue(attribute, "user.test0"))); |
| | | } |
| | |
| | | newEntry = DirectoryServer.getEntry(DN.decode( |
| | | "uid=user.0,ou=People,dc=example,dc=com")); |
| | | assertNotNull(newEntry); |
| | | for(AttributeType attribute : newEntry.getDN().getRDN().getAttributeTypes()) |
| | | rdn = newEntry.getDN().getRDN(); |
| | | for (int i = 0; i < rdn.getNumValues(); i++) |
| | | { |
| | | AttributeType attribute = rdn.getAttributeType(i); |
| | | assertTrue(newEntry.hasValue(attribute, null, new AttributeValue(attribute, "user.0"))); |
| | | assertFalse(newEntry.hasValue(attribute, null, new AttributeValue(attribute, "user.test0"))); |
| | | } |
| | |
| | | Entry newEntry = DirectoryServer.getEntry(DN.decode( |
| | | "uid=user.test0,ou=People,dc=example,dc=com")); |
| | | assertNotNull(newEntry); |
| | | for(AttributeType attribute : newEntry.getDN().getRDN().getAttributeTypes()) |
| | | RDN rdn = newEntry.getDN().getRDN(); |
| | | for (int i = 0; i < rdn.getNumValues(); i++) |
| | | { |
| | | AttributeType attribute = rdn.getAttributeType(i); |
| | | assertFalse(newEntry.hasValue(attribute, null, new AttributeValue(attribute, "user.0"))); |
| | | assertTrue(newEntry.hasValue(attribute, null, new AttributeValue(attribute, "user.test0"))); |
| | | } |
| | |
| | | newEntry = DirectoryServer.getEntry(DN.decode( |
| | | "uid=user.0,ou=People,dc=example,dc=com")); |
| | | assertNotNull(newEntry); |
| | | for(AttributeType attribute : newEntry.getDN().getRDN().getAttributeTypes()) |
| | | rdn = newEntry.getDN().getRDN(); |
| | | for (int i = 0; i < rdn.getNumValues(); i++) |
| | | { |
| | | AttributeType attribute = rdn.getAttributeType(i); |
| | | assertTrue(newEntry.hasValue(attribute, null, new AttributeValue(attribute, "user.0"))); |
| | | assertFalse(newEntry.hasValue(attribute, null, new AttributeValue(attribute, "user.test0"))); |
| | | } |
| | |
| | | Entry newEntry = DirectoryServer.getEntry(DN.decode( |
| | | "uid=user.test0,ou=People,dc=example,dc=com")); |
| | | assertNotNull(newEntry); |
| | | for(AttributeType attribute : newEntry.getDN().getRDN().getAttributeTypes()) |
| | | RDN rdn = newEntry.getDN().getRDN(); |
| | | for (int i = 0; i < rdn.getNumValues(); i++) |
| | | { |
| | | AttributeType attribute = rdn.getAttributeType(i); |
| | | assertFalse(newEntry.hasValue(attribute, null, new AttributeValue(attribute, "user.0"))); |
| | | assertTrue(newEntry.hasValue(attribute, null, new AttributeValue(attribute, "user.test0"))); |
| | | } |
| | |
| | | newEntry = DirectoryServer.getEntry(DN.decode( |
| | | "uid=user.0,ou=People,dc=example,dc=com")); |
| | | assertNotNull(newEntry); |
| | | for(AttributeType attribute : newEntry.getDN().getRDN().getAttributeTypes()) |
| | | rdn = newEntry.getDN().getRDN(); |
| | | for (int i = 0; i < rdn.getNumValues(); i++) |
| | | { |
| | | AttributeType attribute = rdn.getAttributeType(i); |
| | | assertTrue(newEntry.hasValue(attribute, null, new AttributeValue(attribute, "user.0"))); |
| | | assertFalse(newEntry.hasValue(attribute, null, new AttributeValue(attribute, "user.test0"))); |
| | | } |
| | |
| | | Entry newEntry = DirectoryServer.getEntry(DN.decode( |
| | | "uid=user.test0,dc=example,dc=com")); |
| | | assertNotNull(newEntry); |
| | | for(AttributeType attribute : newEntry.getDN().getRDN().getAttributeTypes()) |
| | | RDN rdn = newEntry.getDN().getRDN(); |
| | | for (int i = 0; i < rdn.getNumValues(); i++) |
| | | { |
| | | AttributeType attribute = rdn.getAttributeType(i); |
| | | assertFalse(newEntry.hasValue(attribute, null, new AttributeValue(attribute, "user.0"))); |
| | | assertTrue(newEntry.hasValue(attribute, null, new AttributeValue(attribute, "user.test0"))); |
| | | } |
| | |
| | | newEntry = DirectoryServer.getEntry(DN.decode( |
| | | "uid=user.0,ou=People,dc=example,dc=com")); |
| | | assertNotNull(newEntry); |
| | | for(AttributeType attribute : newEntry.getDN().getRDN().getAttributeTypes()) |
| | | rdn = newEntry.getDN().getRDN(); |
| | | for (int i = 0; i < rdn.getNumValues(); i++) |
| | | { |
| | | AttributeType attribute = rdn.getAttributeType(i); |
| | | assertTrue(newEntry.hasValue(attribute, null, new AttributeValue(attribute, "user.0"))); |
| | | assertFalse(newEntry.hasValue(attribute, null, new AttributeValue(attribute, "user.test0"))); |
| | | } |
| | |
| | | Entry newEntry = DirectoryServer.getEntry(DN.decode( |
| | | "uid=user.test0,dc=example,dc=com")); |
| | | assertNotNull(newEntry); |
| | | for(AttributeType attribute : newEntry.getDN().getRDN().getAttributeTypes()) |
| | | RDN rdn = newEntry.getDN().getRDN(); |
| | | for (int i = 0; i < rdn.getNumValues(); i++) |
| | | { |
| | | AttributeType attribute = rdn.getAttributeType(i); |
| | | assertFalse(newEntry.hasValue(attribute, null, new AttributeValue(attribute, "user.0"))); |
| | | assertTrue(newEntry.hasValue(attribute, null, new AttributeValue(attribute, "user.test0"))); |
| | | } |
| | |
| | | newEntry = DirectoryServer.getEntry(DN.decode( |
| | | "uid=user.0,ou=People,dc=example,dc=com")); |
| | | assertNotNull(newEntry); |
| | | for(AttributeType attribute : newEntry.getDN().getRDN().getAttributeTypes()) |
| | | rdn = newEntry.getDN().getRDN(); |
| | | for (int i = 0; i < rdn.getNumValues(); i++) |
| | | { |
| | | AttributeType attribute = rdn.getAttributeType(i); |
| | | assertTrue(newEntry.hasValue(attribute, null, new AttributeValue(attribute, "user.0"))); |
| | | assertFalse(newEntry.hasValue(attribute, null, new AttributeValue(attribute, "user.test0"))); |
| | | } |
| | |
| | | Entry newEntry = DirectoryServer.getEntry(DN.decode( |
| | | "uid=user.test0,ou=People,dc=example,dc=com")); |
| | | assertNotNull(newEntry); |
| | | for(AttributeType attribute : newEntry.getDN().getRDN().getAttributeTypes()) |
| | | RDN rdn = newEntry.getDN().getRDN(); |
| | | for (int i = 0; i < rdn.getNumValues(); i++) |
| | | { |
| | | AttributeType attribute = rdn.getAttributeType(i); |
| | | assertTrue(newEntry.hasValue(attribute, null, new AttributeValue(attribute, "user.0"))); |
| | | assertTrue(newEntry.hasValue(attribute, null, new AttributeValue(attribute, "user.test0"))); |
| | | } |
| | |
| | | newEntry = DirectoryServer.getEntry(DN.decode( |
| | | "uid=user.0,ou=People,dc=example,dc=com")); |
| | | assertNotNull(newEntry); |
| | | for(AttributeType attribute : newEntry.getDN().getRDN().getAttributeTypes()) |
| | | rdn = newEntry.getDN().getRDN(); |
| | | for (int i = 0; i < rdn.getNumValues(); i++) |
| | | { |
| | | AttributeType attribute = rdn.getAttributeType(i); |
| | | assertTrue(newEntry.hasValue(attribute, null, new AttributeValue(attribute, "user.0"))); |
| | | assertFalse(newEntry.hasValue(attribute, null, new AttributeValue(attribute, "user.test0"))); |
| | | } |
| | |
| | | Entry newEntry = DirectoryServer.getEntry(DN.decode( |
| | | "uid=user.test0,ou=People,dc=example,dc=com")); |
| | | assertNotNull(newEntry); |
| | | for(AttributeType attribute : newEntry.getDN().getRDN().getAttributeTypes()) |
| | | RDN rdn = newEntry.getDN().getRDN(); |
| | | for (int i = 0; i < rdn.getNumValues(); i++) |
| | | { |
| | | AttributeType attribute = rdn.getAttributeType(i); |
| | | assertTrue(newEntry.hasValue(attribute, null, new AttributeValue(attribute, "user.0"))); |
| | | assertTrue(newEntry.hasValue(attribute, null, new AttributeValue(attribute, "user.test0"))); |
| | | } |
| | |
| | | newEntry = DirectoryServer.getEntry(DN.decode( |
| | | "uid=user.0,ou=People,dc=example,dc=com")); |
| | | assertNotNull(newEntry); |
| | | for(AttributeType attribute : newEntry.getDN().getRDN().getAttributeTypes()) |
| | | rdn = newEntry.getDN().getRDN(); |
| | | for (int i = 0; i < rdn.getNumValues(); i++) |
| | | { |
| | | AttributeType attribute = rdn.getAttributeType(i); |
| | | assertTrue(newEntry.hasValue(attribute, null, new AttributeValue(attribute, "user.0"))); |
| | | assertFalse(newEntry.hasValue(attribute, null, new AttributeValue(attribute, "user.test0"))); |
| | | } |
| | |
| | | Entry newEntry = DirectoryServer.getEntry(DN.decode( |
| | | "uid=user.test0,ou=People,dc=example,dc=com")); |
| | | assertNotNull(newEntry); |
| | | for(AttributeType attribute : newEntry.getDN().getRDN().getAttributeTypes()) |
| | | RDN rdn = newEntry.getDN().getRDN(); |
| | | for (int i = 0; i < rdn.getNumValues(); i++) |
| | | { |
| | | AttributeType attribute = rdn.getAttributeType(i); |
| | | assertTrue(newEntry.hasValue(attribute, null, new AttributeValue(attribute, "user.0"))); |
| | | assertTrue(newEntry.hasValue(attribute, null, new AttributeValue(attribute, "user.test0"))); |
| | | } |
| | |
| | | newEntry = DirectoryServer.getEntry(DN.decode( |
| | | "uid=user.0,ou=People,dc=example,dc=com")); |
| | | assertNotNull(newEntry); |
| | | for(AttributeType attribute : newEntry.getDN().getRDN().getAttributeTypes()) |
| | | rdn = newEntry.getDN().getRDN(); |
| | | for (int i = 0; i < rdn.getNumValues(); i++) |
| | | { |
| | | AttributeType attribute = rdn.getAttributeType(i); |
| | | assertTrue(newEntry.hasValue(attribute, null, new AttributeValue(attribute, "user.0"))); |
| | | assertFalse(newEntry.hasValue(attribute, null, new AttributeValue(attribute, "user.test0"))); |
| | | } |
| | |
| | | SubtreeSpecificationTestCase { |
| | | |
| | | // Cached root DN. |
| | | private DN rootDN = new DN(); |
| | | private DN rootDN = DN.nullDN(); |
| | | |
| | | /** |
| | | * Tests the {@link RFC3672SubtreeSpecification#valueOf(DN, String)} |
| | |
| | | SubtreeSpecificationTestCase { |
| | | |
| | | // Cached root DN. |
| | | private DN rootDN = new DN(); |
| | | private DN rootDN = DN.nullDN(); |
| | | |
| | | /** |
| | | * Tests the {@link RelativeSubtreeSpecification#valueOf(DN, String)} |
| | |
| | | InternalClientConnection.getRootConnection(); |
| | | BindOperation bindOperation = |
| | | new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(), |
| | | new ArrayList<Control>(), new DN(), |
| | | new ArrayList<Control>(), DN.nullDN(), |
| | | SASL_MECHANISM_ANONYMOUS, null); |
| | | handler.processSASLBind(bindOperation); |
| | | assertEquals(bindOperation.getResultCode(), ResultCode.SUCCESS); |
| | |
| | | InternalClientConnection.getRootConnection(); |
| | | BindOperation bindOperation = |
| | | new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(), |
| | | new ArrayList<Control>(), new DN(), |
| | | new ArrayList<Control>(), DN.nullDN(), |
| | | SASL_MECHANISM_ANONYMOUS, new ASN1OctetString()); |
| | | handler.processSASLBind(bindOperation); |
| | | assertEquals(bindOperation.getResultCode(), ResultCode.SUCCESS); |
| | |
| | | InternalClientConnection.getRootConnection(); |
| | | BindOperation bindOperation = |
| | | new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(), |
| | | new ArrayList<Control>(), new DN(), |
| | | new ArrayList<Control>(), DN.nullDN(), |
| | | SASL_MECHANISM_ANONYMOUS, |
| | | new ASN1OctetString("Internal Trace String")); |
| | | handler.processSASLBind(bindOperation); |
| | |
| | | InternalClientConnection conn = |
| | | new InternalClientConnection(new AuthenticationInfo()); |
| | | BindOperation bindOperation = |
| | | conn.processSASLBind(new DN(), SASL_MECHANISM_CRAM_MD5, |
| | | conn.processSASLBind(DN.nullDN(), SASL_MECHANISM_CRAM_MD5, |
| | | new ASN1OctetString("invalid")); |
| | | assertFalse(bindOperation.getResultCode() == ResultCode.SUCCESS); |
| | | } |
| | |
| | | InternalClientConnection conn = |
| | | new InternalClientConnection(new AuthenticationInfo()); |
| | | BindOperation bindOperation = |
| | | conn.processSASLBind(new DN(), SASL_MECHANISM_CRAM_MD5, null); |
| | | conn.processSASLBind(DN.nullDN(), SASL_MECHANISM_CRAM_MD5, null); |
| | | assertEquals(bindOperation.getResultCode(), |
| | | ResultCode.SASL_BIND_IN_PROGRESS); |
| | | |
| | | bindOperation = |
| | | conn.processSASLBind(new DN(), SASL_MECHANISM_CRAM_MD5, |
| | | conn.processSASLBind(DN.nullDN(), SASL_MECHANISM_CRAM_MD5, |
| | | new ASN1OctetString("malformed")); |
| | | assertFalse(bindOperation.getResultCode() == ResultCode.SUCCESS); |
| | | } |
| | |
| | | InternalClientConnection conn = |
| | | new InternalClientConnection(new AuthenticationInfo()); |
| | | BindOperation bindOperation = |
| | | conn.processSASLBind(new DN(), SASL_MECHANISM_CRAM_MD5, null); |
| | | conn.processSASLBind(DN.nullDN(), SASL_MECHANISM_CRAM_MD5, null); |
| | | assertEquals(bindOperation.getResultCode(), |
| | | ResultCode.SASL_BIND_IN_PROGRESS); |
| | | |
| | | ASN1OctetString creds = |
| | | new ASN1OctetString("dn:cn=Directory Manager malformeddigest"); |
| | | bindOperation = |
| | | conn.processSASLBind(new DN(), SASL_MECHANISM_CRAM_MD5, creds); |
| | | conn.processSASLBind(DN.nullDN(), SASL_MECHANISM_CRAM_MD5, creds); |
| | | assertFalse(bindOperation.getResultCode() == ResultCode.SUCCESS); |
| | | } |
| | | |
| | |
| | | InternalClientConnection conn = |
| | | new InternalClientConnection(new AuthenticationInfo()); |
| | | BindOperation bindOperation = |
| | | conn.processSASLBind(new DN(), SASL_MECHANISM_CRAM_MD5, null); |
| | | conn.processSASLBind(DN.nullDN(), SASL_MECHANISM_CRAM_MD5, null); |
| | | assertEquals(bindOperation.getResultCode(), |
| | | ResultCode.SASL_BIND_IN_PROGRESS); |
| | | |
| | |
| | | new ASN1OctetString("dn:cn=Directory Manager " + |
| | | "malformedcredswiththerightlength"); |
| | | bindOperation = |
| | | conn.processSASLBind(new DN(), SASL_MECHANISM_CRAM_MD5, creds); |
| | | conn.processSASLBind(DN.nullDN(), SASL_MECHANISM_CRAM_MD5, creds); |
| | | assertFalse(bindOperation.getResultCode() == ResultCode.SUCCESS); |
| | | } |
| | | } |
| | |
| | | InternalClientConnection conn = |
| | | new InternalClientConnection(new AuthenticationInfo()); |
| | | BindOperation bindOperation = |
| | | conn.processSASLBind(new DN(), SASL_MECHANISM_DIGEST_MD5, |
| | | conn.processSASLBind(DN.nullDN(), SASL_MECHANISM_DIGEST_MD5, |
| | | new ASN1OctetString("invalid")); |
| | | assertFalse(bindOperation.getResultCode() == ResultCode.SUCCESS); |
| | | } |
| | |
| | | InternalClientConnection conn = |
| | | new InternalClientConnection(new AuthenticationInfo()); |
| | | BindOperation bindOperation = |
| | | conn.processSASLBind(new DN(), SASL_MECHANISM_DIGEST_MD5, null); |
| | | conn.processSASLBind(DN.nullDN(), SASL_MECHANISM_DIGEST_MD5, null); |
| | | assertEquals(bindOperation.getResultCode(), |
| | | ResultCode.SASL_BIND_IN_PROGRESS); |
| | | |
| | | bindOperation = |
| | | conn.processSASLBind(new DN(), SASL_MECHANISM_DIGEST_MD5, |
| | | conn.processSASLBind(DN.nullDN(), SASL_MECHANISM_DIGEST_MD5, |
| | | new ASN1OctetString("malformed")); |
| | | assertFalse(bindOperation.getResultCode() == ResultCode.SUCCESS); |
| | | } |
| | |
| | | throws Exception |
| | | { |
| | | AttributeType cnType = DirectoryServer.getAttributeType(ATTR_COMMON_NAME); |
| | | RDN[] components = new RDN[2]; |
| | | components[0] = new RDN(cnType, new AttributeValue(cnType, monitorName)); |
| | | components[1] = new RDN(cnType, new AttributeValue(cnType, "monitor")); |
| | | DN monitorDN = new DN(components); |
| | | |
| | | RDN rdn0 = RDN.create(cnType, new AttributeValue(cnType, monitorName)); |
| | | RDN rdn1 = RDN.create(cnType, new AttributeValue(cnType, "monitor")); |
| | | DN monitorDN = DN.create(rdn0, rdn1); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | BindOperation bindOperation = |
| | | conn.processSASLBind(new DN(), "PLAIN", creds); |
| | | conn.processSASLBind(DN.nullDN(), "PLAIN", creds); |
| | | assertEquals(bindOperation.getResultCode(), ResultCode.SUCCESS); |
| | | } |
| | | |
| | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | InternalSearchOperation searchOperation = |
| | | conn.processSearch(new DN(), SearchScope.BASE_OBJECT, |
| | | conn.processSearch(DN.nullDN(), SearchScope.BASE_OBJECT, |
| | | SearchFilter.createFilterFromString("(objectClass=*)")); |
| | | assertEquals(searchOperation.getResultCode(), ResultCode.SUCCESS); |
| | | assertFalse(searchOperation.getSearchEntries().isEmpty()); |
| | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | InternalSearchOperation searchOperation = |
| | | conn.processSearch(new DN(), SearchScope.BASE_OBJECT, |
| | | conn.processSearch(DN.nullDN(), SearchScope.BASE_OBJECT, |
| | | DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false, |
| | | SearchFilter.createFilterFromString("(objectClass=*)"), |
| | | new LinkedHashSet<String>()); |
| | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | InternalSearchOperation searchOperation = |
| | | conn.processSearch(new DN(), SearchScope.BASE_OBJECT, |
| | | conn.processSearch(DN.nullDN(), SearchScope.BASE_OBJECT, |
| | | DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false, |
| | | SearchFilter.createFilterFromString("(objectClass=*)"), |
| | | new LinkedHashSet<String>(), searchListener); |
| | |
| | | InternalClientConnection.getRootConnection(); |
| | | new InternalSearchOperation(conn, conn.nextOperationID(), |
| | | conn.nextMessageID(), new ArrayList<Control>(), |
| | | new DN(), SearchScope.BASE_OBJECT, |
| | | DN.nullDN(), SearchScope.BASE_OBJECT, |
| | | DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, |
| | | false, searchFilter, |
| | | new LinkedHashSet<String>(), null); |
| | |
| | | InternalClientConnection.getRootConnection(); |
| | | new InternalSearchOperation(conn, conn.nextOperationID(), |
| | | conn.nextMessageID(), new ArrayList<Control>(), |
| | | new DN(), SearchScope.BASE_OBJECT, |
| | | DN.nullDN(), SearchScope.BASE_OBJECT, |
| | | DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, |
| | | false, searchFilter, |
| | | new LinkedHashSet<String>(), |
| | |
| | | |
| | | AttributeValue attributeValue = new AttributeValue(attribute, "testValue"); |
| | | |
| | | RDN rdn = new RDN(attribute, attributeValue); |
| | | RDN rdn = RDN.create(attribute, attributeValue); |
| | | |
| | | RDN[] rdns = {rdn}; |
| | | |
| | | dn = new DN(rdns); |
| | | dn = DN.create(rdn); |
| | | } |
| | | |
| | | /** |
| | |
| | | |
| | | |
| | | //Test case for a full encode decode operation with an empty DN params. |
| | | addEncoded = new AddResponseProtocolOp(resultCode, resultMsg, new DN(), |
| | | addEncoded = new AddResponseProtocolOp(resultCode, resultMsg, DN.nullDN(), |
| | | referralURLs); |
| | | element = addEncoded.encode(); |
| | | addDecoded = (AddResponseProtocolOp)AddResponseProtocolOp.decode(element); |
| | |
| | | |
| | | AttributeValue attributeValue = new AttributeValue(attribute, "testValue"); |
| | | |
| | | RDN rdn = new RDN(attribute, attributeValue); |
| | | |
| | | RDN[] rdns = {rdn}; |
| | | |
| | | dn = new DN(rdns); |
| | | RDN rdn = RDN.create(attribute, attributeValue); |
| | | dn = DN.create(rdn); |
| | | } |
| | | |
| | | /** |
| | |
| | | |
| | | |
| | | //Test case for a full encode decode operation with an empty DN params. |
| | | deleteEncoded = new CompareResponseProtocolOp(resultCode, resultMsg, new DN(), |
| | | deleteEncoded = new CompareResponseProtocolOp(resultCode, resultMsg, DN.nullDN(), |
| | | referralURLs); |
| | | element = deleteEncoded.encode(); |
| | | deleteDecoded = (CompareResponseProtocolOp)CompareResponseProtocolOp.decode( |
| | |
| | | |
| | | AttributeValue attributeValue = new AttributeValue(attribute, "testValue"); |
| | | |
| | | RDN rdn = new RDN(attribute, attributeValue); |
| | | |
| | | RDN[] rdns = {rdn}; |
| | | |
| | | dn = new DN(rdns); |
| | | RDN rdn = RDN.create(attribute, attributeValue); |
| | | dn = DN.create(rdn); |
| | | } |
| | | |
| | | /** |
| | |
| | | |
| | | |
| | | //Test case for a full encode decode operation with an empty DN params. |
| | | deleteEncoded = new DeleteResponseProtocolOp(resultCode, resultMsg, new DN(), |
| | | deleteEncoded = new DeleteResponseProtocolOp(resultCode, resultMsg, DN.nullDN(), |
| | | referralURLs); |
| | | element = deleteEncoded.encode(); |
| | | deleteDecoded = (DeleteResponseProtocolOp)DeleteResponseProtocolOp.decode( |
| | |
| | | |
| | | AttributeValue attributeValue = new AttributeValue(attribute, "testValue"); |
| | | |
| | | RDN rdn = new RDN(attribute, attributeValue); |
| | | |
| | | RDN[] rdns = {rdn}; |
| | | |
| | | dn = new DN(rdns); |
| | | RDN rdn = RDN.create(attribute, attributeValue); |
| | | dn = DN.create(rdn); |
| | | } |
| | | |
| | | /** |
| | |
| | | |
| | | |
| | | //Test case for a full encode decode operation with an empty DN params. |
| | | deleteEncoded = new ModifyDNResponseProtocolOp(resultCode, resultMsg, new DN(), |
| | | deleteEncoded = new ModifyDNResponseProtocolOp(resultCode, resultMsg, DN.nullDN(), |
| | | referralURLs); |
| | | element = deleteEncoded.encode(); |
| | | deleteDecoded = (ModifyDNResponseProtocolOp)ModifyDNResponseProtocolOp.decode( |
| | |
| | | |
| | | AttributeValue attributeValue = new AttributeValue(attribute, "testValue"); |
| | | |
| | | RDN rdn = new RDN(attribute, attributeValue); |
| | | |
| | | RDN[] rdns = {rdn}; |
| | | |
| | | dn = new DN(rdns); |
| | | RDN rdn = RDN.create(attribute, attributeValue); |
| | | dn = DN.create(rdn); |
| | | } |
| | | |
| | | /** |
| | |
| | | |
| | | |
| | | //Test case for a full encode decode operation with an empty DN params. |
| | | modifyEncoded = new ModifyResponseProtocolOp(resultCode, resultMsg, new DN(), |
| | | modifyEncoded = new ModifyResponseProtocolOp(resultCode, resultMsg, DN.nullDN(), |
| | | referralURLs); |
| | | element = modifyEncoded.encode(); |
| | | modifyDecoded = (ModifyResponseProtocolOp)ModifyResponseProtocolOp.decode( |
| | |
| | | */ |
| | | package org.opends.server.types; |
| | | |
| | | |
| | | |
| | | import static org.testng.Assert.*; |
| | | |
| | | import org.opends.server.TestCaseUtils; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.protocols.asn1.ASN1OctetString; |
| | | import org.testng.annotations.DataProvider; |
| | | import org.testng.annotations.Test; |
| | | import org.testng.annotations.BeforeClass; |
| | | import org.testng.annotations.AfterClass; |
| | | |
| | | import java.util.Arrays; |
| | | |
| | | |
| | | /** |
| | | * This class defines a set of tests for the org.opends.server.core.DN |
| | |
| | | @DataProvider(name = "testDNs") |
| | | public Object[][] createData() { |
| | | return new Object[][] { |
| | | { "", "" }, |
| | | { " ", "" }, |
| | | { "dc=com", "dc=com" }, |
| | | { "DC=COM", "dc=com" }, |
| | | { "dc = com", "dc=com" }, |
| | | { " dc = com ", "dc=com" }, |
| | | { "dc=example,dc=com", "dc=example,dc=com" }, |
| | | { "dc=example, dc=com", "dc=example,dc=com" }, |
| | | { "dc=example ,dc=com", "dc=example,dc=com" }, |
| | | { "dc =example , dc = com", "dc=example,dc=com" }, |
| | | { "", "", "" }, |
| | | { " ", "", "" }, |
| | | { "dc=com", "dc=com", "dc=com" }, |
| | | { "DC=COM", "dc=com", "DC=COM" }, |
| | | { "dc = com", "dc=com", "dc=com" }, |
| | | { " dc = com ", "dc=com", "dc=com" }, |
| | | { "dc=example,dc=com", "dc=example,dc=com", |
| | | "dc=example,dc=com" }, |
| | | { "dc=example, dc=com", "dc=example,dc=com", |
| | | "dc=example,dc=com" }, |
| | | { "dc=example ,dc=com", "dc=example,dc=com", |
| | | "dc=example,dc=com" }, |
| | | { "dc =example , dc = com", "dc=example,dc=com", |
| | | "dc=example,dc=com" }, |
| | | { "givenName=John+cn=Doe,ou=People,dc=example,dc=com", |
| | | "cn=doe+givenname=john,ou=people,dc=example,dc=com" }, |
| | | "cn=doe+givenname=john,ou=people,dc=example,dc=com", |
| | | "givenName=John+cn=Doe,ou=People,dc=example,dc=com" }, |
| | | { "givenName=John\\+cn=Doe,ou=People,dc=example,dc=com", |
| | | "givenname=john\\+cn=doe,ou=people,dc=example,dc=com" }, |
| | | "givenname=john\\+cn=doe,ou=people,dc=example,dc=com", |
| | | "givenName=John\\+cn=Doe,ou=People,dc=example,dc=com" }, |
| | | { "cn=Doe\\, John,ou=People,dc=example,dc=com", |
| | | "cn=doe\\, john,ou=people,dc=example,dc=com" }, |
| | | { "UID=jsmith,DC=example,DC=net", "uid=jsmith,dc=example,dc=net" }, |
| | | "cn=doe\\, john,ou=people,dc=example,dc=com", |
| | | "cn=Doe\\, John,ou=People,dc=example,dc=com" }, |
| | | { "UID=jsmith,DC=example,DC=net", |
| | | "uid=jsmith,dc=example,dc=net", |
| | | "UID=jsmith,DC=example,DC=net" }, |
| | | { "OU=Sales+CN=J. Smith,DC=example,DC=net", |
| | | "cn=j. smith+ou=sales,dc=example,dc=net" }, |
| | | "cn=j. smith+ou=sales,dc=example,dc=net", |
| | | "OU=Sales+CN=J. Smith,DC=example,DC=net" }, |
| | | { "CN=James \\\"Jim\\\" Smith\\, III,DC=example,DC=net", |
| | | "cn=james \\\"jim\\\" smith\\, iii,dc=example,dc=net" }, |
| | | "cn=james \\\"jim\\\" smith\\, iii,dc=example,dc=net", |
| | | "CN=James \\\"Jim\\\" Smith\\, III,DC=example,DC=net" }, |
| | | { "CN=John Smith\\2C III,DC=example,DC=net", |
| | | "cn=john smith\\, iii,dc=example,dc=net", |
| | | "CN=John Smith\\, III,DC=example,DC=net" }, |
| | | { "CN=\\23John Smith\\20,DC=example,DC=net", |
| | | "cn=\\#john smith,dc=example,dc=net", |
| | | "CN=\\#John Smith\\ ,DC=example,DC=net" }, |
| | | { "CN=Before\\0dAfter,DC=example,DC=net", |
| | | "cn=before\\0dafter,dc=example,dc=net" }, |
| | | { "1.3.6.1.4.1.1466.0=#04024869", "1.3.6.1.4.1.1466.0=\\04\\02hi" }, |
| | | { "CN=Lu\\C4\\8Di\\C4\\87", "cn=lu\\c4\\8di\\c4\\87" }, |
| | | "cn=before\\0dafter,dc=example,dc=net", |
| | | "CN=Before\\0dAfter,DC=example,DC=net" }, |
| | | { "1.3.6.1.4.1.1466.0=#04024869", |
| | | "1.3.6.1.4.1.1466.0=\\04\\02hi", |
| | | "1.3.6.1.4.1.1466.0=\\04\\02Hi" }, |
| | | { "1.1.1=", "1.1.1=", "1.1.1=" }, |
| | | { "CN=Lu\\C4\\8Di\\C4\\87", "cn=lu\\c4\\8di\\c4\\87", |
| | | "CN=Lu\\c4\\8di\\c4\\87" }, |
| | | { "ou=\\e5\\96\\b6\\e6\\a5\\ad\\e9\\83\\a8,o=Airius", |
| | | "ou=\\e5\\96\\b6\\e6\\a5\\ad\\e9\\83\\a8,o=airius" }, |
| | | { "photo=\\ john \\ ,dc=com", "photo=\\ john \\ ,dc=com" }, |
| | | { "AB-global=", "ab-global=" }, |
| | | "ou=\\e5\\96\\b6\\e6\\a5\\ad\\e9\\83\\a8,o=airius", |
| | | "ou=\\e5\\96\\b6\\e6\\a5\\ad\\e9\\83\\a8,o=Airius" }, |
| | | { "photo=\\ john \\ ,dc=com", "photo=\\ john \\ ,dc=com", |
| | | "photo=\\ john \\ ,dc=com" }, |
| | | { "AB-global=", "ab-global=", "AB-global=" }, |
| | | { "OU= Sales + CN = J. Smith ,DC=example,DC=net", |
| | | "cn=j. smith+ou=sales,dc=example,dc=net" }, |
| | | { "cn=John+a=", "a=+cn=john" }, |
| | | "cn=j. smith+ou=sales,dc=example,dc=net", |
| | | "OU=Sales+CN=J. Smith,DC=example,DC=net" }, |
| | | { "cn=John+a=", "a=+cn=john", "cn=John+a=" }, |
| | | { "OID.1.3.6.1.4.1.1466.0=#04024869", |
| | | "1.3.6.1.4.1.1466.0=\\04\\02hi" }, |
| | | "1.3.6.1.4.1.1466.0=\\04\\02hi", |
| | | "1.3.6.1.4.1.1466.0=\\04\\02Hi" }, |
| | | { "O=\"Sue, Grabbit and Runn\",C=US", |
| | | "o=sue\\, grabbit and runn,c=us" }, |
| | | }; |
| | | "o=sue\\, grabbit and runn,c=us", |
| | | "O=Sue\\, Grabbit and Runn,C=US" }, }; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Illegal DN test data provider. |
| | | * |
| | |
| | | */ |
| | | @DataProvider(name = "illegalDNs") |
| | | public Object[][] createIllegalData() { |
| | | return new Object[][] { |
| | | { "manager" }, |
| | | { "manager " }, |
| | | { "cn+Jim" }, |
| | | { "cn=Jim+" }, |
| | | { "cn=Jim," }, |
| | | { "cn=Jim, " }, |
| | | { "cn+uid=Jim" }, |
| | | { "-cn=Jim" }, |
| | | { "/tmp=a" }, |
| | | { "\\tmp=a" }, |
| | | { "cn;lang-en=Jim" }, |
| | | { "@cn=Jim" }, |
| | | { "_name_=Jim" }, |
| | | { "\u03c0=pi" }, |
| | | { "v1.0=buggy" }, |
| | | { "1.3.6.1.4.1.1466..0=#04024869" }, |
| | | }; |
| | | return new Object[][] { { "manager" }, { "manager " }, |
| | | { "cn+Jim" }, { "cn=Jim+" }, { "cn=Jim," }, { "cn=Jim, " }, |
| | | { "cn+uid=Jim" }, { "-cn=Jim" }, { "/tmp=a" }, { "\\tmp=a" }, |
| | | { "cn;lang-en=Jim" }, { "@cn=Jim" }, { "_name_=Jim" }, |
| | | { "\u03c0=pi" }, { "v1.0=buggy" }, |
| | | { "1.3.6.1.4.1.1466..0=#04024869" }, }; |
| | | } |
| | | |
| | | /** |
| | | * DN compare test data provider. |
| | | * |
| | | * @return The unsorted and sorted DN strings . |
| | | */ |
| | | @DataProvider(name = "compareDNs") |
| | | public Object[][] createSortData() { |
| | | return new Object[][] { |
| | | { |
| | | // Not sorted. |
| | | new String[] |
| | | { |
| | | "UID=jsmith,DC=example,DC=net", |
| | | "dc=com", |
| | | "", |
| | | "dc=example,dc=net", |
| | | "uid=jsmith,dc=example,dc=com", |
| | | "dc=example,dc=com", |
| | | "cn=jsmith,dc=example,dc=com", |
| | | "", |
| | | "dc =example , dc = com", |
| | | "uid=asmith,dc=example,dc=net", |
| | | }, |
| | | // Sorted. |
| | | new String[] |
| | | { |
| | | "", |
| | | "", |
| | | "dc=com", |
| | | "dc =example , dc = com", |
| | | "dc=example,dc=com", |
| | | "cn=jsmith,dc=example,dc=com", |
| | | "uid=jsmith,dc=example,dc=com", |
| | | "dc=example,dc=net", |
| | | "uid=asmith,dc=example,dc=net", |
| | | "UID=jsmith,DC=example,DC=net", |
| | | }, |
| | | } |
| | | }; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Set up the environment for performing the tests in this suite. |
| | |
| | | */ |
| | | @BeforeClass |
| | | public void setUp() throws Exception { |
| | | // This test suite depends on having the schema available, so we'll start |
| | | // the server. |
| | | // This test suite depends on having the schema available, so |
| | | // we'll start the server. |
| | | TestCaseUtils.startServer(); |
| | | |
| | | AttributeType dummy = DirectoryServer.getDefaultAttributeType( |
| | | "x-test-integer-type", DirectoryServer |
| | | .getDefaultIntegerSyntax()); |
| | | DirectoryServer.getSchema().registerAttributeType(dummy, true); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the create method. |
| | | * |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(expectedExceptions = { NullPointerException.class, |
| | | AssertionError.class }) |
| | | public void testCreateNPE() throws Exception { |
| | | DN.create((RDN[]) null); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the create method. |
| | | * |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test |
| | | public void testCreateNullDN1() throws Exception { |
| | | DN dn = DN.create(new RDN[0]); |
| | | |
| | | assertEquals(dn, DN.nullDN()); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the create method. |
| | | * |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test |
| | | public void testCreateNullDN2() throws Exception { |
| | | DN dn = DN.create(); |
| | | |
| | | assertEquals(dn, DN.nullDN()); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the create method. |
| | | * |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test |
| | | public void testCreateWithSingleRDN1() throws Exception { |
| | | DN dn = DN.create(new RDN[] { RDN.decode("dc=com") }); |
| | | |
| | | assertEquals(dn, DN.decode("dc=com")); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the create method. |
| | | * |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test |
| | | public void testCreateWithSingleRDN2() throws Exception { |
| | | DN dn = DN.create(RDN.decode("dc=com")); |
| | | |
| | | assertEquals(dn, DN.decode("dc=com")); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the create method. |
| | | * |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test |
| | | public void testCreateWithMultipleRDNs1() throws Exception { |
| | | DN dn = DN.create(new RDN[] { RDN.decode("dc=foo"), |
| | | RDN.decode("dc=opends"), RDN.decode("dc=org") }); |
| | | |
| | | assertEquals(dn, DN.decode("dc=foo,dc=opends,dc=org")); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the create method. |
| | | * |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test |
| | | public void testCreateWithMultipleRDNs2() throws Exception { |
| | | DN dn = DN.create(RDN.decode("dc=foo"), RDN.decode("dc=opends"), |
| | | RDN.decode("dc=org")); |
| | | |
| | | assertEquals(dn, DN.decode("dc=foo,dc=opends,dc=org")); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the <CODE>decode</CODE> method which takes a String |
| | | * argument. |
| | | * |
| | | * @param rawDN |
| | | * The raw undecoded DN string. |
| | | * Raw DN string representation. |
| | | * @param normDN |
| | | * The expected normalized value. |
| | | * Normalized DN string representation. |
| | | * @param stringDN |
| | | * String representation. |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(dataProvider = "testDNs") |
| | | public void testDecodeString(String rawDN, String normDN) |
| | | throws Exception { |
| | | public void testDecodeString(String rawDN, String normDN, |
| | | String stringDN) throws Exception { |
| | | DN dn = DN.decode(rawDN); |
| | | assertEquals(normDN, dn.toNormalizedString()); |
| | | assertEquals(dn.toNormalizedString(), normDN); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the <CODE>decode</CODE> method which takes a String |
| | | * argument. |
| | | * |
| | | * @param rawDN |
| | | * The raw undecoded DN string. |
| | | * Raw DN string representation. |
| | | * @param normDN |
| | | * The expected normalized value. |
| | | * Normalized DN string representation. |
| | | * @param stringDN |
| | | * String representation. |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(dataProvider = "testDNs") |
| | | public void testDecodeOctetString(String rawDN, String normDN) |
| | | throws Exception { |
| | | public void testDecodeOctetString(String rawDN, String normDN, |
| | | String stringDN) throws Exception { |
| | | ASN1OctetString octetString = new ASN1OctetString(rawDN); |
| | | |
| | | DN dn = DN.decode(octetString); |
| | | assertEquals(normDN, dn.toNormalizedString()); |
| | | assertEquals(dn.toNormalizedString(), normDN); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the <CODE>valueOf</CODE> method which takes a String |
| | | * argument. |
| | | * |
| | | * @param rawDN |
| | | * Raw DN string representation. |
| | | * @param normDN |
| | | * Normalized DN string representation. |
| | | * @param stringDN |
| | | * String representation. |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(dataProvider = "testDNs") |
| | | public void testValueOf(String rawDN, String normDN, String stringDN) |
| | | throws Exception { |
| | | DN dn = DN.valueOf(rawDN); |
| | | assertEquals(dn.toNormalizedString(), normDN); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test that decoding an illegal DN as a String throws an exception. |
| | | * @param dn The illegal DN to be tested. |
| | | * |
| | | * @param dn |
| | | * The illegal DN to be tested. |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(dataProvider = "illegalDNs", |
| | | expectedExceptions = DirectoryException.class ) |
| | | public void testIllegalStringDNs(String dn) |
| | | throws Exception |
| | | { |
| | | try |
| | | { |
| | | @Test(dataProvider = "illegalDNs", expectedExceptions = DirectoryException.class) |
| | | public void testIllegalStringDNs(String dn) throws Exception { |
| | | try { |
| | | DN.decode(dn); |
| | | } |
| | | catch (DirectoryException e) |
| | | { |
| | | } catch (DirectoryException e) { |
| | | throw e; |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | System.out.println( |
| | | "Illegal DN <" + dn + "> threw the wrong type of exception"); |
| | | } catch (Exception e) { |
| | | System.out.println("Illegal DN <" + dn |
| | | + "> threw the wrong type of exception"); |
| | | throw e; |
| | | } |
| | | |
| | | throw new RuntimeException( |
| | | "Illegal DN <" + dn + "> did not throw an exception"); |
| | | throw new RuntimeException("Illegal DN <" + dn |
| | | + "> did not throw an exception"); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test that decoding an illegal DN as an octet string throws an exception. |
| | | * @param dn The illegal DN to be tested. |
| | | * Test that decoding an illegal DN as an octet string throws an |
| | | * exception. |
| | | * |
| | | * @param dn |
| | | * The illegal DN to be tested. |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(dataProvider = "illegalDNs", |
| | | expectedExceptions = DirectoryException.class ) |
| | | public void testIllegalOctetStringDNs(String dn) |
| | | throws Exception |
| | | { |
| | | @Test(dataProvider = "illegalDNs", expectedExceptions = DirectoryException.class) |
| | | public void testIllegalOctetStringDNs(String dn) throws Exception { |
| | | ASN1OctetString octetString = new ASN1OctetString(dn); |
| | | |
| | | try |
| | | { |
| | | try { |
| | | DN.decode(octetString); |
| | | } |
| | | catch (DirectoryException e) |
| | | { |
| | | } catch (DirectoryException e) { |
| | | throw e; |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | System.out.println( |
| | | "Illegal DN <" + dn + "> threw the wrong type of exception"); |
| | | } catch (Exception e) { |
| | | System.out.println("Illegal DN <" + dn |
| | | + "> threw the wrong type of exception"); |
| | | throw e; |
| | | } |
| | | |
| | | throw new RuntimeException( |
| | | "Illegal DN <" + dn + "> did not throw an exception"); |
| | | throw new RuntimeException("Illegal DN <" + dn |
| | | + "> did not throw an exception"); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test the <CODE>compareTo</CODE> method. |
| | | * @param unsorted An array of string DNs in no particular order. |
| | | * @param sorted An array of the same DNs in sort order. |
| | | * Test that decoding an illegal DN as a String throws an exception. |
| | | * |
| | | * @param dn |
| | | * The illegal DN to be tested. |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(dataProvider = "compareDNs") |
| | | public void testCompareTo(String[] unsorted, String[] sorted) |
| | | throws Exception |
| | | { |
| | | DN[] expected = new DN[sorted.length]; |
| | | for (int i = 0; i < sorted.length; i++) |
| | | { |
| | | expected[i] = DN.decode(sorted[i]); |
| | | @Test(dataProvider = "illegalDNs", expectedExceptions = DirectoryException.class) |
| | | public void testIllegalValueOf(String dn) throws Exception { |
| | | try { |
| | | DN.valueOf(dn); |
| | | } catch (DirectoryException e) { |
| | | throw e; |
| | | } catch (Exception e) { |
| | | System.out.println("Illegal DN <" + dn |
| | | + "> threw the wrong type of exception"); |
| | | throw e; |
| | | } |
| | | |
| | | throw new RuntimeException("Illegal DN <" + dn |
| | | + "> did not throw an exception"); |
| | | } |
| | | |
| | | |
| | | DN[] actual = new DN[unsorted.length]; |
| | | for (int i = 0; i < unsorted.length; i++) |
| | | { |
| | | actual[i] = DN.decode(unsorted[i]); |
| | | |
| | | /** |
| | | * Test the nullDN method. |
| | | * |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test |
| | | public void testNullDN() throws Exception { |
| | | DN nullDN = DN.nullDN(); |
| | | |
| | | assertTrue(nullDN.getNumComponents() == 0); |
| | | assertEquals(nullDN.toNormalizedString(), ""); |
| | | } |
| | | |
| | | Arrays.sort(actual); |
| | | |
| | | |
| | | /** |
| | | * Test the isNullDN method. |
| | | * |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test |
| | | public void testIsNullDNWithNullDN() throws Exception { |
| | | DN nullDN = DN.nullDN(); |
| | | assertTrue(nullDN.isNullDN()); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test the isNullDN method. |
| | | * |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test |
| | | public void testIsNullDNWithNonNullDN() throws Exception { |
| | | DN dn = DN.decode("dc=com"); |
| | | assertFalse(dn.isNullDN()); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * DN test data provider. |
| | | * |
| | | * @return The array of test DN strings. |
| | | */ |
| | | @DataProvider(name = "createNumComponentsTestData") |
| | | public Object[][] createNumComponentsTestData() { |
| | | return new Object[][] { { "", 0 }, { "dc=com", 1 }, |
| | | { "dc=opends,dc=com", 2 }, |
| | | { "dc=world,dc=opends,dc=com", 3 }, |
| | | { "dc=hello,dc=world,dc=opends,dc=com", 4 }, }; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test the getNumComponents method. |
| | | * |
| | | * @param s |
| | | * The test DN string. |
| | | * @param sz |
| | | * The expected number of RDNs. |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(dataProvider = "createNumComponentsTestData") |
| | | public void testNumComponents(String s, int sz) throws Exception { |
| | | DN dn = DN.decode(s); |
| | | assertEquals(dn.getNumComponents(), sz); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * DN test data provider. |
| | | * |
| | | * @return The array of test DN strings. |
| | | */ |
| | | @DataProvider(name = "createParentAndRDNTestData") |
| | | public Object[][] createParentAndRDNTestData() { |
| | | return new Object[][] { |
| | | { "", null, null }, |
| | | { "dc=com", null, "dc=com" }, |
| | | { "dc=opends,dc=com", "dc=com", "dc=opends" }, |
| | | { "dc=world,dc=opends,dc=com", "dc=opends,dc=com", "dc=world" }, |
| | | { "dc=hello,dc=world,dc=opends,dc=com", |
| | | "dc=world,dc=opends,dc=com", "dc=hello" }, }; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test the getParent method. |
| | | * |
| | | * @param s |
| | | * The test DN string. |
| | | * @param p |
| | | * The expected parent. |
| | | * @param r |
| | | * The expected rdn. |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(dataProvider = "createParentAndRDNTestData") |
| | | public void testGetParent(String s, String p, String r) |
| | | throws Exception { |
| | | DN dn = DN.decode(s); |
| | | DN parent = (p != null ? DN.decode(p) : null); |
| | | |
| | | assertEquals(dn.getParent(), parent, "For DN " + s); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test the getParent method's interaction with other methods. |
| | | * |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test |
| | | public void testGetParentInteraction() throws Exception { |
| | | DN c = DN.decode("dc=foo,dc=bar,dc=opends,dc=org"); |
| | | DN e = DN.decode("dc=bar,dc=opends,dc=org"); |
| | | DN p = c.getParent(); |
| | | |
| | | assertFalse(p.isNullDN()); |
| | | |
| | | assertEquals(p.getNumComponents(), 3); |
| | | |
| | | assertEquals(p.compareTo(c), -1); |
| | | assertEquals(c.compareTo(p), 1); |
| | | |
| | | assertTrue(p.isAncestorOf(c)); |
| | | assertFalse(c.isAncestorOf(p)); |
| | | |
| | | assertTrue(c.isDescendantOf(p)); |
| | | assertFalse(p.isDescendantOf(c)); |
| | | |
| | | assertEquals(p, e); |
| | | assertEquals(p.hashCode(), e.hashCode()); |
| | | |
| | | assertEquals(p.toNormalizedString(), e.toNormalizedString()); |
| | | assertEquals(p.toString(), e.toString()); |
| | | |
| | | assertEquals(p.getRDN(), RDN.decode("dc=bar")); |
| | | |
| | | assertEquals(p.getRDN(0), RDN.decode("dc=bar")); |
| | | assertEquals(p.getRDN(1), RDN.decode("dc=opends")); |
| | | assertEquals(p.getRDN(2), RDN.decode("dc=org")); |
| | | |
| | | assertEquals(p.getParent(), DN.decode("dc=opends,dc=org")); |
| | | assertEquals(p.getParent(), e.getParent()); |
| | | |
| | | assertEquals(p.concat(RDN.decode("dc=foo")), DN |
| | | .decode("dc=foo,dc=bar,dc=opends,dc=org")); |
| | | assertEquals(p.concat(RDN.decode("dc=foo")), c); |
| | | assertEquals(p.concat(DN.decode("dc=xxx,dc=foo")), DN |
| | | .decode("dc=xxx,dc=foo,dc=bar,dc=opends,dc=org")); |
| | | |
| | | assertEquals(p.getLocalName(1), DN.decode("dc=bar,dc=opends")); |
| | | assertEquals(p.getLocalName(0, 2), DN.decode("dc=opends,dc=org")); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test the getRDN method. |
| | | * |
| | | * @param s |
| | | * The test DN string. |
| | | * @param p |
| | | * The expected parent. |
| | | * @param r |
| | | * The expected rdn. |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(dataProvider = "createParentAndRDNTestData") |
| | | public void testGetRDN(String s, String p, String r) |
| | | throws Exception { |
| | | DN dn = DN.decode(s); |
| | | RDN rdn = (r != null ? RDN.decode(r) : null); |
| | | |
| | | assertEquals(dn.getRDN(), rdn, "For DN " + s); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * DN test data provider. |
| | | * |
| | | * @return The array of test DN strings. |
| | | */ |
| | | @DataProvider(name = "createRDNTestData") |
| | | public Object[][] createRDNTestData() { |
| | | return new Object[][] { { "dc=com", 0, "dc=com" }, |
| | | { "dc=opends,dc=com", 0, "dc=opends" }, |
| | | { "dc=opends,dc=com", 1, "dc=com" }, |
| | | { "dc=hello,dc=world,dc=opends,dc=com", 0, "dc=hello" }, |
| | | { "dc=hello,dc=world,dc=opends,dc=com", 1, "dc=world" }, |
| | | { "dc=hello,dc=world,dc=opends,dc=com", 2, "dc=opends" }, |
| | | { "dc=hello,dc=world,dc=opends,dc=com", 3, "dc=com" }, }; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test the getRDN indexed method. |
| | | * |
| | | * @param s |
| | | * The test DN string. |
| | | * @param i |
| | | * The RDN index. |
| | | * @param r |
| | | * The expected rdn. |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(dataProvider = "createRDNTestData") |
| | | public void testGetRDNIndexed(String s, int i, String r) |
| | | throws Exception { |
| | | DN dn = DN.decode(s); |
| | | RDN rdn = RDN.decode(r); |
| | | |
| | | assertEquals(dn.getRDN(i), rdn, "For DN " + s); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * DN test data provider. |
| | | * |
| | | * @return The array of test DN strings. |
| | | */ |
| | | @DataProvider(name = "createRDNIllegalTestData") |
| | | public Object[][] createRDNIllegalTestData() { |
| | | return new Object[][] { { "", 0 }, { "", -1 }, { "", 1 }, |
| | | { "dc=com", -1 }, { "dc=com", 1 }, |
| | | { "dc=opends,dc=com", -1 }, { "dc=opends,dc=com", 2 }, |
| | | { "dc=hello,dc=world,dc=opends,dc=com", -1 }, |
| | | { "dc=hello,dc=world,dc=opends,dc=com", 4 }, }; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test the getRDN indexed method with illegal indexes. |
| | | * |
| | | * @param s |
| | | * The test DN string. |
| | | * @param i |
| | | * The illegal RDN index. |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(dataProvider = "createRDNIllegalTestData", expectedExceptions = IndexOutOfBoundsException.class) |
| | | public void testGetRDNIndexedException(String s, int i) |
| | | throws Exception { |
| | | DN dn = DN.decode(s); |
| | | |
| | | // Shoudld throw. |
| | | dn.getRDN(i); |
| | | |
| | | fail("Excepted exception for RDN index " + i + " in DN " + s); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Concat DN test data provider. |
| | | * |
| | | * @return The array of test data. |
| | | */ |
| | | @DataProvider(name = "createConcatDNTestData") |
| | | public Object[][] createConcatDNTestData() { |
| | | return new Object[][] { |
| | | { "", "", "" }, |
| | | { "", "dc=org", "dc=org" }, |
| | | { "", "dc=opends,dc=org", "dc=opends,dc=org" }, |
| | | { "dc=org", "", "dc=org" }, |
| | | { "dc=org", "dc=opends", "dc=opends,dc=org" }, |
| | | { "dc=org", "dc=foo,dc=opends", "dc=foo,dc=opends,dc=org" }, |
| | | { "dc=opends,dc=org", "", "dc=opends,dc=org" }, |
| | | { "dc=opends,dc=org", "dc=foo", "dc=foo,dc=opends,dc=org" }, |
| | | { "dc=opends,dc=org", "dc=bar,dc=foo", |
| | | "dc=bar,dc=foo,dc=opends,dc=org" }, }; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test the concat(DN) method. |
| | | * |
| | | * @param s |
| | | * The test DN string. |
| | | * @param l |
| | | * The local name to be appended. |
| | | * @param e |
| | | * The expected DN. |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(dataProvider = "createConcatDNTestData") |
| | | public void testConcatDN(String s, String l, String e) |
| | | throws Exception { |
| | | DN dn = DN.decode(s); |
| | | DN localName = DN.decode(l); |
| | | DN expected = DN.decode(e); |
| | | |
| | | assertEquals(dn.concat(localName), expected); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test the concat(DN) method. |
| | | * |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(expectedExceptions = { NullPointerException.class, |
| | | AssertionError.class }) |
| | | public void testConcatDNException() throws Exception { |
| | | DN dn = DN.decode("dc=org"); |
| | | dn.concat((DN) null); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test the concat(DN) method's interaction with other methods. |
| | | * |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test |
| | | public void testConcatDNInteraction() throws Exception { |
| | | DN p = DN.decode("dc=opends,dc=org"); |
| | | DN l = DN.decode("dc=foo,dc=bar"); |
| | | DN e = DN.decode("dc=foo,dc=bar,dc=opends,dc=org"); |
| | | DN c = p.concat(l); |
| | | |
| | | assertFalse(c.isNullDN()); |
| | | |
| | | assertEquals(c.getNumComponents(), 4); |
| | | |
| | | assertEquals(c.compareTo(p), 1); |
| | | assertEquals(p.compareTo(c), -1); |
| | | |
| | | assertTrue(p.isAncestorOf(c)); |
| | | assertFalse(c.isAncestorOf(p)); |
| | | |
| | | assertTrue(c.isDescendantOf(p)); |
| | | assertFalse(p.isDescendantOf(c)); |
| | | |
| | | assertEquals(c, e); |
| | | assertEquals(c.hashCode(), e.hashCode()); |
| | | |
| | | assertEquals(c.toNormalizedString(), e.toNormalizedString()); |
| | | assertEquals(c.toString(), e.toString()); |
| | | |
| | | assertEquals(c.getRDN(), RDN.decode("dc=foo")); |
| | | |
| | | assertEquals(c.getRDN(0), RDN.decode("dc=foo")); |
| | | assertEquals(c.getRDN(1), RDN.decode("dc=bar")); |
| | | assertEquals(c.getRDN(2), RDN.decode("dc=opends")); |
| | | assertEquals(c.getRDN(3), RDN.decode("dc=org")); |
| | | |
| | | assertEquals(c.getParent(), DN.decode("dc=bar,dc=opends,dc=org")); |
| | | assertEquals(c.getParent(), e.getParent()); |
| | | |
| | | assertEquals(c.concat(RDN.decode("dc=xxx")), DN |
| | | .decode("dc=xxx,dc=foo,dc=bar,dc=opends,dc=org")); |
| | | assertEquals(c.concat(DN.decode("dc=xxx,dc=yyy")), DN |
| | | .decode("dc=xxx,dc=yyy,dc=foo,dc=bar,dc=opends,dc=org")); |
| | | |
| | | assertEquals(c.getLocalName(1), DN |
| | | .decode("dc=foo,dc=bar,dc=opends")); |
| | | assertEquals(c.getLocalName(1, 3), DN.decode("dc=bar,dc=opends")); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Concat RDN test data provider. |
| | | * |
| | | * @return The array of test data. |
| | | */ |
| | | @DataProvider(name = "createConcatRDNTestData") |
| | | public Object[][] createConcatRDNTestData() { |
| | | return new Object[][] { { "", "dc=org", "dc=org" }, |
| | | { "dc=org", "dc=opends", "dc=opends,dc=org" }, |
| | | { "dc=opends,dc=org", "dc=foo", "dc=foo,dc=opends,dc=org" }, }; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test the concat(RDN...) method. |
| | | * |
| | | * @param s |
| | | * The test DN string. |
| | | * @param r |
| | | * The RDN to be appended. |
| | | * @param e |
| | | * The expected DN. |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(dataProvider = "createConcatRDNTestData") |
| | | public void testConcatSingleRDN(String s, String r, String e) |
| | | throws Exception { |
| | | DN dn = DN.decode(s); |
| | | RDN rdn = RDN.decode(r); |
| | | DN expected = DN.decode(e); |
| | | |
| | | assertEquals(dn.concat(rdn), expected); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test the concat(RDN...) method. |
| | | * |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test |
| | | public void testConcatRDNNoOp() throws Exception { |
| | | DN dn = DN.decode("dc=opends,dc=org"); |
| | | |
| | | assertEquals(dn.concat(), dn); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test the concat(RDN...) method. |
| | | * |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(expectedExceptions = { NullPointerException.class, |
| | | AssertionError.class }) |
| | | public void testConcatRDNException() throws Exception { |
| | | DN dn = DN.decode("dc=org"); |
| | | dn.concat((RDN[]) null); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test the concat(RDN[]...) method. |
| | | * |
| | | * @param s |
| | | * The test DN string. |
| | | * @param l |
| | | * The local name to be appended. |
| | | * @param e |
| | | * The expected DN. |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(dataProvider = "createConcatDNTestData") |
| | | public void testConcatRDNSequence1(String s, String l, String e) |
| | | throws Exception { |
| | | DN dn = DN.decode(s); |
| | | DN localName = DN.decode(l); |
| | | DN expected = DN.decode(e); |
| | | |
| | | // Construct sequence. |
| | | RDN[] rdns = new RDN[localName.getNumComponents()]; |
| | | for (int i = 0; i < localName.getNumComponents(); i++) { |
| | | rdns[i] = localName.getRDN(i); |
| | | } |
| | | |
| | | assertEquals(dn.concat(rdns), expected); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test the concat(RDN[]...) method. |
| | | * |
| | | * @param s |
| | | * The test DN string. |
| | | * @param l |
| | | * The local name to be appended. |
| | | * @param e |
| | | * The expected DN. |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(dataProvider = "createConcatDNTestData") |
| | | public void testConcatRDNSequence2(String s, String l, String e) |
| | | throws Exception { |
| | | DN dn = DN.decode(s); |
| | | DN localName = DN.decode(l); |
| | | DN expected = DN.decode(e); |
| | | |
| | | // Construct sequence. |
| | | DN actual = null; |
| | | switch (localName.getNumComponents()) { |
| | | case 0: |
| | | actual = dn.concat(); |
| | | break; |
| | | case 1: |
| | | actual = dn.concat(localName.getRDN(0)); |
| | | break; |
| | | case 2: |
| | | actual = dn.concat(localName.getRDN(0), localName.getRDN(1)); |
| | | break; |
| | | case 3: |
| | | actual = dn.concat(localName.getRDN(0), localName.getRDN(1), |
| | | localName.getRDN(2)); |
| | | break; |
| | | case 4: |
| | | actual = dn.concat(localName.getRDN(0), localName.getRDN(1), |
| | | localName.getRDN(3), localName.getRDN(3)); |
| | | break; |
| | | } |
| | | |
| | | assertEquals(actual, expected); |
| | | } |
| | |
| | | |
| | | |
| | | /** |
| | | * Test the <CODE>duplicate</CODE> method. |
| | | * Get local name test data provider. |
| | | * |
| | | * @return The array of test data. |
| | | */ |
| | | @DataProvider(name = "createGetLocalNameTestData") |
| | | public Object[][] createGetLocalNameTestData() { |
| | | return new Object[][] { |
| | | { "", 0, -1, "" }, |
| | | { "", 0, 0, "" }, |
| | | { "dc=org", 0, -1, "dc=org" }, |
| | | { "dc=org", 1, -1, "" }, |
| | | { "dc=org", 0, 0, "" }, |
| | | { "dc=org", 0, 1, "dc=org" }, |
| | | { "dc=org", 1, 1, "" }, |
| | | { "dc=opends,dc=org", 0, -1, "dc=opends,dc=org" }, |
| | | { "dc=opends,dc=org", 1, -1, "dc=opends" }, |
| | | { "dc=opends,dc=org", 2, -1, "" }, |
| | | { "dc=opends,dc=org", 0, 0, "" }, |
| | | { "dc=opends,dc=org", 0, 1, "dc=org" }, |
| | | { "dc=opends,dc=org", 0, 2, "dc=opends,dc=org" }, |
| | | { "dc=opends,dc=org", 1, 1, "" }, |
| | | { "dc=opends,dc=org", 1, 2, "dc=opends" }, |
| | | { "dc=opends,dc=org", 2, 2, "" }, |
| | | { "dc=foo,dc=opends,dc=org", 0, -1, "dc=foo,dc=opends,dc=org" }, |
| | | { "dc=foo,dc=opends,dc=org", 1, -1, "dc=foo,dc=opends" }, |
| | | { "dc=foo,dc=opends,dc=org", 2, -1, "dc=foo" }, |
| | | { "dc=foo,dc=opends,dc=org", 3, -1, "" }, |
| | | { "dc=foo,dc=opends,dc=org", 0, 0, "" }, |
| | | { "dc=foo,dc=opends,dc=org", 0, 1, "dc=org" }, |
| | | { "dc=foo,dc=opends,dc=org", 0, 2, "dc=opends,dc=org" }, |
| | | { "dc=foo,dc=opends,dc=org", 0, 3, "dc=foo,dc=opends,dc=org" }, |
| | | { "dc=foo,dc=opends,dc=org", 1, 1, "" }, |
| | | { "dc=foo,dc=opends,dc=org", 1, 2, "dc=opends" }, |
| | | { "dc=foo,dc=opends,dc=org", 1, 3, "dc=foo,dc=opends" }, |
| | | { "dc=foo,dc=opends,dc=org", 2, 2, "" }, |
| | | { "dc=foo,dc=opends,dc=org", 2, 3, "dc=foo" }, |
| | | { "dc=foo,dc=opends,dc=org", 3, 3, "" }, }; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test the getLocalName methods. |
| | | * |
| | | * @param s |
| | | * The test DN string. |
| | | * @param beginIndex |
| | | * The index of the uppermost RDN. |
| | | * @param endIndex |
| | | * The index of the lowest RDN or -1 if there is no end |
| | | * index. |
| | | * @param e |
| | | * The expected result. |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(dataProvider = "createGetLocalNameTestData") |
| | | public void testGetLocalName(String s, int beginIndex, |
| | | int endIndex, String e) throws Exception { |
| | | DN dn = DN.decode(s); |
| | | DN expected = DN.decode(e); |
| | | |
| | | if (endIndex < 0) { |
| | | assertEquals(dn.getLocalName(beginIndex), expected); |
| | | } else { |
| | | assertEquals(dn.getLocalName(beginIndex, endIndex), expected); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test the getLocalName method's interaction with other methods. |
| | | * |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test |
| | | public void testDuplicate() throws Exception |
| | | { |
| | | String s = "dc=example,dc=com"; |
| | | DN orig = DN.decode(s); |
| | | DN dup = orig.duplicate(); |
| | | public void testGetLocalNameInteraction() throws Exception { |
| | | DN p = DN.decode("dc=foo,dc=bar,dc=opends,dc=org"); |
| | | DN e = DN.decode("dc=bar,dc=opends"); |
| | | DN l = p.getLocalName(1, 3); |
| | | |
| | | // The duplicate and the original should compare equal. |
| | | assertEquals(dup, orig); |
| | | assertFalse(l.isNullDN()); |
| | | |
| | | // Alter the duplicate. |
| | | RDN[] origRDNs = dup.getRDNComponents(); |
| | | RDN[] dupRDNs = new RDN[origRDNs.length]; |
| | | System.arraycopy(origRDNs, 0, dupRDNs, 0, origRDNs.length); |
| | | assertEquals(l.getNumComponents(), 2); |
| | | |
| | | AttributeValue[] values = new AttributeValue[1]; |
| | | values[0] = origRDNs[0].getAttributeValues()[0]; |
| | | values[0] = new AttributeValue(origRDNs[0].getAttributeTypes()[0], |
| | | new ASN1OctetString("modified")); |
| | | dupRDNs[0] = new RDN(origRDNs[0].getAttributeTypes(), |
| | | origRDNs[0].getAttributeNames(), |
| | | values); |
| | | assertEquals(l.compareTo(e), 0); |
| | | assertEquals(e.compareTo(l), 0); |
| | | |
| | | dup.setRDNComponents(dupRDNs); |
| | | assertTrue(l.isAncestorOf(DN.decode("dc=foo,dc=bar,dc=opends"))); |
| | | assertFalse(DN.decode("dc=foo,dc=bar,dc=opends").isAncestorOf(l)); |
| | | |
| | | // Check that the duplicate and the original are different. |
| | | String msg = String.format("<%s> and <%s>", dup, orig); |
| | | assertTrue(!dup.equals(orig), msg); |
| | | assertTrue(l.isDescendantOf(DN.decode("dc=opends"))); |
| | | assertFalse(DN.decode("dc=opends").isDescendantOf(l)); |
| | | |
| | | assertEquals(l, e); |
| | | assertEquals(l.hashCode(), e.hashCode()); |
| | | |
| | | assertEquals(l.toNormalizedString(), e.toNormalizedString()); |
| | | assertEquals(l.toString(), e.toString()); |
| | | |
| | | assertEquals(l.getRDN(), RDN.decode("dc=bar")); |
| | | |
| | | assertEquals(l.getRDN(0), RDN.decode("dc=bar")); |
| | | assertEquals(l.getRDN(1), RDN.decode("dc=opends")); |
| | | |
| | | assertEquals(l.getParent(), DN.decode("dc=opends")); |
| | | assertEquals(l.getParent(), e.getParent()); |
| | | |
| | | assertEquals(l.concat(RDN.decode("dc=xxx")), DN |
| | | .decode("dc=xxx,dc=bar,dc=opends")); |
| | | assertEquals(l.concat(DN.decode("dc=xxx,dc=yyy")), DN |
| | | .decode("dc=xxx,dc=yyy,dc=bar,dc=opends")); |
| | | |
| | | assertEquals(l.getLocalName(1), DN.decode("dc=bar")); |
| | | assertEquals(l.getLocalName(0, 1), DN.decode("dc=opends")); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Is ancestor of test data provider. |
| | | * |
| | | * @return The array of test data. |
| | | */ |
| | | @DataProvider(name = "createIsAncestorOfTestData") |
| | | public Object[][] createIsAncestorOfTestData() { |
| | | return new Object[][] { |
| | | { "", "", true }, |
| | | { "", "dc=org", true }, |
| | | { "", "dc=opends,dc=org", true }, |
| | | { "", "dc=foo,dc=opends,dc=org", true }, |
| | | { "dc=org", "", false }, |
| | | { "dc=org", "dc=org", true }, |
| | | { "dc=org", "dc=opends,dc=org", true }, |
| | | { "dc=org", "dc=foo,dc=opends,dc=org", true }, |
| | | { "dc=opends,dc=org", "", false }, |
| | | { "dc=opends,dc=org", "dc=org", false }, |
| | | { "dc=opends,dc=org", "dc=opends,dc=org", true }, |
| | | { "dc=opends,dc=org", "dc=foo,dc=opends,dc=org", true }, |
| | | { "dc=foo,dc=opends,dc=org", "", false }, |
| | | { "dc=foo,dc=opends,dc=org", "dc=org", false }, |
| | | { "dc=foo,dc=opends,dc=org", "dc=opends,dc=org", false }, |
| | | { "dc=foo,dc=opends,dc=org", "dc=foo,dc=opends,dc=org", true }, |
| | | { "dc=org", "dc=com", false }, |
| | | { "dc=opends,dc=org", "dc=foo,dc=org", false }, |
| | | { "dc=opends,dc=org", "dc=opends,dc=com", false }, }; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test the isAncestoryOf method. |
| | | * |
| | | * @param s |
| | | * The test DN string. |
| | | * @param d |
| | | * The dn parameter. |
| | | * @param e |
| | | * The expected result. |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(dataProvider = "createIsAncestorOfTestData") |
| | | public void testIsAncestorOf(String s, String d, boolean e) |
| | | throws Exception { |
| | | DN dn = DN.decode(s); |
| | | DN other = DN.decode(d); |
| | | |
| | | assertEquals(dn.isAncestorOf(other), e, s + " isAncestoryOf " + d); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test the isAncestorOf method. |
| | | * |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(expectedExceptions = { NullPointerException.class, |
| | | AssertionError.class }) |
| | | public void testIsAncestorOfException() throws Exception { |
| | | DN dn = DN.decode("dc=com"); |
| | | dn.isAncestorOf(null); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Is descendant of test data provider. |
| | | * |
| | | * @return The array of test data. |
| | | */ |
| | | @DataProvider(name = "createIsDescendantOfTestData") |
| | | public Object[][] createIsDescendantOfTestData() { |
| | | return new Object[][] { |
| | | { "", "", true }, |
| | | { "", "dc=org", false }, |
| | | { "", "dc=opends,dc=org", false }, |
| | | { "", "dc=foo,dc=opends,dc=org", false }, |
| | | { "dc=org", "", true }, |
| | | { "dc=org", "dc=org", true }, |
| | | { "dc=org", "dc=opends,dc=org", false }, |
| | | { "dc=org", "dc=foo,dc=opends,dc=org", false }, |
| | | { "dc=opends,dc=org", "", true }, |
| | | { "dc=opends,dc=org", "dc=org", true }, |
| | | { "dc=opends,dc=org", "dc=opends,dc=org", true }, |
| | | { "dc=opends,dc=org", "dc=foo,dc=opends,dc=org", false }, |
| | | { "dc=foo,dc=opends,dc=org", "", true }, |
| | | { "dc=foo,dc=opends,dc=org", "dc=org", true }, |
| | | { "dc=foo,dc=opends,dc=org", "dc=opends,dc=org", true }, |
| | | { "dc=foo,dc=opends,dc=org", "dc=foo,dc=opends,dc=org", true }, |
| | | { "dc=org", "dc=com", false }, |
| | | { "dc=opends,dc=org", "dc=foo,dc=org", false }, |
| | | { "dc=opends,dc=org", "dc=opends,dc=com", false }, }; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test the isDescendantOf method. |
| | | * |
| | | * @param s |
| | | * The test DN string. |
| | | * @param d |
| | | * The dn parameter. |
| | | * @param e |
| | | * The expected result. |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(dataProvider = "createIsDescendantOfTestData") |
| | | public void testIsDescendantOf(String s, String d, boolean e) |
| | | throws Exception { |
| | | DN dn = DN.decode(s); |
| | | DN other = DN.decode(d); |
| | | |
| | | assertEquals(dn.isDescendantOf(other), e, s + " isDescendantOf " |
| | | + d); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test the isDescendantOf method. |
| | | * |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(expectedExceptions = { NullPointerException.class, |
| | | AssertionError.class }) |
| | | public void testIsDescendantOfException() throws Exception { |
| | | DN dn = DN.decode("dc=com"); |
| | | dn.isDescendantOf(null); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * DN equality test data provider. |
| | | * |
| | | * @return The array of test DN strings. |
| | | */ |
| | | @DataProvider(name = "createDNEqualityData") |
| | | public Object[][] createDNEqualityData() { |
| | | return new Object[][] { |
| | | { "cn=hello world,dc=com", "cn=hello world,dc=com", 0 }, |
| | | { "cn=hello world,dc=com", "CN=hello world,dc=com", 0 }, |
| | | { "cn=hello world,dc=com", "cn=hello world,dc=com", 0 }, |
| | | { " cn = hello world ,dc=com", "cn=hello world,dc=com", 0 }, |
| | | { "cn=hello world\\ ,dc=com", "cn=hello world,dc=com", 0 }, |
| | | { "cn=HELLO WORLD,dc=com", "cn=hello world,dc=com", 0 }, |
| | | { "cn=HELLO+sn=WORLD,dc=com", "sn=world+cn=hello,dc=com", 0 }, |
| | | { "x-test-integer-type=10,dc=com", |
| | | "x-test-integer-type=9,dc=com", 1 }, |
| | | { "x-test-integer-type=999,dc=com", |
| | | "x-test-integer-type=1000,dc=com", -1 }, |
| | | { "x-test-integer-type=-1,dc=com", |
| | | "x-test-integer-type=0,dc=com", -1 }, |
| | | { "x-test-integer-type=0,dc=com", |
| | | "x-test-integer-type=-1,dc=com", 1 }, |
| | | { "cn=aaa,dc=com", "cn=aaaa,dc=com", -1 }, |
| | | { "cn=AAA,dc=com", "cn=aaaa,dc=com", -1 }, |
| | | { "cn=aaa,dc=com", "cn=AAAA,dc=com", -1 }, |
| | | { "cn=aaaa,dc=com", "cn=aaa,dc=com", 1 }, |
| | | { "cn=AAAA,dc=com", "cn=aaa,dc=com", 1 }, |
| | | { "cn=aaaa,dc=com", "cn=AAA,dc=com", 1 }, |
| | | { "cn=aaab,dc=com", "cn=aaaa,dc=com", 1 }, |
| | | { "cn=aaaa,dc=com", "cn=aaab,dc=com", -1 }, |
| | | { "dc=aaa,dc=aaa", "dc=bbb", -1 }, |
| | | { "dc=bbb,dc=aaa", "dc=bbb", -1 }, |
| | | { "dc=ccc,dc=aaa", "dc=bbb", -1 }, |
| | | { "dc=aaa,dc=bbb", "dc=bbb", 1 }, |
| | | { "dc=bbb,dc=bbb", "dc=bbb", 1 }, |
| | | { "dc=ccc,dc=bbb", "dc=bbb", 1 }, |
| | | { "dc=aaa,dc=ccc", "dc=bbb", 1 }, |
| | | { "dc=bbb,dc=ccc", "dc=bbb", 1 }, |
| | | { "dc=ccc,dc=ccc", "dc=bbb", 1 }, |
| | | |
| | | }; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test DN equality |
| | | * |
| | | * @param first |
| | | * First DN to compare. |
| | | * @param second |
| | | * Second DN to compare. |
| | | * @param result |
| | | * Expected comparison result. |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(dataProvider = "createDNEqualityData") |
| | | public void testEquality(String first, String second, int result) |
| | | throws Exception { |
| | | DN dn1 = DN.decode(first); |
| | | DN dn2 = DN.decode(second); |
| | | |
| | | if (result == 0) { |
| | | assertTrue(dn1.equals(dn2), "DN equality for <" + first |
| | | + "> and <" + second + ">"); |
| | | } else { |
| | | assertFalse(dn1.equals(dn2), "DN equality for <" + first |
| | | + "> and <" + second + ">"); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test DN hashCode |
| | | * |
| | | * @param first |
| | | * First DN to compare. |
| | | * @param second |
| | | * Second DN to compare. |
| | | * @param result |
| | | * Expected comparison result. |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(dataProvider = "createDNEqualityData") |
| | | public void testHashCode(String first, String second, int result) |
| | | throws Exception { |
| | | DN dn1 = DN.decode(first); |
| | | DN dn2 = DN.decode(second); |
| | | |
| | | int h1 = dn1.hashCode(); |
| | | int h2 = dn2.hashCode(); |
| | | |
| | | if (result == 0) { |
| | | if (h1 != h2) { |
| | | fail("Hash codes for <" + first + "> and <" + second |
| | | + "> should be the same."); |
| | | } |
| | | } else { |
| | | if (h1 == h2) { |
| | | fail("Hash codes for <" + first + "> and <" + second |
| | | + "> should be the same."); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test DN compareTo |
| | | * |
| | | * @param first |
| | | * First DN to compare. |
| | | * @param second |
| | | * Second DN to compare. |
| | | * @param result |
| | | * Expected comparison result. |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(dataProvider = "createDNEqualityData") |
| | | public void testCompareTo(String first, String second, int result) |
| | | throws Exception { |
| | | DN dn1 = DN.decode(first); |
| | | DN dn2 = DN.decode(second); |
| | | |
| | | int rc = dn1.compareTo(dn2); |
| | | |
| | | // Normalize the result. |
| | | if (rc < 0) { |
| | | rc = -1; |
| | | } else if (rc > 0) { |
| | | rc = 1; |
| | | } |
| | | |
| | | assertEquals(rc, result, "Comparison for <" + first + "> and <" |
| | | + second + ">."); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test DN string decoder. |
| | | * |
| | | * @param rawDN |
| | | * Raw DN string representation. |
| | | * @param normDN |
| | | * Normalized DN string representation. |
| | | * @param stringDN |
| | | * String representation. |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(dataProvider = "testDNs") |
| | | public void testToString(String rawDN, String normDN, |
| | | String stringDN) throws Exception { |
| | | DN dn = DN.decode(rawDN); |
| | | assertEquals(dn.toString(), stringDN); |
| | | } |
| | | |
| | | } |
| | |
| | | "{ base \"dc=example, dc=com\", maximum 2 }" }; |
| | | |
| | | // Relative to the root DN. |
| | | DN rootDN = new DN(); |
| | | DN rootDN = DN.nullDN(); |
| | | |
| | | SubtreeSpecificationSet expected = new SubtreeSpecificationSet(); |
| | | for (String value : values) { |
| New file |
| | |
| | | /* |
| | | * CDDL HEADER START |
| | | * |
| | | * The contents of this file are subject to the terms of the |
| | | * Common Development and Distribution License, Version 1.0 only |
| | | * (the "License"). You may not use this file except in compliance |
| | | * with the License. |
| | | * |
| | | * You can obtain a copy of the license at |
| | | * trunk/opends/resource/legal-notices/OpenDS.LICENSE |
| | | * or https://OpenDS.dev.java.net/OpenDS.LICENSE. |
| | | * See the License for the specific language governing permissions |
| | | * and limitations under the License. |
| | | * |
| | | * When distributing Covered Code, include this CDDL HEADER in each |
| | | * file and include the License file at |
| | | * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, |
| | | * add the following below this CDDL HEADER, with the fields enclosed |
| | | * by brackets "[]" replaced with your own identifying * information: |
| | | * Portions Copyright [yyyy] [name of copyright owner] |
| | | * |
| | | * CDDL HEADER END |
| | | * |
| | | * |
| | | * Portions Copyright 2006 Sun Microsystems, Inc. |
| | | */ |
| | | package org.opends.server.types; |
| | | |
| | | |
| | | |
| | | import static org.testng.Assert.assertEquals; |
| | | import static org.testng.Assert.assertFalse; |
| | | import static org.testng.Assert.assertTrue; |
| | | import static org.testng.Assert.assertNull; |
| | | import static org.testng.Assert.fail; |
| | | |
| | | import org.opends.server.TestCaseUtils; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.protocols.asn1.ASN1OctetString; |
| | | import org.testng.annotations.BeforeClass; |
| | | import org.testng.annotations.DataProvider; |
| | | import org.testng.annotations.Test; |
| | | |
| | | |
| | | |
| | | /** |
| | | * This class defines a set of tests for the |
| | | * {@link org.opends.server.types.RDN} class. |
| | | */ |
| | | public final class TestRDN extends TypesTestCase { |
| | | |
| | | // Domain component attribute type. |
| | | private AttributeType AT_DC; |
| | | |
| | | // Common name attribute type. |
| | | private AttributeType AT_CN; |
| | | |
| | | // Test attribute value. |
| | | private AttributeValue AV_DC_ORG; |
| | | |
| | | // Test attribute value. |
| | | private AttributeValue AV_DC_OPENDS; |
| | | |
| | | // Test attribute value. |
| | | private AttributeValue AV_CN; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Set up the environment for performing the tests in this suite. |
| | | * |
| | | * @throws Exception |
| | | * If the environment could not be set up. |
| | | */ |
| | | @BeforeClass |
| | | public void setUp() throws Exception { |
| | | // This test suite depends on having the schema available, so |
| | | // we'll start the server. |
| | | TestCaseUtils.startServer(); |
| | | |
| | | AT_DC = DirectoryServer.getAttributeType("dc"); |
| | | AT_CN = DirectoryServer.getAttributeType("cn"); |
| | | |
| | | AttributeType dummy = DirectoryServer.getDefaultAttributeType( |
| | | "x-test-integer-type", DirectoryServer |
| | | .getDefaultIntegerSyntax()); |
| | | DirectoryServer.getSchema().registerAttributeType(dummy, true); |
| | | |
| | | AV_DC_ORG = new AttributeValue(AT_DC, "org"); |
| | | AV_DC_OPENDS = new AttributeValue(AT_DC, "opends"); |
| | | AV_CN = new AttributeValue(AT_DC, "hello world"); |
| | | } |
| | | |
| | | |
| | | |
| | | // First test the constructors. |
| | | |
| | | /** |
| | | * Check the constructor throws a NPE when parameters are not |
| | | * provided. |
| | | * |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(expectedExceptions = { NullPointerException.class, |
| | | AssertionError.class }) |
| | | public void testConstructorNPE1() throws Exception { |
| | | RDN.create(AT_DC, null); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Check the constructor throws a NPE when parameters are not |
| | | * provided. |
| | | * |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(expectedExceptions = { NullPointerException.class, |
| | | AssertionError.class }) |
| | | public void testConstructorNPE2() throws Exception { |
| | | RDN.create(null, AV_DC_ORG); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Check the constructor throws a NPE when parameters are not |
| | | * provided. |
| | | * |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(expectedExceptions = { NullPointerException.class, |
| | | AssertionError.class }) |
| | | public void testConstructorNPE3() throws Exception { |
| | | RDN.create(AT_DC, "dc", null); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Check the constructor throws a NPE when parameters are not |
| | | * provided. |
| | | * |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(expectedExceptions = { NullPointerException.class, |
| | | AssertionError.class }) |
| | | public void testConstructorNPE4() throws Exception { |
| | | RDN.create(AT_DC, null, AV_DC_ORG); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Check the constructor throws a NPE when parameters are not |
| | | * provided. |
| | | * |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(expectedExceptions = { NullPointerException.class, |
| | | AssertionError.class }) |
| | | public void testConstructorNPE5() throws Exception { |
| | | RDN.create(null, "dc", AV_DC_ORG); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Check the decode method throws a NPE when parameters are not |
| | | * provided. |
| | | * |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(expectedExceptions = { NullPointerException.class, |
| | | AssertionError.class }) |
| | | public void testDecodeNPE() throws Exception { |
| | | RDN.decode((String) null); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Check the valueOf method throws a NPE when parameters are not |
| | | * provided. |
| | | * |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(expectedExceptions = { NullPointerException.class, |
| | | AssertionError.class }) |
| | | public void testValueOfNPE() throws Exception { |
| | | RDN.valueOf(null); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test RDN construction with single AVA. |
| | | * |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test |
| | | public void testConstructor() throws Exception { |
| | | RDN rdn = RDN.create(AT_DC, AV_DC_ORG); |
| | | |
| | | assertEquals(rdn.getNumValues(), 1); |
| | | assertEquals(rdn.getAttributeType(0), AT_DC); |
| | | assertEquals(rdn.getAttributeName(0), AT_DC.getNameOrOID()); |
| | | assertEquals(rdn.getAttributeValue(0), AV_DC_ORG); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test RDN construction with single AVA and a user-defined name. |
| | | * |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test |
| | | public void testConstructorWithName() throws Exception { |
| | | RDN rdn = RDN.create(AT_DC, "domainComponent", AV_DC_ORG); |
| | | |
| | | assertEquals(rdn.getNumValues(), 1); |
| | | assertEquals(rdn.getAttributeType(0), AT_DC); |
| | | assertEquals(rdn.getAttributeName(0), "domainComponent"); |
| | | assertEquals(rdn.getAttributeValue(0), AV_DC_ORG); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test RDN builder. |
| | | * |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test |
| | | public void testBuilder() throws Exception { |
| | | RDN.Builder builder = RDN.createBuilder(); |
| | | |
| | | builder.append(AT_DC, AV_DC_ORG); |
| | | RDN rdn = builder.getInstance(); |
| | | |
| | | assertEquals(rdn.getNumValues(), 1); |
| | | assertEquals(rdn.getAttributeType(0), AT_DC); |
| | | assertEquals(rdn.getAttributeName(0), AT_DC.getNameOrOID()); |
| | | assertEquals(rdn.getAttributeValue(0), AV_DC_ORG); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test RDN builder. |
| | | * |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test |
| | | public void testBuilderWithName() throws Exception { |
| | | RDN.Builder builder = RDN.createBuilder(); |
| | | |
| | | builder.append(AT_DC, "domainComponent", AV_DC_ORG); |
| | | RDN rdn = builder.getInstance(); |
| | | |
| | | assertEquals(rdn.getNumValues(), 1); |
| | | assertEquals(rdn.getAttributeType(0), AT_DC); |
| | | assertEquals(rdn.getAttributeName(0), "domainComponent"); |
| | | assertEquals(rdn.getAttributeValue(0), AV_DC_ORG); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test RDN builder. |
| | | * |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test |
| | | public void testBuilderIsEmpty() throws Exception { |
| | | RDN.Builder builder = RDN.createBuilder(); |
| | | |
| | | assertTrue(builder.isEmpty()); |
| | | |
| | | builder.append(AT_DC, AV_DC_ORG); |
| | | |
| | | assertFalse(builder.isEmpty()); |
| | | |
| | | builder.getInstance(); |
| | | |
| | | assertFalse(builder.isEmpty()); |
| | | |
| | | builder.clear(); |
| | | |
| | | assertTrue(builder.isEmpty()); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test RDN builder. |
| | | * |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(expectedExceptions = IllegalArgumentException.class) |
| | | public void testBuilderDupesNotAllowed() throws Exception { |
| | | RDN.Builder builder = RDN.createBuilder(); |
| | | |
| | | builder.append(AT_DC, AV_DC_ORG); |
| | | builder.append(AT_DC, AV_DC_OPENDS); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test RDN builder. |
| | | * |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test |
| | | public void testBuilderMultiAVA() throws Exception { |
| | | RDN.Builder builder = RDN.createBuilder(); |
| | | |
| | | builder.append(AT_DC, AV_DC_ORG); |
| | | builder.append(AT_CN, AV_CN); |
| | | RDN rdn = builder.getInstance(); |
| | | |
| | | assertEquals(rdn.getNumValues(), 2); |
| | | |
| | | assertEquals(rdn.getAttributeType(0), AT_DC); |
| | | assertEquals(rdn.getAttributeName(0), AT_DC.getNameOrOID()); |
| | | assertEquals(rdn.getAttributeValue(0), AV_DC_ORG); |
| | | |
| | | assertEquals(rdn.getAttributeType(1), AT_CN); |
| | | assertEquals(rdn.getAttributeName(1), AT_CN.getNameOrOID()); |
| | | assertEquals(rdn.getAttributeValue(1), AV_CN); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * RDN test data provider. |
| | | * |
| | | * @return The array of test RDN strings. |
| | | */ |
| | | @DataProvider(name = "testRDNs") |
| | | public Object[][] createData() { |
| | | return new Object[][] { |
| | | { "dc=hello world", "dc=hello world", "dc=hello world" }, |
| | | { "DC=HELLO WORLD", "dc=hello world", "DC=HELLO WORLD" }, |
| | | { "dc = hello world", "dc=hello world", |
| | | "dc=hello world" }, |
| | | { " dc = hello world ", "dc=hello world", |
| | | "dc=hello world" }, |
| | | { "givenName=John+cn=Doe", "cn=doe+givenname=john", |
| | | "givenName=John+cn=Doe" }, |
| | | { "givenName=John\\+cn=Doe", "givenname=john\\+cn=doe", |
| | | "givenName=John\\+cn=Doe" }, |
| | | { "cn=Doe\\, John", "cn=doe\\, john", "cn=Doe\\, John" }, |
| | | { "OU=Sales+CN=J. Smith", "cn=j. smith+ou=sales", |
| | | "OU=Sales+CN=J. Smith" }, |
| | | { "CN=James \\\"Jim\\\" Smith\\, III", |
| | | "cn=james \\\"jim\\\" smith\\, iii", |
| | | "CN=James \\\"Jim\\\" Smith\\, III" }, |
| | | { "CN=Before\\0dAfter", "cn=before\\0dafter", |
| | | "CN=Before\\0dAfter" }, |
| | | { "1.3.6.1.4.1.1466.0=#04024869", |
| | | "1.3.6.1.4.1.1466.0=\\04\\02hi", |
| | | "1.3.6.1.4.1.1466.0=\\04\\02Hi" }, |
| | | { "CN=Lu\\C4\\8Di\\C4\\87", "cn=lu\\c4\\8di\\c4\\87", |
| | | "CN=Lu\\c4\\8di\\c4\\87" }, |
| | | { "ou=\\e5\\96\\b6\\e6\\a5\\ad\\e9\\83\\a8", |
| | | "ou=\\e5\\96\\b6\\e6\\a5\\ad\\e9\\83\\a8", |
| | | "ou=\\e5\\96\\b6\\e6\\a5\\ad\\e9\\83\\a8" }, |
| | | { "photo=\\ john \\ ", "photo=\\ john \\ ", |
| | | "photo=\\ john \\ " }, |
| | | { "AB-global=", "ab-global=", "AB-global=" }, |
| | | { "cn=John+a=", "a=+cn=john", "cn=John+a=" }, |
| | | { "OID.1.3.6.1.4.1.1466.0=#04024869", |
| | | "1.3.6.1.4.1.1466.0=\\04\\02hi", |
| | | "1.3.6.1.4.1.1466.0=\\04\\02Hi" }, |
| | | { "O=\"Sue, Grabbit and Runn\"", "o=sue\\, grabbit and runn", |
| | | "O=Sue\\, Grabbit and Runn" }, }; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test RDN string decoder. |
| | | * |
| | | * @param rawRDN |
| | | * Raw RDN string representation. |
| | | * @param normRDN |
| | | * Normalized RDN string representation. |
| | | * @param stringRDN |
| | | * String representation. |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(dataProvider = "testRDNs") |
| | | public void testDecodeString(String rawRDN, String normRDN, |
| | | String stringRDN) throws Exception { |
| | | RDN rdn = RDN.decode(rawRDN); |
| | | assertEquals(rdn.toNormalizedString(), normRDN); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test RDN byte string decoder. |
| | | * |
| | | * @param rawRDN |
| | | * Raw RDN string representation. |
| | | * @param normRDN |
| | | * Normalized RDN string representation. |
| | | * @param stringRDN |
| | | * String representation. |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(dataProvider = "testRDNs") |
| | | public void testDecodeByteString(String rawRDN, String normRDN, |
| | | String stringRDN) throws Exception { |
| | | ASN1OctetString octetString = new ASN1OctetString(rawRDN); |
| | | RDN rdn = RDN.decode(octetString); |
| | | assertEquals(rdn.toNormalizedString(), normRDN); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test valueOf. |
| | | * |
| | | * @param rawRDN |
| | | * Raw RDN string representation. |
| | | * @param normRDN |
| | | * Normalized RDN string representation. |
| | | * @param stringRDN |
| | | * String representation. |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(dataProvider = "testRDNs") |
| | | public void testValueOf(String rawRDN, String normRDN, |
| | | String stringRDN) throws Exception { |
| | | RDN rdn = RDN.valueOf(rawRDN); |
| | | assertEquals(rdn.toNormalizedString(), normRDN); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Illegal RDN test data provider. |
| | | * |
| | | * @return The array of illegal test RDN strings. |
| | | */ |
| | | @DataProvider(name = "illegalRDNs") |
| | | public Object[][] createIllegalData() { |
| | | return new Object[][] { { "" }, { "=" }, { "manager" }, |
| | | { "manager " }, { "cn+Jim" }, { "cn=Jim+" }, { "cn=Jim+sn" }, |
| | | { "cn=Jim," }, { "cn=Jim, " }, { "cn=Jim, sn=Jam " }, |
| | | { "cn+uid=Jim" }, { "-cn=Jim" }, { "/tmp=a" }, { "\\tmp=a" }, |
| | | { "cn;lang-en=Jim" }, { "@cn=Jim" }, { "_name_=Jim" }, |
| | | { "\u03c0=pi" }, { "v1.0=buggy" }, |
| | | { "1.3.6.1.4.1.1466..0=#04024869" }, }; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test RDN string decoder against illegal strings. |
| | | * |
| | | * @param rawRDN |
| | | * Illegal RDN string representation. |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(dataProvider = "illegalRDNs", expectedExceptions = DirectoryException.class) |
| | | public void testDecodeString(String rawRDN) throws Exception { |
| | | RDN.decode(rawRDN); |
| | | |
| | | fail("Expected exception for value \"" + rawRDN + "\""); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test RDN byte string decoder against illegal strings. |
| | | * |
| | | * @param rawRDN |
| | | * Illegal RDN string representation. |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(dataProvider = "illegalRDNs", expectedExceptions = DirectoryException.class) |
| | | public void testDecodeByteString(String rawRDN) throws Exception { |
| | | ASN1OctetString octetString = new ASN1OctetString(rawRDN); |
| | | RDN.decode(octetString); |
| | | |
| | | fail("Expected exception for value \"" + rawRDN + "\""); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test valueOf against illegal strings. |
| | | * |
| | | * @param rawRDN |
| | | * Illegal RDN string representation. |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(dataProvider = "illegalRDNs", expectedExceptions = DirectoryException.class) |
| | | public void testValueOf(String rawRDN) throws Exception { |
| | | RDN.valueOf(rawRDN); |
| | | |
| | | fail("Expected exception for value \"" + rawRDN + "\""); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test getAttributeName. |
| | | * |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test |
| | | public void testGetAttributeName() throws Exception { |
| | | RDN.Builder builder = RDN.createBuilder(); |
| | | |
| | | builder.append(AT_DC, AV_DC_ORG); |
| | | builder.append(AT_CN, AV_CN); |
| | | RDN rdn = builder.getInstance(); |
| | | |
| | | assertEquals(rdn.getAttributeName(0), AT_DC.getNameOrOID()); |
| | | assertEquals(rdn.getAttributeName(1), AT_CN.getNameOrOID()); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test getAttributeName IndexOutOfBoundsException. |
| | | * |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(expectedExceptions = IndexOutOfBoundsException.class) |
| | | public void testGetAttributeNameException() throws Exception { |
| | | RDN.Builder builder = RDN.createBuilder(); |
| | | |
| | | builder.append(AT_DC, AV_DC_ORG); |
| | | RDN rdn = builder.getInstance(); |
| | | |
| | | rdn.getAttributeName(1); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test getAttributeType. |
| | | * |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test |
| | | public void testGetAttributeType() throws Exception { |
| | | RDN.Builder builder = RDN.createBuilder(); |
| | | |
| | | builder.append(AT_DC, AV_DC_ORG); |
| | | builder.append(AT_CN, AV_CN); |
| | | RDN rdn = builder.getInstance(); |
| | | |
| | | assertEquals(rdn.getAttributeType(0), AT_DC); |
| | | assertEquals(rdn.getAttributeType(1), AT_CN); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test getAttributeType IndexOutOfBoundsException. |
| | | * |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(expectedExceptions = IndexOutOfBoundsException.class) |
| | | public void testGetAttributeTypeException() throws Exception { |
| | | RDN.Builder builder = RDN.createBuilder(); |
| | | |
| | | builder.append(AT_DC, AV_DC_ORG); |
| | | RDN rdn = builder.getInstance(); |
| | | |
| | | rdn.getAttributeType(1); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test getAttributeValue. |
| | | * |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test |
| | | public void testGetAttributeValue() throws Exception { |
| | | RDN.Builder builder = RDN.createBuilder(); |
| | | |
| | | builder.append(AT_DC, AV_DC_ORG); |
| | | builder.append(AT_CN, AV_CN); |
| | | RDN rdn = builder.getInstance(); |
| | | |
| | | assertEquals(rdn.getAttributeValue(0), AV_DC_ORG); |
| | | assertEquals(rdn.getAttributeValue(1), AV_CN); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test getAttributeValue IndexOutOfBoundsException. |
| | | * |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(expectedExceptions = IndexOutOfBoundsException.class) |
| | | public void testGetAttributeValueException() throws Exception { |
| | | RDN.Builder builder = RDN.createBuilder(); |
| | | |
| | | builder.append(AT_DC, AV_DC_ORG); |
| | | RDN rdn = builder.getInstance(); |
| | | |
| | | rdn.getAttributeValue(1); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test getAttributeValue. |
| | | * |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test |
| | | public void testGetAttributeValueByType() throws Exception { |
| | | RDN.Builder builder = RDN.createBuilder(); |
| | | |
| | | builder.append(AT_DC, AV_DC_ORG); |
| | | RDN rdn = builder.getInstance(); |
| | | |
| | | assertEquals(rdn.getAttributeValue(AT_DC), AV_DC_ORG); |
| | | assertNull(rdn.getAttributeValue(AT_CN)); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test getNumValues. |
| | | * |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test |
| | | public void testGetNumValues() throws Exception { |
| | | RDN.Builder builder = RDN.createBuilder(); |
| | | |
| | | builder.append(AT_DC, AV_DC_ORG); |
| | | RDN rdn = builder.getInstance(); |
| | | assertEquals(rdn.getNumValues(), 1); |
| | | |
| | | builder.append(AT_CN, AV_CN); |
| | | rdn = builder.getInstance(); |
| | | assertEquals(rdn.getNumValues(), 2); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test hasAttributeType. |
| | | * |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test |
| | | public void testHasAttributeType() throws Exception { |
| | | RDN.Builder builder = RDN.createBuilder(); |
| | | builder.append(AT_DC, AV_DC_ORG); |
| | | RDN rdn = builder.getInstance(); |
| | | |
| | | assertTrue(rdn.hasAttributeType(AT_DC)); |
| | | assertFalse(rdn.hasAttributeType(AT_CN)); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test isMultiValued. |
| | | * |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test |
| | | public void testIsMultiValued() throws Exception { |
| | | RDN.Builder builder = RDN.createBuilder(); |
| | | |
| | | builder.append(AT_DC, AV_DC_ORG); |
| | | RDN rdn = builder.getInstance(); |
| | | assertFalse(rdn.isMultiValued()); |
| | | |
| | | builder.append(AT_CN, AV_CN); |
| | | rdn = builder.getInstance(); |
| | | assertTrue(rdn.isMultiValued()); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test RDN string decoder. |
| | | * |
| | | * @param rawRDN |
| | | * Raw RDN string representation. |
| | | * @param normRDN |
| | | * Normalized RDN string representation. |
| | | * @param stringRDN |
| | | * String representation. |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(dataProvider = "testRDNs") |
| | | public void testToString(String rawRDN, String normRDN, |
| | | String stringRDN) throws Exception { |
| | | RDN rdn = RDN.decode(rawRDN); |
| | | assertEquals(rdn.toString(), stringRDN); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * RDN equality test data provider. |
| | | * |
| | | * @return The array of test RDN strings. |
| | | */ |
| | | @DataProvider(name = "createRDNEqualityData") |
| | | public Object[][] createRDNEqualityData() { |
| | | return new Object[][] { |
| | | { "cn=hello world", "cn=hello world", 0 }, |
| | | { "cn=hello world", "CN=hello world", 0 }, |
| | | { "cn=hello world", "cn=hello world", 0 }, |
| | | { " cn = hello world ", "cn=hello world", 0 }, |
| | | { "cn=hello world\\ ", "cn=hello world", 0 }, |
| | | { "cn=HELLO WORLD", "cn=hello world", 0 }, |
| | | { "cn=HELLO+sn=WORLD", "sn=world+cn=hello", 0 }, |
| | | { "x-test-integer-type=10", "x-test-integer-type=9", 1 }, |
| | | { "x-test-integer-type=999", "x-test-integer-type=1000", -1 }, |
| | | { "x-test-integer-type=-1", "x-test-integer-type=0", -1 }, |
| | | { "x-test-integer-type=0", "x-test-integer-type=-1", 1 }, |
| | | { "cn=aaa", "cn=aaaa", -1 }, { "cn=AAA", "cn=aaaa", -1 }, |
| | | { "cn=aaa", "cn=AAAA", -1 }, { "cn=aaaa", "cn=aaa", 1 }, |
| | | { "cn=AAAA", "cn=aaa", 1 }, { "cn=aaaa", "cn=AAA", 1 }, |
| | | { "cn=aaab", "cn=aaaa", 1 }, { "cn=aaaa", "cn=aaab", -1 } }; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test RDN equality |
| | | * |
| | | * @param first |
| | | * First RDN to compare. |
| | | * @param second |
| | | * Second RDN to compare. |
| | | * @param result |
| | | * Expected comparison result. |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(dataProvider = "createRDNEqualityData") |
| | | public void testEquality(String first, String second, int result) |
| | | throws Exception { |
| | | RDN rdn1 = RDN.decode(first); |
| | | RDN rdn2 = RDN.decode(second); |
| | | |
| | | if (result == 0) { |
| | | assertTrue(rdn1.equals(rdn2), "RDN equality for <" + first |
| | | + "> and <" + second + ">"); |
| | | } else { |
| | | assertFalse(rdn1.equals(rdn2), "RDN equality for <" + first |
| | | + "> and <" + second + ">"); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test RDN hashCode |
| | | * |
| | | * @param first |
| | | * First RDN to compare. |
| | | * @param second |
| | | * Second RDN to compare. |
| | | * @param result |
| | | * Expected comparison result. |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(dataProvider = "createRDNEqualityData") |
| | | public void testHashCode(String first, String second, int result) |
| | | throws Exception { |
| | | RDN rdn1 = RDN.decode(first); |
| | | RDN rdn2 = RDN.decode(second); |
| | | |
| | | int h1 = rdn1.hashCode(); |
| | | int h2 = rdn2.hashCode(); |
| | | |
| | | if (result == 0) { |
| | | if (h1 != h2) { |
| | | fail("Hash codes for <" + first + "> and <" + second |
| | | + "> should be the same."); |
| | | } |
| | | } else { |
| | | if (h1 == h2) { |
| | | fail("Hash codes for <" + first + "> and <" + second |
| | | + "> should be the same."); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test RDN compareTo |
| | | * |
| | | * @param first |
| | | * First RDN to compare. |
| | | * @param second |
| | | * Second RDN to compare. |
| | | * @param result |
| | | * Expected comparison result. |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(dataProvider = "createRDNEqualityData") |
| | | public void testCompareTo(String first, String second, int result) |
| | | throws Exception { |
| | | RDN rdn1 = RDN.decode(first); |
| | | RDN rdn2 = RDN.decode(second); |
| | | |
| | | int rc = rdn1.compareTo(rdn2); |
| | | |
| | | // Normalize the result. |
| | | if (rc < 0) { |
| | | rc = -1; |
| | | } else if (rc > 0) { |
| | | rc = 1; |
| | | } |
| | | |
| | | assertEquals(rc, result, "Comparison for <" + first + "> and <" |
| | | + second + ">."); |
| | | } |
| | | |
| | | } |
| | |
| | | @Test(expectedExceptions = { NullPointerException.class, |
| | | AssertionError.class }) |
| | | public void testConstructorNullDN() throws Exception { |
| | | AddChangeRecordEntry entry = new AddChangeRecordEntry(null, attributes); |
| | | new AddChangeRecordEntry(null, attributes); |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | @Test |
| | | public void testConstructorEmptyDN() throws Exception { |
| | | AddChangeRecordEntry entry = new AddChangeRecordEntry(new DN(), |
| | | AddChangeRecordEntry entry = new AddChangeRecordEntry(DN.nullDN(), |
| | | attributes); |
| | | |
| | | Assert.assertEquals(entry.getDN(), new DN()); |
| | | Assert.assertEquals(entry.getDN(), DN.nullDN()); |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | @Test |
| | | public void testChangeOperationType() throws Exception { |
| | | AddChangeRecordEntry entry = new AddChangeRecordEntry(new DN(), attributes); |
| | | AddChangeRecordEntry entry = new AddChangeRecordEntry(DN.nullDN(), attributes); |
| | | |
| | | Assert.assertEquals(entry.getChangeOperationType(), |
| | | ChangeOperationType.ADD); |
| | |
| | | @Test |
| | | public void testGetAttributesEmpty() throws Exception { |
| | | Map<AttributeType, List<Attribute>> empty = Collections.emptyMap(); |
| | | AddChangeRecordEntry entry = new AddChangeRecordEntry(new DN(), empty); |
| | | AddChangeRecordEntry entry = new AddChangeRecordEntry(DN.nullDN(), empty); |
| | | |
| | | List<Attribute> attrs = entry.getAttributes(); |
| | | Assert.assertEquals(attrs.size(), 0); |
| | |
| | | */ |
| | | @Test |
| | | public void testGetAttributesNonEmpty() throws Exception { |
| | | AddChangeRecordEntry entry = new AddChangeRecordEntry(new DN(), attributes); |
| | | AddChangeRecordEntry entry = new AddChangeRecordEntry(DN.nullDN(), attributes); |
| | | |
| | | List<Attribute> attrs = entry.getAttributes(); |
| | | Assert.assertEquals(attrs.size(), 1); |
| | |
| | | @Test(expectedExceptions = { NullPointerException.class, |
| | | AssertionError.class }) |
| | | public void testConstructorNullDN() throws Exception { |
| | | MyChangeRecordEntry entry = new MyChangeRecordEntry(null); |
| | | new MyChangeRecordEntry(null); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Tests the constructor with empty DN. |
| | | * |
| | |
| | | */ |
| | | @Test |
| | | public void testConstructorEmptyDN() throws Exception { |
| | | MyChangeRecordEntry entry = new MyChangeRecordEntry(new DN()); |
| | | MyChangeRecordEntry entry = new MyChangeRecordEntry(DN.nullDN()); |
| | | |
| | | Assert.assertEquals(entry.getDN(), new DN()); |
| | | Assert.assertEquals(entry.getDN(), DN.nullDN()); |
| | | } |
| | | |
| | | /** |
| | |
| | | @Test(expectedExceptions = { NullPointerException.class, |
| | | AssertionError.class }) |
| | | public void testConstructorNullDN() throws Exception { |
| | | DeleteChangeRecordEntry entry = new DeleteChangeRecordEntry(null); |
| | | new DeleteChangeRecordEntry(null); |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | @Test |
| | | public void testConstructorEmptyDN() throws Exception { |
| | | DeleteChangeRecordEntry entry = new DeleteChangeRecordEntry(new DN()); |
| | | DeleteChangeRecordEntry entry = new DeleteChangeRecordEntry(DN.nullDN()); |
| | | |
| | | Assert.assertEquals(entry.getDN(), new DN()); |
| | | Assert.assertEquals(entry.getDN(), DN.nullDN()); |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | @Test |
| | | public void testChangeOperationType() throws Exception { |
| | | DeleteChangeRecordEntry entry = new DeleteChangeRecordEntry(new DN()); |
| | | DeleteChangeRecordEntry entry = new DeleteChangeRecordEntry(DN.nullDN()); |
| | | |
| | | Assert.assertEquals(entry.getChangeOperationType(), |
| | | ChangeOperationType.DELETE); |
| | |
| | | @Test(expectedExceptions = { NullPointerException.class, |
| | | AssertionError.class }) |
| | | public void testConstructorNullDN() throws Exception { |
| | | ModifyChangeRecordEntry entry = new ModifyChangeRecordEntry(null, |
| | | modifications); |
| | | new ModifyChangeRecordEntry(null, modifications); |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | @Test |
| | | public void testConstructorEmptyDN() throws Exception { |
| | | ModifyChangeRecordEntry entry = new ModifyChangeRecordEntry(new DN(), |
| | | ModifyChangeRecordEntry entry = new ModifyChangeRecordEntry(DN.nullDN(), |
| | | modifications); |
| | | |
| | | Assert.assertEquals(entry.getDN(), new DN()); |
| | | Assert.assertEquals(entry.getDN(), DN.nullDN()); |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | @Test |
| | | public void testChangeOperationType() throws Exception { |
| | | ModifyChangeRecordEntry entry = new ModifyChangeRecordEntry(new DN(), |
| | | ModifyChangeRecordEntry entry = new ModifyChangeRecordEntry(DN.nullDN(), |
| | | modifications); |
| | | |
| | | Assert.assertEquals(entry.getChangeOperationType(), |
| | |
| | | @Test |
| | | public void testGetModificationsEmpty() throws Exception { |
| | | List<LDAPModification> empty = Collections.emptyList(); |
| | | ModifyChangeRecordEntry entry = new ModifyChangeRecordEntry(new DN(), |
| | | ModifyChangeRecordEntry entry = new ModifyChangeRecordEntry(DN.nullDN(), |
| | | empty); |
| | | |
| | | List<LDAPModification> mods = entry.getModifications(); |
| | |
| | | */ |
| | | @Test |
| | | public void testGetModificationsNonEmpty() throws Exception { |
| | | ModifyChangeRecordEntry entry = new ModifyChangeRecordEntry(new DN(), |
| | | ModifyChangeRecordEntry entry = new ModifyChangeRecordEntry(DN.nullDN(), |
| | | modifications); |
| | | |
| | | List<LDAPModification> mods = entry.getModifications(); |
| | |
| | | @Test(expectedExceptions = { NullPointerException.class, |
| | | AssertionError.class }) |
| | | public void testConstructorNullDN() throws Exception { |
| | | ModifyDNChangeRecordEntry entry = |
| | | new ModifyDNChangeRecordEntry(null, newRDN, false, newSuperiorDN); |
| | | } |
| | | |
| | |
| | | @Test |
| | | public void testConstructorEmptyDN() throws Exception { |
| | | ModifyDNChangeRecordEntry entry = new ModifyDNChangeRecordEntry( |
| | | new DN(), newRDN, false, newSuperiorDN); |
| | | DN.nullDN(), newRDN, false, newSuperiorDN); |
| | | |
| | | Assert.assertEquals(entry.getDN(), new DN()); |
| | | Assert.assertEquals(entry.getDN(), DN.nullDN()); |
| | | } |
| | | |
| | | /** |
| | |
| | | @Test |
| | | public void testChangeOperationType() throws Exception { |
| | | ModifyDNChangeRecordEntry entry = |
| | | new ModifyDNChangeRecordEntry(new DN(), newRDN, false, newSuperiorDN); |
| | | new ModifyDNChangeRecordEntry(DN.nullDN(), newRDN, false, newSuperiorDN); |
| | | |
| | | Assert.assertEquals(entry.getChangeOperationType(), |
| | | ChangeOperationType.MODIFY_DN); |
| | |
| | | @Test |
| | | public void testGetNewRDN() throws Exception { |
| | | ModifyDNChangeRecordEntry entry = |
| | | new ModifyDNChangeRecordEntry(new DN(), newRDN, false, newSuperiorDN); |
| | | new ModifyDNChangeRecordEntry(DN.nullDN(), newRDN, false, newSuperiorDN); |
| | | |
| | | Assert.assertEquals(entry.getNewRDN(), newRDN.duplicate()); |
| | | Assert.assertEquals(entry.getNewRDN(), newRDN); |
| | | } |
| | | |
| | | /** |
| | |
| | | @Test |
| | | public void testGetNewSuperiorDN() throws Exception { |
| | | ModifyDNChangeRecordEntry entry = |
| | | new ModifyDNChangeRecordEntry(new DN(), newRDN, false, newSuperiorDN); |
| | | new ModifyDNChangeRecordEntry(DN.nullDN(), newRDN, false, newSuperiorDN); |
| | | |
| | | Assert |
| | | .assertEquals(entry.getNewSuperiorDN(), newSuperiorDN.duplicate()); |
| | | .assertEquals(entry.getNewSuperiorDN(), newSuperiorDN); |
| | | } |
| | | |
| | | /** |
| | |
| | | @Test |
| | | public void testDeleteOldRDNFalse() throws Exception { |
| | | ModifyDNChangeRecordEntry entry = |
| | | new ModifyDNChangeRecordEntry(new DN(), newRDN, false, newSuperiorDN); |
| | | new ModifyDNChangeRecordEntry(DN.nullDN(), newRDN, false, newSuperiorDN); |
| | | |
| | | Assert.assertEquals(entry.deleteOldRDN(), false); |
| | | } |
| | |
| | | @Test |
| | | public void testDeleteOldRDNTrue() throws Exception { |
| | | ModifyDNChangeRecordEntry entry = |
| | | new ModifyDNChangeRecordEntry(new DN(), newRDN, true, newSuperiorDN); |
| | | new ModifyDNChangeRecordEntry(DN.nullDN(), newRDN, true, newSuperiorDN); |
| | | |
| | | Assert.assertEquals(entry.deleteOldRDN(), true); |
| | | } |
| | |
| | | } |
| | | |
| | | /** |
| | | * Create test data for {@link StaticUtils#compare(byte[], byte[])}. |
| | | * |
| | | * @return Returns an array of test data. |
| | | */ |
| | | @DataProvider(name = "compareBytesTestData") |
| | | public Object[][] createCompareBytesTestData() { |
| | | return new Object[][] { |
| | | { null, null, 0 }, |
| | | { null, new byte[0], -1 }, |
| | | { new byte[0], null, 1 }, |
| | | { new byte[0], new byte[0], 0 }, |
| | | { new byte[] { 0x00 }, new byte[] { 0x00 }, 0 }, |
| | | { new byte[] { 0x01 }, new byte[] { 0x00 }, 1 }, |
| | | { new byte[] { 0x7f }, new byte[] { 0x00 }, 1 }, |
| | | { new byte[] { (byte) 0x80 }, new byte[] { 0x00 }, -1 }, |
| | | { new byte[] { (byte) 0xff }, new byte[] { 0x00 }, -1 }, |
| | | { new byte[] { 0x00 }, new byte[] { 0x01 }, -1 }, |
| | | { new byte[] { 0x00 }, new byte[] { 0x7f }, -1 }, |
| | | { new byte[] { 0x00 }, new byte[] { (byte) 0x80 }, 1 }, |
| | | { new byte[] { 0x00 }, new byte[] { (byte) 0xff }, 1 }, |
| | | { new byte[] { 0x00, 0x01, 0x02 }, |
| | | new byte[] { 0x00, 0x01, 0x02 }, 0 }, |
| | | { new byte[] { 0x00, 0x01 }, new byte[] { 0x00, 0x01, 0x02 }, |
| | | -1 }, |
| | | { new byte[] { 0x00, 0x01, 0x02 }, new byte[] { 0x00, 0x01 }, |
| | | 1 }, }; |
| | | } |
| | | |
| | | /** |
| | | * Tests the {@link StaticUtils#compare(byte[], byte[])} method. |
| | | * |
| | | * @param a |
| | | * The first byte array. |
| | | * @param a2 |
| | | * The second byte array. |
| | | * @param expected |
| | | * The expected result. |
| | | * @throws Exception |
| | | * If the test failed unexpectedly. |
| | | */ |
| | | @Test(dataProvider = "compareBytesTestData") |
| | | public void testCompareBytes(byte[] a, byte[] a2, int expected) |
| | | throws Exception { |
| | | int rc = StaticUtils.compare(a, a2); |
| | | |
| | | if (expected < 0 && rc >= 0) { |
| | | Assert.fail("Expected negative result but got " + rc); |
| | | } |
| | | |
| | | if (expected > 0 && rc <= 0) { |
| | | Assert.fail("Expected positive result but got " + rc); |
| | | } |
| | | |
| | | if (expected == 0 && rc != 0) { |
| | | Assert.fail("Expected zero result but got " + rc); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Create test strings for the {@link StaticUtils#isDigit(char)}. |
| | | * |
| | | * @return Returns an array of test data. |