This fixes serveral issues LDIF import and VLV features:
- Added the ability to use both a backend ID and include branch arguments for LDIF imports
(Issue 1971)
- Fixed incorrect search scope enum in the VLV index configuration
- Added unit tests for partial LDIF imports
- Fixed issue where using overlapping include branches during an import would result in a ConcurrentModificationException (Issue 2039)
| | |
| | | Search the base object only. |
| | | </adm:synopsis> |
| | | </adm:value> |
| | | <adm:value name="single-object"> |
| | | <adm:value name="single-level"> |
| | | <adm:synopsis> |
| | | Search subordinate objects to the base object but not include |
| | | the base object itself. |
| | | Search immediate children of the base object but not include |
| | | any of their descendants and the base object itself. |
| | | </adm:synopsis> |
| | | </adm:value> |
| | | <adm:value name="subordinate-subtree"> |
| | |
| | | * Close the attribute index. |
| | | * |
| | | * @throws DatabaseException if a JE database error occurs while |
| | | * openning the index. |
| | | * closing the index. |
| | | */ |
| | | public void close() throws DatabaseException |
| | | { |
| | |
| | | } |
| | | |
| | | // Remove any overlapping include branches. |
| | | for(DN includeDN : includeBranches) |
| | | Iterator<DN> includeBranchIterator = includeBranches.iterator(); |
| | | while(includeBranchIterator.hasNext()) |
| | | { |
| | | DN includeDN = includeBranchIterator.next(); |
| | | boolean keep = true; |
| | | for(DN dn : includeBranches) |
| | | { |
| | |
| | | } |
| | | if(!keep) |
| | | { |
| | | includeBranches.remove(includeDN); |
| | | includeBranchIterator.remove(); |
| | | } |
| | | } |
| | | |
| | | // Remvoe any exclude branches that are not are not under a include |
| | | // branch since they will be migrated as part of the existing entries |
| | | // outside of the include branches anyways. |
| | | for(DN excludeDN : excludeBranches) |
| | | Iterator<DN> excludeBranchIterator = excludeBranches.iterator(); |
| | | while(excludeBranchIterator.hasNext()) |
| | | { |
| | | DN excludeDN = excludeBranchIterator.next(); |
| | | boolean keep = false; |
| | | for(DN includeDN : includeBranches) |
| | | { |
| | |
| | | } |
| | | if(!keep) |
| | | { |
| | | excludeBranches.remove(excludeDN); |
| | | excludeBranchIterator.remove(); |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | this.count = new AtomicInteger(0); |
| | | this.config.addChangeListener(this); |
| | | } |
| | | |
| | | /** |
| | |
| | | } |
| | | |
| | | /** |
| | | * Close the VLV index. |
| | | * |
| | | * @throws DatabaseException if a JE database error occurs while |
| | | * closing the index. |
| | | */ |
| | | public void close() throws DatabaseException |
| | | { |
| | | super.close(); |
| | | this.config.removeChangeListener(this); |
| | | } |
| | | |
| | | /** |
| | | * Update the vlvIndex for a new entry. |
| | | * |
| | | * @param txn A database transaction, or null if none is required. |
| | |
| | | if(adminActionRequired) |
| | | { |
| | | trusted = false; |
| | | int msgID = MSGID_JEB_INDEX_ADD_REQUIRES_REBUILD; |
| | | String message = getMessage(msgID, name); |
| | | messages.add(message); |
| | | try |
| | | { |
| | | state.putIndexTrustState(null, this, false); |
| | |
| | | "index entry limit in index %s. This index must be " + |
| | | "rebuilt before it can use the new limit"); |
| | | registerMessage(MSGID_JEB_INDEX_ADD_REQUIRES_REBUILD, |
| | | "Index %s is currently operating in a degraded read-only " + |
| | | "state and must be rebuilt before it can used"); |
| | | "Due to changes in the configuration, index %s is " + |
| | | "currently operating in a degraded state and must be " + |
| | | "rebuilt before it can used"); |
| | | registerMessage(MSGID_JEB_INDEX_CORRUPT_REQUIRES_REBUILD, |
| | | "An error occurred while reading from index %s. The " + |
| | | "index seems to be corrupt and is now operating in " + |
| | | "a degraded read-only state. The index must be rebuilt " + |
| | | "a degraded state. The index must be rebuilt " + |
| | | "before it can return to normal operation"); |
| | | registerMessage(MSGID_JEB_IMPORT_BACKEND_ONLINE, |
| | | "The backend must be disabled before the import process" + |
| | |
| | | clearBackend = TaskUtils.getBoolean(attrList, false); |
| | | |
| | | // Make sure that either the "includeBranchStrings" argument or the |
| | | // "backendID" argument was provided, but not both. |
| | | if(!includeBranchStrings.isEmpty()) |
| | | { |
| | | if(backendID != null) |
| | | { |
| | | int msgID = MSGID_LDIFIMPORT_CONFLICTING_OPTIONS; |
| | | String message = getMessage(msgID, typeIncludeBranch.getNameOrOID(), |
| | | typeBackendID.getNameOrOID()); |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message, |
| | | msgID); |
| | | } |
| | | } |
| | | else if(backendID == null) |
| | | // "backendID" argument was provided. |
| | | if(includeBranchStrings.isEmpty() && backendID == null) |
| | | { |
| | | int msgID = MSGID_LDIFIMPORT_MISSING_BACKEND_ARGUMENT; |
| | | String message = getMessage(msgID, typeIncludeBranch.getNameOrOID(), |
| | |
| | | msgID); |
| | | } |
| | | |
| | | Backend backend = null; |
| | | ArrayList<DN> defaultIncludeBranches; |
| | | ArrayList<DN> excludeBranches = |
| | | new ArrayList<DN>(excludeBranchStrings.size()); |
| | | ArrayList<DN> includeBranches = |
| | | new ArrayList<DN>(includeBranchStrings.size()); |
| | | |
| | | for (String s : includeBranchStrings) |
| | | { |
| | | DN includeBranch; |
| | | try |
| | | { |
| | | includeBranch = DN.decode(s); |
| | | } |
| | | catch (DirectoryException de) |
| | | { |
| | | int msgID = MSGID_LDIFIMPORT_CANNOT_DECODE_INCLUDE_BASE; |
| | | String message = getMessage(msgID, s, de.getErrorMessage()); |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message, |
| | | msgID); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | int msgID = MSGID_LDIFIMPORT_CANNOT_DECODE_INCLUDE_BASE; |
| | | String message = getMessage(msgID, s, getExceptionMessage(e)); |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message, |
| | | msgID); |
| | | } |
| | | |
| | | if(! includeBranches.contains(includeBranch)) |
| | | { |
| | | includeBranches.add(includeBranch); |
| | | } |
| | | } |
| | | for (String s : excludeBranchStrings) |
| | | { |
| | | DN excludeBranch; |
| | | try |
| | | { |
| | | excludeBranch = DN.decode(s); |
| | | } |
| | | catch (DirectoryException de) |
| | | { |
| | | int msgID = MSGID_LDIFIMPORT_CANNOT_DECODE_EXCLUDE_BASE; |
| | | String message = getMessage(msgID, s, de.getErrorMessage()); |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message, |
| | | msgID); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | int msgID = MSGID_LDIFIMPORT_CANNOT_DECODE_EXCLUDE_BASE; |
| | | String message = getMessage(msgID, s, getExceptionMessage(e)); |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message, |
| | | msgID); |
| | | } |
| | | |
| | | if (! excludeBranches.contains(excludeBranch)) |
| | | { |
| | | excludeBranches.add(excludeBranch); |
| | | } |
| | | } |
| | | |
| | | for (String filterString : excludeFilterStrings) |
| | | { |
| | | try |
| | | { |
| | | SearchFilter.createFilterFromString(filterString); |
| | | } |
| | | catch (DirectoryException de) |
| | | { |
| | | int msgID = MSGID_LDIFIMPORT_CANNOT_PARSE_EXCLUDE_FILTER; |
| | | String message = getMessage(msgID, filterString, |
| | | de.getErrorMessage()); |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message, |
| | | msgID); |
| | | } |
| | | } |
| | | |
| | | for (String filterString : includeFilterStrings) |
| | | { |
| | | try |
| | | { |
| | | SearchFilter.createFilterFromString(filterString); |
| | | } |
| | | catch (DirectoryException de) |
| | | { |
| | | int msgID = MSGID_LDIFIMPORT_CANNOT_PARSE_INCLUDE_FILTER; |
| | | String message = getMessage(msgID, filterString, |
| | | de.getErrorMessage()); |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message, |
| | | msgID); |
| | | } |
| | | } |
| | | |
| | | if(backendID != null) |
| | | { |
| | | Backend backend = DirectoryServer.getBackend(backendID); |
| | | backend = DirectoryServer.getBackend(backendID); |
| | | if (backend == null) |
| | | { |
| | | int msgID = MSGID_LDIFIMPORT_NO_BACKENDS_FOR_ID; |
| | | String message = getMessage(msgID, backendID); |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message, |
| | | msgID); |
| | | msgID); |
| | | } |
| | | else if (! backend.supportsLDIFImport()) |
| | | { |
| | |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message, |
| | | msgID); |
| | | } |
| | | // Make sure that if the "backendID" argument was provided and the |
| | | // "append" option was not provided, the "clearBackend" argument was also |
| | | // provided if there are more then one baseDNs for the backend being |
| | | // imported. |
| | | else if(!append && backend.getBaseDNs().length > 1 && !clearBackend) |
| | | // Make sure that if the "backendID" argument was provided, no include |
| | | // base was included, and the "append" ption was not provided, the |
| | | // "clearBackend" argument was also provided if there are more then one |
| | | // baseDNs for the backend being imported. |
| | | else if(!append && includeBranchStrings.isEmpty() && |
| | | backend.getBaseDNs().length > 1 && !clearBackend) |
| | | { |
| | | StringBuilder builder = new StringBuilder(); |
| | | for(DN dn : backend.getBaseDNs()) |
| | |
| | | else |
| | | { |
| | | // Find the backend that includes all the branches. |
| | | Backend backend = null; |
| | | for (String s : includeBranchStrings) |
| | | for(DN includeBranch : includeBranches) |
| | | { |
| | | DN includeBranch; |
| | | try |
| | | { |
| | | includeBranch = DN.decode(s); |
| | | } |
| | | catch (DirectoryException de) |
| | | { |
| | | int msgID = MSGID_LDIFIMPORT_CANNOT_DECODE_INCLUDE_BASE; |
| | | String message = getMessage(msgID, s, de.getErrorMessage()); |
| | | logError(ErrorLogCategory.BACKEND, ErrorLogSeverity.SEVERE_ERROR, |
| | | message, msgID); |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message, |
| | | msgID); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | int msgID = MSGID_LDIFIMPORT_CANNOT_DECODE_INCLUDE_BASE; |
| | | String message = getMessage(msgID, s, getExceptionMessage(e)); |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message, |
| | | msgID); |
| | | } |
| | | |
| | | Backend locatedBackend = DirectoryServer.getBackend(includeBranch); |
| | | if(locatedBackend != null) |
| | | { |
| | |
| | | { |
| | | // The include branches span across multiple backends. |
| | | int msgID = MSGID_LDIFIMPORT_INVALID_INCLUDE_BASE; |
| | | String message = getMessage(msgID, s, backend.getBackendID()); |
| | | String message = getMessage(msgID, |
| | | includeBranch.toNormalizedString(), |
| | | backend.getBackendID()); |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, |
| | | message, msgID); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | // Make sure the selected backend will handle all the include branches |
| | | defaultIncludeBranches = new ArrayList<DN>(backend.getBaseDNs().length); |
| | | for (DN dn : backend.getBaseDNs()) |
| | | { |
| | | defaultIncludeBranches.add(dn); |
| | | } |
| | | |
| | | for(DN includeBranch : includeBranches) |
| | | { |
| | | if (! Backend.handlesEntry(includeBranch, defaultIncludeBranches, |
| | | excludeBranches)) |
| | | { |
| | | int msgID = MSGID_LDIFIMPORT_INVALID_INCLUDE_BASE; |
| | | String message = getMessage(msgID, includeBranch.toNormalizedString(), |
| | | backend.getBackendID()); |
| | | throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message, |
| | | msgID); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | |
| | | // Get the backend into which the LDIF should be imported. |
| | | Backend backend = null; |
| | | ArrayList<DN> defaultIncludeBranches; |
| | | ArrayList<DN> excludeBranches = new ArrayList<DN>(); |
| | | ArrayList<DN> includeBranches = new ArrayList<DN>(); |
| | | ArrayList<DN> excludeBranches = |
| | | new ArrayList<DN>(excludeBranchStrings.size()); |
| | | ArrayList<DN> includeBranches = |
| | | new ArrayList<DN>(includeBranchStrings.size()); |
| | | |
| | | |
| | | includeBranches = new ArrayList<DN>(includeBranchStrings.size()); |
| | | for (String s : includeBranchStrings) |
| | | { |
| | | DN includeBranch; |
| | |
| | | return TaskState.STOPPED_BY_ERROR; |
| | | } |
| | | |
| | | includeBranches.add(includeBranch); |
| | | if(! includeBranches.contains(includeBranch)) |
| | | { |
| | | includeBranches.add(includeBranch); |
| | | } |
| | | } |
| | | |
| | | if(backendID != null) |
| | |
| | | message, msgID); |
| | | return TaskState.STOPPED_BY_ERROR; |
| | | } |
| | | // Make sure that if the "backendID" argument was provided and the |
| | | // "append" option was not provided, the "clearBackend" argument was also |
| | | // provided if there are more then one baseDNs for the backend being |
| | | // imported. |
| | | else if(!append && backend.getBaseDNs().length > 1 && !clearBackend) |
| | | // Make sure that if the "backendID" argument was provided, no include |
| | | // base was included, and the "append" ption was not provided, the |
| | | // "clearBackend" argument was also provided if there are more then one |
| | | // baseDNs for the backend being imported. |
| | | else if(!append && includeBranches.isEmpty() && |
| | | backend.getBaseDNs().length > 1 && !clearBackend) |
| | | { |
| | | StringBuilder builder = new StringBuilder(); |
| | | builder.append(backend.getBaseDNs()[0].toNormalizedString()); |
| | |
| | | { |
| | | includeBranches = defaultIncludeBranches; |
| | | } |
| | | else |
| | | { |
| | | // Make sure the selected backend will handle all the include branches |
| | | for(DN includeBranch : includeBranches) |
| | | { |
| | | if (! Backend.handlesEntry(includeBranch, defaultIncludeBranches, |
| | | excludeBranches)) |
| | | { |
| | | int msgID = MSGID_LDIFIMPORT_INVALID_INCLUDE_BASE; |
| | | String message = getMessage(msgID, includeBranch.toNormalizedString(), |
| | | backend.getBackendID()); |
| | | logError(ErrorLogCategory.BACKEND, ErrorLogSeverity.SEVERE_ERROR, |
| | | message, msgID); |
| | | return TaskState.STOPPED_BY_ERROR; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // Create the LDIF import configuration to use when reading the LDIF. |
| | | ArrayList<String> fileList = new ArrayList<String>(ldifFiles); |
| | |
| | | } |
| | | |
| | | // Make sure that either the "includeBranchStrings" argument or the |
| | | // "backendID" argument was provided, but not both. |
| | | if(includeBranchStrings.isPresent()) |
| | | { |
| | | if(backendID.isPresent()) |
| | | { |
| | | int msgID = MSGID_LDIFIMPORT_CONFLICTING_OPTIONS; |
| | | String message = getMessage(msgID, |
| | | includeBranchStrings.getLongIdentifier(), |
| | | backendID.getLongIdentifier()); |
| | | err.println(wrapText(message, MAX_LINE_WIDTH)); |
| | | return 1; |
| | | } |
| | | } |
| | | else if(! backendID.isPresent()) |
| | | // "backendID" argument was provided. |
| | | if(!includeBranchStrings.isPresent() && !backendID.isPresent()) |
| | | { |
| | | int msgID = MSGID_LDIFIMPORT_MISSING_BACKEND_ARGUMENT; |
| | | String message = getMessage(msgID, |
| | |
| | | } |
| | | } |
| | | |
| | | // Make sure that if the "backendID" argument was provided and the "append" |
| | | // option was not provided, the "clearBackend" argument was also |
| | | // provided if there are more then one baseDNs for the backend being |
| | | // imported. |
| | | if(backendID.isPresent() && !append.isPresent() && |
| | | defaultIncludeBranches.size() > 1 && !clearBackend.isPresent()) |
| | | // Make sure that if the "backendID" argument was provided, no include base |
| | | // was included, and the "append" ption was not provided, the "clearBackend" |
| | | // argument was also provided if there are more then one baseDNs for the |
| | | // backend being imported. |
| | | if(backendID.isPresent() && !includeBranchStrings.isPresent() && |
| | | !append.isPresent() && defaultIncludeBranches.size() > 1 && |
| | | !clearBackend.isPresent()) |
| | | { |
| | | StringBuilder builder = new StringBuilder(); |
| | | builder.append(backend.getBaseDNs()[0].toNormalizedString()); |
| | |
| | | "objectclass: organizationalUnit\n" + |
| | | "ou: People\n" + |
| | | "\n" + |
| | | "dn: ou=Others,ou=People,dc=importtest,dc=com\n" + |
| | | "objectclass: top\n" + |
| | | "objectclass: organizationalUnit\n" + |
| | | "ou: Others\n" + |
| | | "\n" + |
| | | "dn: dc=importtest1,dc=com\n" + |
| | | "objectclass: top\n" + |
| | | "objectclass: domain\n" + |
| | |
| | | |
| | | if(baseDN.toString().equals("dc=importtest,dc=com")) |
| | | { |
| | | assertEquals(entryContainer.getEntryCount(), 4); |
| | | assertEquals(entryContainer.getEntryCount(), 5); |
| | | assertTrue(entryContainer.entryExists(baseDN)); |
| | | assertTrue(entryContainer.entryExists(DN.decode("ou=People,dc=importtest,dc=com"))); |
| | | assertTrue(entryContainer.entryExists(DN.decode("ou=Others,ou=People,dc=importtest,dc=com"))); |
| | | assertTrue(entryContainer.entryExists(DN.decode("uid=user.0,ou=People,dc=importtest,dc=com"))); |
| | | assertTrue(entryContainer.entryExists(DN.decode("uid=user.539,ou=People,dc=importtest,dc=com"))); |
| | | |
| | |
| | | } |
| | | |
| | | @Test(dependsOnMethods = "testImportAll") |
| | | public void testImportPartial() throws Exception |
| | | { |
| | | ArrayList<String> fileList = new ArrayList<String>(); |
| | | fileList.add(homeDirName + File.separator + "top.ldif"); |
| | | fileList.add(homeDirName + File.separator + "entries1.ldif"); |
| | | |
| | | ArrayList<DN> includeBranches = new ArrayList<DN>(); |
| | | includeBranches.add(DN.decode("ou=People,dc=importtest,dc=com")); |
| | | ArrayList<DN> excludeBranches = new ArrayList<DN>(); |
| | | excludeBranches.add(DN.decode("ou=Others,ou=People,dc=importtest,dc=com")); |
| | | |
| | | ByteArrayOutputStream rejectedEntries = new ByteArrayOutputStream(); |
| | | ByteArrayOutputStream skippedEntries = new ByteArrayOutputStream(); |
| | | LDIFImportConfig importConfig = new LDIFImportConfig(fileList); |
| | | importConfig.setAppendToExistingData(false); |
| | | importConfig.setReplaceExistingEntries(false); |
| | | importConfig.setValidateSchema(true); |
| | | importConfig.writeRejectedEntries(rejectedEntries); |
| | | importConfig.writeSkippedEntries(skippedEntries); |
| | | importConfig.setIncludeBranches(includeBranches); |
| | | importConfig.setExcludeBranches(excludeBranches); |
| | | |
| | | be=(BackendImpl) DirectoryServer.getBackend(beID); |
| | | TaskUtils.disableBackend(beID); |
| | | try |
| | | { |
| | | be.importLDIF(importConfig); |
| | | } |
| | | finally |
| | | { |
| | | TaskUtils.enableBackend(beID); |
| | | } |
| | | |
| | | be=(BackendImpl) DirectoryServer.getBackend(beID); |
| | | RootContainer rootContainer = be.getRootContainer(); |
| | | EntryContainer entryContainer; |
| | | |
| | | assertTrue(rejectedEntries.size() <= 0); |
| | | for(DN baseDN : baseDNs) |
| | | { |
| | | entryContainer = rootContainer.getEntryContainer(baseDN); |
| | | entryContainer.sharedLock.lock(); |
| | | try |
| | | { |
| | | assertNotNull(entryContainer); |
| | | |
| | | if(baseDN.toString().equals("dc=importtest,dc=com")) |
| | | { |
| | | assertEquals(entryContainer.getEntryCount(), 5); |
| | | assertTrue(entryContainer.entryExists(baseDN)); |
| | | assertTrue(entryContainer.entryExists(DN.decode("ou=People,dc=importtest,dc=com"))); |
| | | assertTrue(entryContainer.entryExists(DN.decode("ou=Others,ou=People,dc=importtest,dc=com"))); |
| | | assertTrue(entryContainer.entryExists(DN.decode("uid=user.0,ou=People,dc=importtest,dc=com"))); |
| | | assertTrue(entryContainer.entryExists(DN.decode("uid=user.539,ou=People,dc=importtest,dc=com"))); |
| | | |
| | | VerifyConfig verifyConfig = new VerifyConfig(); |
| | | verifyConfig.setBaseDN(baseDN); |
| | | |
| | | Entry statEntry=bldStatEntry(""); |
| | | be=(BackendImpl) DirectoryServer.getBackend(beID); |
| | | be.verifyBackend(verifyConfig, statEntry); |
| | | assertEquals(getStatEntryCount(statEntry, errorCount), 0); |
| | | } |
| | | else if(baseDN.toString().equals("dc=importtest1,dc=com")) |
| | | { |
| | | assertEquals(entryContainer.getEntryCount(), 3); |
| | | assertTrue(entryContainer.entryExists(baseDN)); |
| | | assertTrue(entryContainer.entryExists(DN.decode("uid=user.446,dc=importtest1,dc=com"))); |
| | | assertTrue(entryContainer.entryExists(DN.decode("uid=user.362,dc=importtest1,dc=com"))); |
| | | |
| | | VerifyConfig verifyConfig = new VerifyConfig(); |
| | | verifyConfig.setBaseDN(baseDN); |
| | | |
| | | Entry statEntry=bldStatEntry(""); |
| | | be=(BackendImpl) DirectoryServer.getBackend(beID); |
| | | be.verifyBackend(verifyConfig, statEntry); |
| | | assertEquals(getStatEntryCount(statEntry, errorCount), 0); |
| | | } |
| | | } |
| | | finally |
| | | { |
| | | entryContainer.sharedLock.unlock(); |
| | | |
| | | } |
| | | } |
| | | } |
| | | |
| | | @Test(dependsOnMethods = "testImportPartial") |
| | | public void testImportReplaceExisting() throws Exception |
| | | { |
| | | ByteArrayOutputStream rejectedEntries = new ByteArrayOutputStream(); |
| | |
| | | { |
| | | if(baseDN.toString().equals("dc=importtest,dc=com")) |
| | | { |
| | | assertEquals(entryContainer.getEntryCount(), 4); |
| | | assertEquals(entryContainer.getEntryCount(), 5); |
| | | assertTrue(entryContainer.entryExists(baseDN)); |
| | | assertTrue(entryContainer.entryExists(DN.decode("ou=People,dc=importtest,dc=com"))); |
| | | assertTrue(entryContainer.entryExists(DN.decode("uid=user.0,ou=People,dc=importtest,dc=com"))); |
| | |
| | | } |
| | | } |
| | | |
| | | @Test(dependsOnMethods = "testImportAll") |
| | | @Test(dependsOnMethods = "testImportPartial") |
| | | public void testImportNotReplaceExisting() throws Exception |
| | | { |
| | | ByteArrayOutputStream rejectedEntries = new ByteArrayOutputStream(); |
| | |
| | | assertTrue(rejectedEntries.toString().contains("uid=user.446,dc=importtest1,dc=com")); |
| | | } |
| | | |
| | | @Test(dependsOnMethods = "testImportAll") |
| | | @Test(dependsOnMethods = "testImportPartial") |
| | | public void testImportSkip() throws Exception |
| | | { |
| | | ArrayList<DN> excludeBranches = new ArrayList<DN>(); |
| | |
| | | import org.testng.annotations.AfterClass; |
| | | import org.testng.annotations.DataProvider; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.core.AddOperation; |
| | | import org.opends.server.TestCaseUtils; |
| | | import org.opends.server.protocols.internal.InternalClientConnection; |
| | | import org.opends.server.api.TestTaskListener; |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.ObjectClass; |
| | | import org.opends.server.types.ResultCode; |
| | | import org.opends.server.backends.task.TaskState; |
| | | |
| | | import static org.testng.Assert.*; |
| | |
| | | public Object[][] createData() throws Exception |
| | | { |
| | | return new Object[][] { |
| | | // A fairly simple, valid import task. |
| | | // A fairly simple, valid import task using backend ID. |
| | | { |
| | | TestCaseUtils.makeEntry( |
| | | "dn: ds-task-id=" + UUID.randomUUID() + |
| | |
| | | ), |
| | | TaskState.COMPLETED_SUCCESSFULLY |
| | | }, |
| | | // A fairly simple, valid import task using include base DN. |
| | | { |
| | | TestCaseUtils.makeEntry( |
| | | "dn: ds-task-id=" + UUID.randomUUID() + |
| | | ",cn=Scheduled Tasks,cn=Tasks", |
| | | "objectclass: top", |
| | | "objectclass: ds-task", |
| | | "objectclass: ds-task-import", |
| | | "ds-task-class-name: org.opends.server.tasks.ImportTask", |
| | | "ds-task-import-include-branch: dc=example,dc=com", |
| | | "ds-task-import-ldif-file: " + ldifFile.getPath(), |
| | | "ds-task-import-reject-file: " + rejectFile.getPath(), |
| | | "ds-task-import-overwrite-rejects: TRUE", |
| | | "ds-task-import-exclude-attribute: description", |
| | | "ds-task-import-exclude-filter: (st=CA)", |
| | | "ds-task-import-exclude-branch: o=exclude,dc=example,dc=com" |
| | | ), |
| | | TaskState.COMPLETED_SUCCESSFULLY |
| | | }, |
| | | // A complex, valid import task. |
| | | { |
| | | TestCaseUtils.makeEntry( |
| | |
| | | ), |
| | | TaskState.COMPLETED_SUCCESSFULLY |
| | | }, |
| | | // LDIF file does not exist. |
| | | // A partial, valid import task. |
| | | { |
| | | TestCaseUtils.makeEntry( |
| | | "dn: ds-task-id=" + UUID.randomUUID() + |
| | |
| | | "objectclass: ds-task", |
| | | "objectclass: ds-task-import", |
| | | "ds-task-class-name: org.opends.server.tasks.ImportTask", |
| | | "ds-task-import-ldif-file: doesnotexist", |
| | | "ds-task-import-backend-id: userRoot" |
| | | ), |
| | | TaskState.STOPPED_BY_ERROR |
| | | }, |
| | | // Invalid exclude filter. |
| | | { |
| | | TestCaseUtils.makeEntry( |
| | | "dn: ds-task-id=" + UUID.randomUUID() + |
| | | ",cn=Scheduled Tasks,cn=Tasks", |
| | | "objectclass: top", |
| | | "objectclass: ds-task", |
| | | "objectclass: ds-task-import", |
| | | "ds-task-class-name: org.opends.server.tasks.ImportTask", |
| | | "ds-task-import-include-branch: ou=people,dc=example,dc=com", |
| | | "ds-task-import-ldif-file: " + ldifFile.getPath(), |
| | | "ds-task-import-backend-id: userRoot", |
| | | "ds-task-import-exclude-filter: ()" |
| | | "ds-task-import-reject-file: " + rejectFile.getPath(), |
| | | "ds-task-import-overwrite-rejects: TRUE", |
| | | "ds-task-import-exclude-attribute: description", |
| | | "ds-task-import-exclude-filter: (st=CA)", |
| | | "ds-task-import-exclude-branch: o=exclude,dc=example,dc=com" |
| | | ), |
| | | TaskState.STOPPED_BY_ERROR |
| | | }, |
| | | // Invalid include filter. |
| | | { |
| | | TestCaseUtils.makeEntry( |
| | | "dn: ds-task-id=" + UUID.randomUUID() + |
| | | ",cn=Scheduled Tasks,cn=Tasks", |
| | | "objectclass: top", |
| | | "objectclass: ds-task", |
| | | "objectclass: ds-task-import", |
| | | "ds-task-class-name: org.opends.server.tasks.ImportTask", |
| | | "ds-task-import-ldif-file: " + ldifFile.getPath(), |
| | | "ds-task-import-backend-id: userRoot", |
| | | "ds-task-import-include-filter: ()" |
| | | ), |
| | | TaskState.STOPPED_BY_ERROR |
| | | TaskState.COMPLETED_SUCCESSFULLY |
| | | }, |
| | | // Backend id does not exist. |
| | | { |
| | |
| | | "objectclass: ds-task", |
| | | "objectclass: ds-task-import", |
| | | "ds-task-class-name: org.opends.server.tasks.ImportTask", |
| | | "ds-task-import-ldif-file: " + ldifFile.getPath(), |
| | | "ds-task-import-backend-id: doesnotexist" |
| | | ), |
| | | TaskState.STOPPED_BY_ERROR |
| | | }, |
| | | // Backend does not support import. |
| | | { |
| | | TestCaseUtils.makeEntry( |
| | | "dn: ds-task-id=" + UUID.randomUUID() + |
| | | ",cn=Scheduled Tasks,cn=Tasks", |
| | | "objectclass: top", |
| | | "objectclass: ds-task", |
| | | "objectclass: ds-task-import", |
| | | "ds-task-class-name: org.opends.server.tasks.ImportTask", |
| | | "ds-task-import-ldif-file: " + ldifFile.getPath(), |
| | | "ds-task-import-backend-id: monitor" |
| | | ), |
| | | TaskState.STOPPED_BY_ERROR |
| | | }, |
| | | // Backend does not handle include branch. |
| | | { |
| | | TestCaseUtils.makeEntry( |
| | | "dn: ds-task-id=" + UUID.randomUUID() + |
| | | ",cn=Scheduled Tasks,cn=Tasks", |
| | | "objectclass: top", |
| | | "objectclass: ds-task", |
| | | "objectclass: ds-task-import", |
| | | "ds-task-class-name: org.opends.server.tasks.ImportTask", |
| | | "ds-task-import-ldif-file: " + ldifFile.getPath(), |
| | | "ds-task-import-backend-id: userRoot", |
| | | "ds-task-import-include-branch: dc=opends,dc=org" |
| | | "ds-task-import-ldif-file: doesnotexist", |
| | | "ds-task-import-backend-id: userRoot" |
| | | ), |
| | | TaskState.STOPPED_BY_ERROR |
| | | }, |
| | |
| | | } |
| | | |
| | | /** |
| | | * Import and export tasks bad test data provider. |
| | | * |
| | | * @return The array of tasks test data. The first column is a task entry |
| | | * and the second column is the expected completed task state. |
| | | */ |
| | | @DataProvider(name = "badimportexport") |
| | | public Object[][] createBadData() throws Exception |
| | | { |
| | | return new Object[][] { |
| | | // Invalid exclude filter. |
| | | { |
| | | TestCaseUtils.makeEntry( |
| | | "dn: ds-task-id=" + UUID.randomUUID() + |
| | | ",cn=Scheduled Tasks,cn=Tasks", |
| | | "objectclass: top", |
| | | "objectclass: ds-task", |
| | | "objectclass: ds-task-import", |
| | | "ds-task-class-name: org.opends.server.tasks.ImportTask", |
| | | "ds-task-import-ldif-file: " + ldifFile.getPath(), |
| | | "ds-task-import-backend-id: userRoot", |
| | | "ds-task-import-exclude-filter: ()" |
| | | ), |
| | | ResultCode.UNWILLING_TO_PERFORM |
| | | }, |
| | | // Invalid include filter. |
| | | { |
| | | TestCaseUtils.makeEntry( |
| | | "dn: ds-task-id=" + UUID.randomUUID() + |
| | | ",cn=Scheduled Tasks,cn=Tasks", |
| | | "objectclass: top", |
| | | "objectclass: ds-task", |
| | | "objectclass: ds-task-import", |
| | | "ds-task-class-name: org.opends.server.tasks.ImportTask", |
| | | "ds-task-import-ldif-file: " + ldifFile.getPath(), |
| | | "ds-task-import-backend-id: userRoot", |
| | | "ds-task-import-include-filter: ()" |
| | | ), |
| | | ResultCode.UNWILLING_TO_PERFORM |
| | | }, |
| | | // Backend id does not exist. |
| | | { |
| | | TestCaseUtils.makeEntry( |
| | | "dn: ds-task-id=" + UUID.randomUUID() + |
| | | ",cn=Scheduled Tasks,cn=Tasks", |
| | | "objectclass: top", |
| | | "objectclass: ds-task", |
| | | "objectclass: ds-task-import", |
| | | "ds-task-class-name: org.opends.server.tasks.ImportTask", |
| | | "ds-task-import-ldif-file: " + ldifFile.getPath(), |
| | | "ds-task-import-backend-id: doesnotexist" |
| | | ), |
| | | ResultCode.UNWILLING_TO_PERFORM |
| | | }, |
| | | // Backend does not support import. |
| | | { |
| | | TestCaseUtils.makeEntry( |
| | | "dn: ds-task-id=" + UUID.randomUUID() + |
| | | ",cn=Scheduled Tasks,cn=Tasks", |
| | | "objectclass: top", |
| | | "objectclass: ds-task", |
| | | "objectclass: ds-task-import", |
| | | "ds-task-class-name: org.opends.server.tasks.ImportTask", |
| | | "ds-task-import-ldif-file: " + ldifFile.getPath(), |
| | | "ds-task-import-backend-id: monitor" |
| | | ), |
| | | ResultCode.UNWILLING_TO_PERFORM |
| | | }, |
| | | // Backend does not handle include branch. |
| | | { |
| | | TestCaseUtils.makeEntry( |
| | | "dn: ds-task-id=" + UUID.randomUUID() + |
| | | ",cn=Scheduled Tasks,cn=Tasks", |
| | | "objectclass: top", |
| | | "objectclass: ds-task", |
| | | "objectclass: ds-task-import", |
| | | "ds-task-class-name: org.opends.server.tasks.ImportTask", |
| | | "ds-task-import-ldif-file: " + ldifFile.getPath(), |
| | | "ds-task-import-backend-id: userRoot", |
| | | "ds-task-import-include-branch: dc=opends,dc=org" |
| | | ), |
| | | ResultCode.UNWILLING_TO_PERFORM |
| | | }, |
| | | // Not specifying a destination. |
| | | { |
| | | TestCaseUtils.makeEntry( |
| | | "dn: ds-task-id=" + UUID.randomUUID() + |
| | | ",cn=Scheduled Tasks,cn=Tasks", |
| | | "objectclass: top", |
| | | "objectclass: ds-task", |
| | | "objectclass: ds-task-import", |
| | | "ds-task-class-name: org.opends.server.tasks.ImportTask", |
| | | "ds-task-import-ldif-file: " + ldifFile.getPath() |
| | | ), |
| | | ResultCode.UNWILLING_TO_PERFORM |
| | | } |
| | | }; |
| | | } |
| | | |
| | | /** |
| | | * Test that various import and export task definitions complete with the |
| | | * expected state. |
| | | * @param taskEntry The task entry. |
| | | * @param expectedState The expected completion state of the task. |
| | | */ |
| | | @Test(enabled = false, dataProvider = "importexport", groups = "slow") |
| | | @Test(dataProvider = "importexport", groups = "slow") |
| | | public void testImportExport(Entry taskEntry, TaskState expectedState) |
| | | throws Exception |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Add a task definition and check that it completes with the expected state. |
| | | * @param taskEntry The task entry. |
| | | * @param resultCode The expected result code of the task add. |
| | | * @throws Exception If the test fails. |
| | | */ |
| | | @Test(dataProvider = "badimportexport") |
| | | public void testBadTask(Entry taskEntry, ResultCode resultCode) |
| | | throws Exception |
| | | { |
| | | InternalClientConnection connection = |
| | | InternalClientConnection.getRootConnection(); |
| | | |
| | | // Add the task. |
| | | AddOperation addOperation = |
| | | connection.processAdd(taskEntry.getDN(), |
| | | taskEntry.getObjectClasses(), |
| | | taskEntry.getUserAttributes(), |
| | | taskEntry.getOperationalAttributes()); |
| | | assertEquals(addOperation.getResultCode(), resultCode); |
| | | } |
| | | |
| | | } |
| | |
| | | String configFilePath ; |
| | | private String homeDirName; |
| | | private String beID; |
| | | private String baseDN = "dc=example,dc=com"; |
| | | |
| | | /** |
| | | * Ensures that the ldif file is created with the entry. |
| | |
| | | assertEntry(attr,true); |
| | | } |
| | | |
| | | /** |
| | | * Tests a simple Import LDIF using base DN with none of the attributes |
| | | * excluded or included. It is expected to import the entry(ies) |
| | | * with all the attributes in the ldif file. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test |
| | | public void testImportDefaultBaseDN() throws Exception |
| | | { |
| | | |
| | | File reject = File.createTempFile("reject", ".ldif"); |
| | | String rejectFilePath = reject.getAbsolutePath(); |
| | | String[] args = |
| | | { |
| | | "-f", DirectoryServer.getConfigFile(), |
| | | "-l", ldifFilePath, |
| | | "-b", baseDN, |
| | | "-R", rejectFilePath |
| | | }; |
| | | assertEquals(ImportLDIF.mainImportLDIF(args,false,System.out,System.err),0); |
| | | //Reject file should be empty. |
| | | assertRejectedFile(reject,true); |
| | | //check the presence of some random attributes. |
| | | Attribute[] attr = |
| | | { |
| | | new Attribute ("description", |
| | | "This is the description for Aaccf Amar"), |
| | | new Attribute("mail","user.0@example.com"), |
| | | new Attribute ("creatorsname", "cn=Import") , |
| | | new Attribute("modifiersname","cn=Import") |
| | | } ; |
| | | assertEntry(attr,true); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |