/** * Attempt to read a single entry. * * @throws Exception If the test failed unexpectedly. */ @Test(dependsOnMethods = {"testReadEntryEmptyStream"}) public void testReadEntrySingle() throws Exception { final String ldifString = "dn: cn=john, dc=foo, dc=com\n" + "objectClass: top\n" + "objectClass: person\n" + "cn: john\n" + "sn: smith\n"; LDIFReader reader = createLDIFReader(ldifString); try { Entry entry = reader.readEntry(); Assert.assertNotNull(entry); Assert.assertEquals(entry.getDN(), DN.decode("cn=john, dc=foo, dc=com")); Assert.assertTrue(entry.hasObjectClass(OC_TOP)); Assert.assertTrue(entry.hasObjectClass(OC_PERSON)); Assert.assertTrue(entry.hasValue(AT_CN, null, AttributeValues.create(AT_CN, "john"))); Assert.assertTrue(entry.hasValue(AT_SN, null, AttributeValues.create(AT_SN, "smith"))); Assert.assertNull(reader.readEntry()); Assert.assertEquals(reader.getEntriesIgnored(), 0); Assert.assertEquals(reader.getEntriesRead(), 1); Assert.assertEquals(reader.getEntriesRejected(), 0); Assert.assertEquals(reader.getLastEntryLineNumber(), 1); } finally { reader.close(); } }
/** * Attempt to read an entry containing a base64 line. * * @throws Exception If the test failed unexpectedly. */ @Test(dependsOnMethods = {"testReadEntrySingle"}) public void testReadEntryBase64() throws Exception { final String ldifString = "dn: cn=john, dc=foo, dc=com\n" + "objectClass: top\n" + "objectClass: person\n" + "cn: john\n" + "sn: smith\n" + "description:: b25jZSB1cG9uIGEgdGltZSBpbiB0aGUgd2VzdA==\n"; LDIFReader reader = createLDIFReader(ldifString); try { Entry entry = reader.readEntry(); Assert.assertNotNull(entry); Assert.assertTrue( entry.hasValue( AT_DESCR, null, AttributeValues.create(AT_DESCR, "once upon a time in the west"))); } finally { reader.close(); } }
/** * Ensures that password policy pwdPolicySubentry operational attribute reflects active password * policy for a given user entry. * * @throws Exception If an unexpected problem occurs. */ @Test() public void testPasswordPolicySubentryAttribute() throws Exception { PasswordPolicy defaultPolicy = DirectoryServer.getDefaultPasswordPolicy(); assertNotNull(defaultPolicy); Entry testEntry = DirectoryServer.getEntry(DN.decode("uid=rogasawara," + BASE)); assertNotNull(testEntry); AttributeType attrType = DirectoryServer.getAttributeType("pwdpolicysubentry"); // Make sure that default policy is in effect // for the user entry. assertTrue(testEntry.hasAttribute(attrType)); assertTrue( testEntry.hasValue( attrType, null, AttributeValues.create(attrType, defaultPolicy.getDN().toString()))); // Add new subentry policy with the // scope to apply to the user entry. Entry policyEntry = TestCaseUtils.makeEntry( "dn: cn=Temp Policy," + SUFFIX, "objectClass: top", "objectClass: pwdPolicy", "objectClass: subentry", "cn: Temp Policy", "subtreeSpecification: { base \"ou=people\" }", "pwdLockoutDuration: 300", "pwdMaxFailure: 3", "pwdMustChange: true", "pwdAttribute: userPassword"); InternalClientConnection connection = InternalClientConnection.getRootConnection(); AddOperation addOperation = connection.processAdd( policyEntry.getDN(), policyEntry.getObjectClasses(), policyEntry.getUserAttributes(), policyEntry.getOperationalAttributes()); assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS); assertNotNull(DirectoryServer.getEntry(policyEntry.getDN())); // Make sure just added policy is in effect. testEntry = DirectoryServer.getEntry(DN.decode("uid=rogasawara," + BASE)); assertNotNull(testEntry); assertTrue(testEntry.hasAttribute(attrType)); assertTrue( testEntry.hasValue( attrType, null, AttributeValues.create(attrType, "cn=Temp Policy," + SUFFIX))); // Remove subentry policy and make sure // default policy is in effect again. TestCaseUtils.deleteEntry(policyEntry.getDN()); testEntry = DirectoryServer.getEntry(DN.decode("uid=rogasawara," + BASE)); assertNotNull(testEntry); assertTrue(testEntry.hasAttribute(attrType)); assertTrue( testEntry.hasValue( attrType, null, AttributeValues.create(attrType, defaultPolicy.getDN().toString()))); }
/** * Process a delete attribute values that is conflicting with a previous modification. * * @param csn The CSN of the currently processed change * @param m the modification that is being processed * @param modifiedEntry the entry that is modified (before current mod) * @return false if there is nothing to do */ private boolean conflictDelete(CSN csn, Modification m, Entry modifiedEntry) { /* * We are processing a conflicting DELETE modification * * This code is written on the assumption that conflict are * rare. We therefore don't care much about the performance * However since it is rarely executed this code needs to be * as simple as possible to make sure that all paths are tested. * In this case the most simple seem to change the DELETE * in a REPLACE modification that keeps all values * more recent that the DELETE. * we are therefore going to change m into a REPLACE that will keep * all the values that have been updated after the DELETE time * If a value is present in the entry without any state information * it must be removed so we simply ignore them */ Attribute modAttr = m.getAttribute(); if (modAttr.isEmpty()) { /* * We are processing a DELETE attribute modification */ m.setModificationType(ModificationType.REPLACE); AttributeBuilder builder = new AttributeBuilder(modAttr, true); Iterator<AttrValueHistorical> it = valuesHist.keySet().iterator(); while (it.hasNext()) { AttrValueHistorical valInfo = it.next(); if (csn.isOlderThan(valInfo.getValueUpdateTime())) { /* * this value has been updated after this delete, therefore * this value must be kept */ builder.add(valInfo.getAttributeValue()); } else { /* * this value is going to be deleted, remove it from historical * information unless it is a Deleted attribute value that is * more recent than this DELETE */ if (csn.isNewerThanOrEqualTo(valInfo.getValueDeleteTime())) { it.remove(); } } } m.setAttribute(builder.toAttribute()); if (csn.isNewerThan(getDeleteTime())) { deleteTime = csn; } if (csn.isNewerThan(getLastUpdateTime())) { lastUpdateTime = csn; } } else { // we are processing DELETE of some attribute values AttributeBuilder builder = new AttributeBuilder(modAttr); for (ByteString val : modAttr) { boolean deleteIt = true; // true if the delete must be done boolean addedInCurrentOp = false; /* update historical information */ AttrValueHistorical valInfo = new AttrValueHistorical(val, null, csn); AttrValueHistorical oldValInfo = valuesHist.get(valInfo); if (oldValInfo != null) { /* this value already exist in the historical information */ if (csn.equals(oldValInfo.getValueUpdateTime())) { // This value was added earlier in the same operation // we need to keep the delete. addedInCurrentOp = true; } if (csn.isNewerThanOrEqualTo(oldValInfo.getValueDeleteTime()) && csn.isNewerThanOrEqualTo(oldValInfo.getValueUpdateTime())) { valuesHist.remove(oldValInfo); valuesHist.put(valInfo, valInfo); } else if (oldValInfo.isUpdate()) { deleteIt = false; } } else { valuesHist.remove(oldValInfo); valuesHist.put(valInfo, valInfo); } /* if the attribute value is not to be deleted * or if attribute value is not present suppress it from the * MOD to make sure the delete is going to succeed */ if (!deleteIt || (!modifiedEntry.hasValue(modAttr.getAttributeType(), modAttr.getOptions(), val) && !addedInCurrentOp)) { // this value was already deleted before and therefore // this should not be replayed. builder.remove(val); if (builder.isEmpty()) { // This was the last values in the set of values to be deleted. // this MOD must therefore be skipped. return false; } } } m.setAttribute(builder.toAttribute()); if (csn.isNewerThan(getLastUpdateTime())) { lastUpdateTime = csn; } } return true; }