/** * Updates the config file during the upgrade process. * * @param configPath The original path to the file. * @param filter The filter to select entries. Only useful for modify change type. * @param changeType The change type which must be applied to ldif lines. * @param ldifLines The change record ldif lines. For ADD change type, the first line must be the * dn. For DELETE change type, the first and only line must be the dn. * @throws IOException If an Exception occurs during the input output methods. * @return The changes number that have occurred. */ static int updateConfigFile( final String configPath, final Filter filter, final ChangeOperationType changeType, final String... ldifLines) throws IOException { final File original = new File(configPath); final File copyConfig = File.createTempFile("copyConfig", ".tmp", original.getParentFile()); int changeCount = 0; LDIFEntryReader entryReader = null; LDIFEntryWriter writer = null; try { final Schema schema = getUpgradeSchema(); entryReader = new LDIFEntryReader(new FileInputStream(configPath)).setSchema(schema); writer = new LDIFEntryWriter(new FileOutputStream(copyConfig)); writer.setWrapColumn(80); // Writes the header on the new file. writer.writeComment(INFO_CONFIG_FILE_HEADER.get()); writer.setWrapColumn(0); boolean entryAlreadyExist = false; DN ldifDN = null; if (filter == null && (changeType == ADD || changeType == DELETE)) { // The first line should start with dn: ldifDN = DN.valueOf(ldifLines[0].replaceFirst("dn: ", "")); } final Filter f = filter != null ? filter : Filter.alwaysFalse(); final Matcher matcher = f.matcher(schema); while (entryReader.hasNext()) { Entry entry = entryReader.readEntry(); final DN entryDN = entry.getName(); // Searching for the related entries if (changeType == MODIFY && matcher.matches(entry) == ConditionResult.TRUE) { try { final ModifyRequest mr = Requests.newModifyRequest(readLDIFLines(entryDN, changeType, ldifLines)); entry = Entries.modifyEntryPermissive(entry, mr.getModifications()); changeCount++; logger.debug( LocalizableMessage.raw("The following entry has been modified : %s", entryDN)); } catch (Exception ex) { logger.error(LocalizableMessage.raw(ex.getMessage())); } } if (entryDN.equals(ldifDN)) { logger.debug(LocalizableMessage.raw("Entry %s found", entryDN)); entryAlreadyExist = true; if (changeType == DELETE) { entry = null; changeCount++; logger.debug( LocalizableMessage.raw("The following entry has been deleted : %s", entryDN)); } } if (entry != null) { writer.writeEntry(entry); } } if (changeType == ADD && !entryAlreadyExist) { final AddRequest ar = Requests.newAddRequest(ldifLines); writer.writeEntry(ar); logger.debug( LocalizableMessage.raw( "Entry successfully added %s in %s", ldifDN, original.getAbsolutePath())); changeCount++; } } catch (Exception ex) { throw new IOException(ex.getMessage()); } finally { // The reader and writer must be close before renaming files. // Otherwise it causes exceptions under windows OS. StaticUtils.close(entryReader, writer); } try { // Renaming the file, overwriting previous one. rename(copyConfig, new File(configPath)); } catch (IOException e) { logger.error(LocalizableMessage.raw(e.getMessage())); deleteRecursively(original); throw e; } return changeCount; }
/** Test EntryChangeNotificationControl. */ @Test(dataProvider = "entryChangeNotificationControl") public void checkEntryChangeNotificationControlTest( boolean isCritical, long changeNumber, String dnString) throws Exception { // Test constructor EntryChangeNotificationControl // (PersistentSearchChangeType changeType,long changeNumber) PersistentSearchChangeType[] types = PersistentSearchChangeType.values(); EntryChangeNotificationControl ecnc = null; EntryChangeNotificationControl newEcnc; ByteStringBuilder bsb = new ByteStringBuilder(); ASN1Writer writer = ASN1.getWriter(bsb); for (PersistentSearchChangeType type : types) { ecnc = new EntryChangeNotificationControl(type, changeNumber); assertNotNull(ecnc); assertEquals(OID_ENTRY_CHANGE_NOTIFICATION, ecnc.getOID()); assertEquals(changeNumber, ecnc.getChangeNumber()); assertEquals(type, ecnc.getChangeType()); assertNull(ecnc.getPreviousDN()); assertEquals(false, ecnc.isCritical()); checkEntryChangeNotificationControlToString(ecnc); // also check encode/decode try { bsb.clear(); ecnc.write(writer); LDAPControl control = LDAPReader.readControl(ASN1.getReader(bsb)); newEcnc = EntryChangeNotificationControl.DECODER.decode(control.isCritical(), control.getValue()); assertNotNull(newEcnc); assertEquals(ecnc.getOID(), newEcnc.getOID()); assertEquals(ecnc.getChangeNumber(), newEcnc.getChangeNumber()); assertEquals(ecnc.getChangeType(), newEcnc.getChangeType()); assertNull(newEcnc.getPreviousDN()); assertEquals(ecnc.isCritical(), newEcnc.isCritical()); } catch (DirectoryException e) { fail(); } } // Test constructor EntryChangeNotificationControl // (PersistentSearchChangeType changeType, DN previousDN, long // changeNumber) DN dn = DN.valueOf(dnString); for (PersistentSearchChangeType type : types) { ecnc = new EntryChangeNotificationControl(type, dn, changeNumber); assertNotNull(ecnc); assertEquals(OID_ENTRY_CHANGE_NOTIFICATION, ecnc.getOID()); assertEquals(changeNumber, ecnc.getChangeNumber()); assertEquals(type, ecnc.getChangeType()); assertEquals(dn, ecnc.getPreviousDN()); assertEquals(false, ecnc.isCritical()); checkEntryChangeNotificationControlToString(ecnc); // also check encode/decode try { bsb.clear(); ecnc.write(writer); LDAPControl control = LDAPReader.readControl(ASN1.getReader(bsb)); newEcnc = EntryChangeNotificationControl.DECODER.decode(control.isCritical(), control.getValue()); assertNotNull(newEcnc); assertEquals(ecnc.getOID(), newEcnc.getOID()); assertEquals(ecnc.getChangeNumber(), newEcnc.getChangeNumber()); assertEquals(ecnc.getChangeType(), newEcnc.getChangeType()); assertEquals(ecnc.getPreviousDN(), newEcnc.getPreviousDN()); assertEquals(ecnc.isCritical(), newEcnc.isCritical()); } catch (DirectoryException e) { assertNotEquals( type.compareTo(MODIFY_DN), 0, "couldn't decode a control with previousDN not null and type=modDN"); } } // Test constructor EntryChangeNotificationControl(boolean // isCritical, PersistentSearchChangeType changeType, // DN previousDN, long changeNumber) for (PersistentSearchChangeType type : types) { ecnc = new EntryChangeNotificationControl(isCritical, type, dn, changeNumber); assertNotNull(ecnc); assertEquals(OID_ENTRY_CHANGE_NOTIFICATION, ecnc.getOID()); assertEquals(changeNumber, ecnc.getChangeNumber()); assertEquals(type, ecnc.getChangeType()); assertEquals(dn, ecnc.getPreviousDN()); assertEquals(isCritical, ecnc.isCritical()); checkEntryChangeNotificationControlToString(ecnc); // also check encode/decode try { bsb.clear(); ecnc.write(writer); LDAPControl control = LDAPReader.readControl(ASN1.getReader(bsb)); newEcnc = EntryChangeNotificationControl.DECODER.decode(control.isCritical(), control.getValue()); assertNotNull(newEcnc); assertEquals(ecnc.getOID(), newEcnc.getOID()); assertEquals(ecnc.getChangeNumber(), newEcnc.getChangeNumber()); assertEquals(ecnc.getChangeType(), newEcnc.getChangeType()); assertEquals(ecnc.getPreviousDN(), newEcnc.getPreviousDN()); assertEquals(ecnc.isCritical(), newEcnc.isCritical()); } catch (DirectoryException e) { assertNotEquals( type.compareTo(PersistentSearchChangeType.MODIFY_DN), 0, "couldn't decode a control with previousDN not null and type=modDN"); } } // Check error on decode try { LDAPControl control = new LDAPControl(OID_ENTRY_CHANGE_NOTIFICATION, isCritical); newEcnc = EntryChangeNotificationControl.DECODER.decode(control.isCritical(), control.getValue()); fail(); } catch (DirectoryException expected) { assertEquals(expected.getMessage(), CANNOT_DECODE_CHANGE_NOTIF_CONTROL_NO_VALUE); } }
/** Tests the maximum persistent search limit imposed by the server. */ @Test public void testMaxPSearch() throws Exception { TestCaseUtils.initializeTestBackend(true); // Modify the configuration to allow only 1 concurrent persistent search. InternalClientConnection conn = getRootConnection(); LDAPAttribute attr = new LDAPAttribute("ds-cfg-max-psearches", "1"); ArrayList<RawModification> mods = new ArrayList<>(); mods.add(new LDAPModification(ModificationType.REPLACE, attr)); ModifyOperation modifyOperation = conn.processModify(ByteString.valueOf("cn=config"), mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); // Create a persistent search request. Set<PersistentSearchChangeType> changeTypes = EnumSet.of(ADD, DELETE, MODIFY, MODIFY_DN); SearchRequest request = newSearchRequest(DN.valueOf("o=test"), SearchScope.BASE_OBJECT) .setTypesOnly(true) .addAttribute("cn") .addControl(new PersistentSearchControl(changeTypes, true, true)); final InternalSearchOperation search = conn.processSearch(request); Thread t = new Thread( new Runnable() { @Override public void run() { try { search.run(); } catch (Exception ex) { } } }, "Persistent Search Test"); t.start(); t.join(2000); // Create a persistent search request. final String[] args = { "-D", "cn=Directory Manager", "-w", "password", "-h", "127.0.0.1", "-p", String.valueOf(TestCaseUtils.getServerLdapPort()), "-b", "o=test", "-s", "sub", "-C", "ps:add:true:true", "--noPropertiesFile", "(objectClass=*)" }; assertEquals(LDAPSearch.mainSearch(args, false, true, null, System.err), 11); // cancel the persisting persistent search. search.cancel(new CancelRequest(true, LocalizableMessage.EMPTY)); }
@Test(dataProvider = "findDnKeyParentData") public void testFindDnKeyParent(String dn, int expectedLength) throws Exception { ensureServerIsUpAndRunning(); ByteString dnKey = DnKeyFormat.dnToDNKey(DN.valueOf(dn), 0); assertThat(DnKeyFormat.findDNKeyParent(dnKey)).isEqualTo(expectedLength); }