opends/src/server/org/opends/server/api/AccessControlHandler.java
@@ -225,7 +225,7 @@ * @return {@code true} if the operation should be allowed by the * access control configuration, or {@code false} if not. */ public abstract boolean isAllowed(ModifyDNOperation public abstract boolean isAllowed(LocalBackendModifyDNOperation modifyDNOperation); opends/src/server/org/opends/server/api/AccessLogPublisher.java
@@ -341,7 +341,7 @@ * DN request. */ public abstract void logModifyDNRequest( ModifyDNOperation modifyDNOperation); ModifyDNOperationBasis modifyDNOperation); @@ -355,7 +355,7 @@ * DN response. */ public abstract void logModifyDNResponse( ModifyDNOperation modifyDNOperation); ModifyDNOperationBasis modifyDNOperation); opends/src/server/org/opends/server/authorization/dseecompat/AciHandler.java
@@ -1025,7 +1025,8 @@ * @param newRDN The new RDN component. * @return True if access is allowed. */ private boolean aciCheckRDNs(ModifyDNOperation operation, RDN oldRDN, private boolean aciCheckRDNs(LocalBackendModifyDNOperation operation, RDN oldRDN, RDN newRDN) { boolean ret; @@ -1078,7 +1079,8 @@ * @throws DirectoryException If a problem occurs while trying to * retrieve the new superior entry. */ private boolean aciCheckSuperiorEntry(DN superiorDN, ModifyDNOperation op) private boolean aciCheckSuperiorEntry(DN superiorDN, LocalBackendModifyDNOperation op) throws DirectoryException { boolean ret=false; Lock entryLock = null; @@ -1115,7 +1117,7 @@ * @return True if access is allowed. * */ public boolean isAllowed(ModifyDNOperation operation) { public boolean isAllowed(LocalBackendModifyDNOperation operation) { boolean ret=true; DN newSuperiorDN; RDN oldRDN=operation.getOriginalEntry().getDN().getRDN(); opends/src/server/org/opends/server/authorization/dseecompat/AciLDAPOperationContainer.java
@@ -104,7 +104,8 @@ * @param rights The rights of the modify DN operation. * @param entry The entry to evalauted for this modify DN. */ public AciLDAPOperationContainer(ModifyDNOperation operation, int rights, public AciLDAPOperationContainer(LocalBackendModifyDNOperation operation, int rights, Entry entry) { super(operation, rights, entry); } opends/src/server/org/opends/server/core/DefaultAccessControlHandler.java
@@ -160,7 +160,7 @@ * {@inheritDoc} */ @Override public boolean isAllowed(ModifyDNOperation modifyDNOperation) public boolean isAllowed(LocalBackendModifyDNOperation modifyDNOperation) { return true; } opends/src/server/org/opends/server/core/ModifyDNOperation.java
@@ -26,231 +26,20 @@ */ package org.opends.server.core; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.concurrent.locks.Lock; import org.opends.server.api.Backend; import org.opends.server.api.ChangeNotificationListener; import org.opends.server.api.ClientConnection; import org.opends.server.api.SynchronizationProvider; import org.opends.server.api.plugin.PostOperationPluginResult; import org.opends.server.api.plugin.PreOperationPluginResult; import org.opends.server.api.plugin.PreParsePluginResult; import org.opends.server.controls.LDAPAssertionRequestControl; import org.opends.server.controls.LDAPPreReadRequestControl; import org.opends.server.controls.LDAPPreReadResponseControl; import org.opends.server.controls.LDAPPostReadRequestControl; import org.opends.server.controls.LDAPPostReadResponseControl; import org.opends.server.controls.ProxiedAuthV1Control; import org.opends.server.controls.ProxiedAuthV2Control; import org.opends.server.protocols.asn1.ASN1OctetString; import org.opends.server.types.AbstractOperation; import org.opends.server.types.Attribute; import org.opends.server.types.AttributeType; import org.opends.server.types.AttributeValue; import org.opends.server.types.ByteString; import org.opends.server.types.CancelledOperationException; import org.opends.server.types.CancelRequest; import org.opends.server.types.CancelResult; import org.opends.server.types.Control; import org.opends.server.types.DirectoryException; import org.opends.server.types.DisconnectReason; import org.opends.server.types.DN; import org.opends.server.types.Entry; import org.opends.server.types.ErrorLogCategory; import org.opends.server.types.ErrorLogSeverity; import org.opends.server.types.LDAPException; import org.opends.server.types.LockManager; import org.opends.server.types.Modification; import org.opends.server.types.ModificationType; import org.opends.server.types.OperationType; import org.opends.server.types.Privilege; import org.opends.server.types.Operation; import org.opends.server.types.RDN; import org.opends.server.types.ResultCode; import org.opends.server.types.SearchFilter; import org.opends.server.types.SearchResultEntry; import org.opends.server.types.SynchronizationProviderResult; import org.opends.server.types.operation.PostOperationModifyDNOperation; import org.opends.server.types.operation.PostResponseModifyDNOperation; import org.opends.server.types.operation.PreOperationModifyDNOperation; import org.opends.server.types.operation.PreParseModifyDNOperation; import static org.opends.server.core.CoreConstants.*; import static org.opends.server.loggers.AccessLogger.*; import org.opends.server.types.DebugLogLevel; import static org.opends.server.loggers.ErrorLogger.*; import static org.opends.server.loggers.debug.DebugLogger.*; import org.opends.server.loggers.debug.DebugLogger; import org.opends.server.loggers.debug.DebugTracer; import static org.opends.server.messages.CoreMessages.*; import static org.opends.server.messages.MessageHandler.*; import static org.opends.server.util.ServerConstants.*; import static org.opends.server.util.StaticUtils.*; /** * This class defines an operation that may be used to alter the DN of an entry * in the Directory Server. * This interface defines an operation used to move an entry in * the Directory Server. */ public class ModifyDNOperation extends AbstractOperation implements PreParseModifyDNOperation, PreOperationModifyDNOperation, PostOperationModifyDNOperation, PostResponseModifyDNOperation public interface ModifyDNOperation extends Operation { /** * The tracer object for the debug logger. */ private static final DebugTracer TRACER = DebugLogger.getTracer(); // Indicates whether to delete the old RDN value from the entry. private boolean deleteOldRDN; // The raw, unprocessed current DN of the entry as included in the request // from the client. private ByteString rawEntryDN; // The raw, unprocessed newRDN as included in the request from the client. private ByteString rawNewRDN; // The raw, unprocessed newSuperior as included in the request from the // client. private ByteString rawNewSuperior; // The cancel request issued for this modify DN operation. private CancelRequest cancelRequest; // The current DN of the entry. private DN entryDN; // The new parent for the entry. private DN newSuperior; // The proxied authorization target DN for this operation. private DN proxiedAuthorizationDN; // The current entry, before it is renamed. private Entry currentEntry; // The new entry, as it will appear after it has been renamed. private Entry newEntry; // The set of response controls for this modify DN operation. private List<Control> responseControls; // The set of modifications applied to attributes in the entry in the course // of processing the modify DN. private List<Modification> modifications; // The change number that has been assigned to this operation. private long changeNumber; // The new RDN for the entry. private RDN newRDN; /** * Creates a new modify DN operation with the provided information. * * @param clientConnection The client connection with which this operation * is associated. * @param operationID The operation ID for this operation. * @param messageID The message ID of the request with which this * operation is associated. * @param requestControls The set of controls included in the request. * @param rawEntryDN The raw, unprocessed entry DN as included in the * client request. * @param rawNewRDN The raw, unprocessed newRDN as included in the * client request. * @param deleteOldRDN Indicates whether to delete the old RDN value * from the entry. * @param rawNewSuperior The raw, unprocessed newSuperior as included in * the client request. */ public ModifyDNOperation(ClientConnection clientConnection, long operationID, int messageID, List<Control> requestControls, ByteString rawEntryDN, ByteString rawNewRDN, boolean deleteOldRDN, ByteString rawNewSuperior) { super(clientConnection, operationID, messageID, requestControls); this.rawEntryDN = rawEntryDN; this.rawNewRDN = rawNewRDN; this.deleteOldRDN = deleteOldRDN; this.rawNewSuperior = rawNewSuperior; entryDN = null; newRDN = null; newSuperior = null; responseControls = new ArrayList<Control>(); cancelRequest = null; modifications = null; changeNumber = -1; currentEntry = null; newEntry = null; } /** * Creates a new modify DN operation with the provided information. * * @param clientConnection The client connection with which this operation * is associated. * @param operationID The operation ID for this operation. * @param messageID The message ID of the request with which this * operation is associated. * @param requestControls The set of controls included in the request. * @param entryDN The current entry DN for this modify DN * operation. * @param newRDN The new RDN for this modify DN operation. * @param deleteOldRDN Indicates whether to delete the old RDN value * from the entry. * @param newSuperior The newSuperior DN for this modify DN operation. */ public ModifyDNOperation(ClientConnection clientConnection, long operationID, int messageID, List<Control> requestControls, DN entryDN, RDN newRDN, boolean deleteOldRDN, DN newSuperior) { super(clientConnection, operationID, messageID, requestControls); this.entryDN = entryDN; this.newRDN = newRDN; this.deleteOldRDN = deleteOldRDN; this.newSuperior = newSuperior; rawEntryDN = new ASN1OctetString(entryDN.toString()); rawNewRDN = new ASN1OctetString(newRDN.toString()); if (newSuperior == null) { rawNewSuperior = null; } else { rawNewSuperior = new ASN1OctetString(newSuperior.toString()); } responseControls = new ArrayList<Control>(); cancelRequest = null; modifications = null; changeNumber = -1; currentEntry = null; newEntry = null; } /** * Retrieves the raw, unprocessed entry DN as included in the client request. @@ -259,12 +48,7 @@ * * @return The raw, unprocessed entry DN as included in the client request. */ public final ByteString getRawEntryDN() { return rawEntryDN; } public ByteString getRawEntryDN(); /** * Specifies the raw, unprocessed entry DN as included in the client request. @@ -273,13 +57,7 @@ * @param rawEntryDN The raw, unprocessed entry DN as included in the client * request. */ public final void setRawEntryDN(ByteString rawEntryDN) { this.rawEntryDN = rawEntryDN; entryDN = null; } public void setRawEntryDN(ByteString rawEntryDN); /** @@ -290,12 +68,7 @@ * @return The DN of the entry to rename, or <CODE>null</CODE> if the raw * entry DN has not yet been processed. */ public final DN getEntryDN() { return entryDN; } public DN getEntryDN(); /** * Retrieves the raw, unprocessed newRDN as included in the request from the @@ -305,12 +78,7 @@ * @return The raw, unprocessed newRDN as included in the request from the * client. */ public final ByteString getRawNewRDN() { return rawNewRDN; } public ByteString getRawNewRDN(); /** * Specifies the raw, unprocessed newRDN as included in the request from the @@ -320,14 +88,7 @@ * @param rawNewRDN The raw, unprocessed newRDN as included in the request * from the client. */ public final void setRawNewRDN(ByteString rawNewRDN) { this.rawNewRDN = rawNewRDN; newRDN = null; } public void setRawNewRDN(ByteString rawNewRDN); /** * Retrieves the new RDN to use for the entry. This should not be called by @@ -337,11 +98,7 @@ * @return The new RDN to use for the entry, or <CODE>null</CODE> if the raw * newRDN has not yet been processed. */ public final RDN getNewRDN() { return newRDN; } public RDN getNewRDN(); /** @@ -350,12 +107,7 @@ * @return <CODE>true</CODE> if the current RDN value should be removed from * the entry, or <CODE>false</CODE> if not. */ public final boolean deleteOldRDN() { return deleteOldRDN; } public boolean deleteOldRDN(); /** * Specifies whether the current RDN value should be removed from the entry. @@ -363,12 +115,7 @@ * @param deleteOldRDN Specifies whether the current RDN value should be * removed from the entry. */ public final void setDeleteOldRDN(boolean deleteOldRDN) { this.deleteOldRDN = deleteOldRDN; } public void setDeleteOldRDN(boolean deleteOldRDN); /** * Retrieves the raw, unprocessed newSuperior from the client request. This @@ -378,12 +125,7 @@ * @return The raw, unprocessed newSuperior from the client request, or * <CODE>null</CODE> if there is none. */ public final ByteString getRawNewSuperior() { return rawNewSuperior; } public ByteString getRawNewSuperior(); /** * Specifies the raw, unprocessed newSuperior for this modify DN operation, as @@ -393,14 +135,7 @@ * @param rawNewSuperior The raw, unprocessed newSuperior as provided in the * request from the client. */ public final void setRawNewSuperior(ByteString rawNewSuperior) { this.rawNewSuperior = rawNewSuperior; newSuperior = null; } public void setRawNewSuperior(ByteString rawNewSuperior); /** * Retrieves the newSuperior DN for the entry. This should not be called by @@ -412,12 +147,15 @@ * no newSuperior DN for this request or if the raw newSuperior has * not yet been processed. */ public final DN getNewSuperior() { return newSuperior; } public DN getNewSuperior(); /** * Retrieves the new DN for the entry. * * @return The new DN for the entry, or <CODE>null</CODE> if there is * neither newRDN, nor entryDN for this request. */ public DN getNewDN(); /** * Retrieves the set of modifications applied to attributes of the target @@ -436,12 +174,7 @@ * of the modify DN processing, or <CODE>null</CODE> if that * information is not yet available (e.g., during pre-parse plugins). */ public final List<Modification> getModifications() { return modifications; } public List<Modification> getModifications(); /** * Adds the provided modification to the set of modifications to be applied @@ -451,12 +184,7 @@ * @param modification The modification to add to the set of modifications * to apply to the entry. */ public final void addModification(Modification modification) { modifications.add(modification); } public void addModification(Modification modification); /** * Retrieves the current entry, before it is renamed. This will not be @@ -466,11 +194,7 @@ * @return The current entry, or <CODE>null</CODE> if it is not yet * available. */ public final Entry getOriginalEntry() { return currentEntry; } public Entry getOriginalEntry(); /** @@ -481,10 +205,7 @@ * @return The updated entry, or <CODE>null</CODE> if it is not yet * available. */ public final Entry getUpdatedEntry() { return newEntry; } public Entry getUpdatedEntry(); /** * Retrieves the change number that has been assigned to this operation. @@ -493,11 +214,7 @@ * if none has been assigned yet or if there is no applicable * synchronization mechanism in place that uses change numbers. */ public final long getChangeNumber() { return changeNumber; } public long getChangeNumber(); /** @@ -507,143 +224,7 @@ * @param changeNumber The change number that has been assigned to this * operation by the synchronization mechanism. */ public final void setChangeNumber(long changeNumber) { this.changeNumber = changeNumber; } /** * {@inheritDoc} */ @Override() public final OperationType getOperationType() { // Note that no debugging will be done in this method because it is a likely // candidate for being called by the logging subsystem. return OperationType.MODIFY_DN; } /** * {@inheritDoc} */ @Override() public final void disconnectClient(DisconnectReason disconnectReason, boolean sendNotification, String message, int messageID) { // Before calling clientConnection.disconnect, we need to mark this // operation as cancelled so that the attempt to cancel it later won't cause // an unnecessary delay. setCancelResult(CancelResult.CANCELED); clientConnection.disconnect(disconnectReason, sendNotification, message, messageID); } /** * {@inheritDoc} */ @Override() public final String[][] getRequestLogElements() { // Note that no debugging will be done in this method because it is a likely // candidate for being called by the logging subsystem. String newSuperiorStr; if (rawNewSuperior == null) { newSuperiorStr = null; } else { newSuperiorStr = rawNewSuperior.stringValue(); } return new String[][] { new String[] { LOG_ELEMENT_ENTRY_DN, String.valueOf(rawEntryDN) }, new String[] { LOG_ELEMENT_NEW_RDN, String.valueOf(newRDN) }, new String[] { LOG_ELEMENT_DELETE_OLD_RDN, String.valueOf(deleteOldRDN) }, new String[] { LOG_ELEMENT_NEW_SUPERIOR, newSuperiorStr } }; } /** * {@inheritDoc} */ @Override() public final String[][] getResponseLogElements() { // Note that no debugging will be done in this method because it is a likely // candidate for being called by the logging subsystem. String resultCode = String.valueOf(getResultCode().getIntValue()); String errorMessage; StringBuilder errorMessageBuffer = getErrorMessage(); if (errorMessageBuffer == null) { errorMessage = null; } else { errorMessage = errorMessageBuffer.toString(); } String matchedDNStr; DN matchedDN = getMatchedDN(); if (matchedDN == null) { matchedDNStr = null; } else { matchedDNStr = matchedDN.toString(); } String referrals; List<String> referralURLs = getReferralURLs(); if ((referralURLs == null) || referralURLs.isEmpty()) { referrals = null; } else { StringBuilder buffer = new StringBuilder(); Iterator<String> iterator = referralURLs.iterator(); buffer.append(iterator.next()); while (iterator.hasNext()) { buffer.append(", "); buffer.append(iterator.next()); } referrals = buffer.toString(); } String processingTime = String.valueOf(getProcessingTime()); return new String[][] { new String[] { LOG_ELEMENT_RESULT_CODE, resultCode }, new String[] { LOG_ELEMENT_ERROR_MESSAGE, errorMessage }, new String[] { LOG_ELEMENT_MATCHED_DN, matchedDNStr }, new String[] { LOG_ELEMENT_REFERRAL_URLS, referrals }, new String[] { LOG_ELEMENT_PROCESSING_TIME, processingTime } }; } public void setChangeNumber(long changeNumber); /** @@ -654,1572 +235,17 @@ * authorization has been requested, or {@code null} if proxied * authorization has not been requested. */ public DN getProxiedAuthorizationDN() { return proxiedAuthorizationDN; } public DN getProxiedAuthorizationDN(); /** * {@inheritDoc} * Sets the proxied authorization DN for this operation if proxied * authorization has been requested. * * @param dn The proxied authorization DN for this operation if proxied * authorization has been requested, or {@code null} if proxied * authorization has not been requested. */ @Override() public final List<Control> getResponseControls() { return responseControls; } /** * {@inheritDoc} */ @Override() public final void addResponseControl(Control control) { responseControls.add(control); } /** * {@inheritDoc} */ @Override() public final void removeResponseControl(Control control) { responseControls.remove(control); } /** * Performs the work of actually processing this operation. This * should include all processing for the operation, including * invoking plugins, logging messages, performing access control, * managing synchronization, and any other work that might need to * be done in the course of processing. */ public final void run() { setResultCode(ResultCode.UNDEFINED); // Get the plugin config manager that will be used for invoking plugins. PluginConfigManager pluginConfigManager = DirectoryServer.getPluginConfigManager(); boolean skipPostOperation = false; // Start the processing timer. setProcessingStartTime(); // Check for and handle a request to cancel this operation. if (cancelRequest != null) { indicateCancelled(cancelRequest); setProcessingStopTime(); return; } // Create a labeled block of code that we can break out of if a problem is // detected. modifyDNProcessing: { // Invoke the pre-parse modify DN plugins. PreParsePluginResult preParseResult = pluginConfigManager.invokePreParseModifyDNPlugins(this); if (preParseResult.connectionTerminated()) { // There's no point in continuing with anything. Log the request and // result and return. setResultCode(ResultCode.CANCELED); int msgID = MSGID_CANCELED_BY_PREPARSE_DISCONNECT; appendErrorMessage(getMessage(msgID)); setProcessingStopTime(); logModifyDNRequest(this); logModifyDNResponse(this); pluginConfigManager.invokePostResponseModifyDNPlugins(this); return; } else if (preParseResult.sendResponseImmediately()) { skipPostOperation = true; logModifyDNRequest(this); break modifyDNProcessing; } else if (preParseResult.skipCoreProcessing()) { skipPostOperation = false; break modifyDNProcessing; } // Log the modify DN request message. logModifyDNRequest(this); // Check for and handle a request to cancel this operation. if (cancelRequest != null) { indicateCancelled(cancelRequest); setProcessingStopTime(); logModifyDNResponse(this); pluginConfigManager.invokePostResponseModifyDNPlugins(this); return; } // Process the entry DN, newRDN, and newSuperior elements from their raw // forms as provided by the client to the forms required for the rest of // the modify DN processing. try { if (entryDN == null) { entryDN = DN.decode(rawEntryDN); } } catch (DirectoryException de) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, de); } setResultCode(de.getResultCode()); appendErrorMessage(de.getErrorMessage()); skipPostOperation = true; break modifyDNProcessing; } try { if (newRDN == null) { newRDN = RDN.decode(rawNewRDN.stringValue()); } } catch (DirectoryException de) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, de); } setResultCode(de.getResultCode()); appendErrorMessage(de.getErrorMessage()); skipPostOperation = true; break modifyDNProcessing; } if (rawNewSuperior == null) { newSuperior = null; } else { try { if (newSuperior == null) { newSuperior = DN.decode(rawNewSuperior); } } catch (DirectoryException de) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, de); } setResultCode(de.getResultCode()); appendErrorMessage(de.getErrorMessage()); skipPostOperation = true; break modifyDNProcessing; } } // Construct the new DN to use for the entry. DN parentDN; if (newSuperior == null) { parentDN = entryDN.getParentDNInSuffix(); } else { parentDN = newSuperior; } if ((parentDN == null) || parentDN.isNullDN()) { setResultCode(ResultCode.UNWILLING_TO_PERFORM); appendErrorMessage(getMessage(MSGID_MODDN_NO_PARENT, String.valueOf(entryDN))); break modifyDNProcessing; } 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. Backend currentBackend = DirectoryServer.getBackend(entryDN); if (currentBackend == null) { setResultCode(ResultCode.NO_SUCH_OBJECT); appendErrorMessage(getMessage(MSGID_MODDN_NO_BACKEND_FOR_CURRENT_ENTRY, String.valueOf(entryDN))); break modifyDNProcessing; } Backend newBackend = DirectoryServer.getBackend(newDN); if (newBackend == null) { setResultCode(ResultCode.NO_SUCH_OBJECT); appendErrorMessage(getMessage(MSGID_MODDN_NO_BACKEND_FOR_NEW_ENTRY, String.valueOf(entryDN), String.valueOf(newDN))); break modifyDNProcessing; } else if (! currentBackend.equals(newBackend)) { setResultCode(ResultCode.UNWILLING_TO_PERFORM); appendErrorMessage(getMessage(MSGID_MODDN_DIFFERENT_BACKENDS, String.valueOf(entryDN), String.valueOf(newDN))); break modifyDNProcessing; } // Check for and handle a request to cancel this operation. if (cancelRequest != null) { indicateCancelled(cancelRequest); setProcessingStopTime(); logModifyDNResponse(this); pluginConfigManager.invokePostResponseModifyDNPlugins(this); return; } // Acquire write locks for the current and new DN. Lock currentLock = null; for (int i=0; i < 3; i++) { currentLock = LockManager.lockWrite(entryDN); if (currentLock != null) { break; } } if (currentLock == null) { setResultCode(DirectoryServer.getServerErrorResultCode()); appendErrorMessage(getMessage(MSGID_MODDN_CANNOT_LOCK_CURRENT_DN, String.valueOf(entryDN))); skipPostOperation = true; break modifyDNProcessing; } Lock newLock = null; try { for (int i=0; i < 3; i++) { newLock = LockManager.lockWrite(newDN); if (newLock != null) { break; } } } catch (Exception e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } LockManager.unlock(entryDN, currentLock); if (newLock != null) { LockManager.unlock(newDN, newLock); } setResultCode(DirectoryServer.getServerErrorResultCode()); appendErrorMessage(getMessage(MSGID_MODDN_EXCEPTION_LOCKING_NEW_DN, String.valueOf(entryDN), String.valueOf(newDN), getExceptionMessage(e))); skipPostOperation = true; break modifyDNProcessing; } if (newLock == null) { LockManager.unlock(entryDN, currentLock); setResultCode(DirectoryServer.getServerErrorResultCode()); appendErrorMessage(getMessage(MSGID_MODDN_CANNOT_LOCK_NEW_DN, String.valueOf(entryDN), String.valueOf(newDN))); skipPostOperation = true; break modifyDNProcessing; } try { // Check for and handle a request to cancel this operation. if (cancelRequest != null) { indicateCancelled(cancelRequest); setProcessingStopTime(); logModifyDNResponse(this); pluginConfigManager.invokePostResponseModifyDNPlugins(this); return; } // Get the current entry from the appropriate backend. If it doesn't // exist, then fail. try { currentEntry = currentBackend.getEntry(entryDN); } catch (DirectoryException de) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, de); } setResultCode(de.getResultCode()); appendErrorMessage(de.getErrorMessage()); setMatchedDN(de.getMatchedDN()); setReferralURLs(de.getReferralURLs()); break modifyDNProcessing; } if (currentEntry == null) { // See if one of the entry's ancestors exists. parentDN = entryDN.getParentDNInSuffix(); while (parentDN != null) { try { if (DirectoryServer.entryExists(parentDN)) { setMatchedDN(parentDN); break; } } catch (Exception e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } break; } parentDN = parentDN.getParentDNInSuffix(); } setResultCode(ResultCode.NO_SUCH_OBJECT); appendErrorMessage(getMessage(MSGID_MODDN_NO_CURRENT_ENTRY, String.valueOf(entryDN))); break modifyDNProcessing; } // Invoke any conflict resolution processing that might be needed by the // synchronization provider. for (SynchronizationProvider provider : DirectoryServer.getSynchronizationProviders()) { try { SynchronizationProviderResult result = provider.handleConflictResolution(this); if (! result.continueOperationProcessing()) { break modifyDNProcessing; } } catch (DirectoryException de) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, de); } logError(ErrorLogCategory.SYNCHRONIZATION, ErrorLogSeverity.SEVERE_ERROR, MSGID_MODDN_SYNCH_CONFLICT_RESOLUTION_FAILED, getConnectionID(), getOperationID(), getExceptionMessage(de)); setResponseData(de); break modifyDNProcessing; } } // Check to see if there are any controls in the request. If so, then // see if there is any special processing required. boolean noOp = false; LDAPPreReadRequestControl preReadRequest = null; LDAPPostReadRequestControl postReadRequest = null; List<Control> requestControls = getRequestControls(); if ((requestControls != null) && (! requestControls.isEmpty())) { for (int i=0; i < requestControls.size(); i++) { Control c = requestControls.get(i); String oid = c.getOID(); if (oid.equals(OID_LDAP_ASSERTION)) { LDAPAssertionRequestControl assertControl; if (c instanceof LDAPAssertionRequestControl) { assertControl = (LDAPAssertionRequestControl) c; } else { try { assertControl = LDAPAssertionRequestControl.decodeControl(c); requestControls.set(i, assertControl); } catch (LDAPException le) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, le); } setResultCode(ResultCode.valueOf(le.getResultCode())); appendErrorMessage(le.getMessage()); break modifyDNProcessing; } } try { // FIXME -- We need to determine whether the current user has // permission to make this determination. SearchFilter filter = assertControl.getSearchFilter(); if (! filter.matchesEntry(currentEntry)) { setResultCode(ResultCode.ASSERTION_FAILED); appendErrorMessage(getMessage(MSGID_MODDN_ASSERTION_FAILED, String.valueOf(entryDN))); break modifyDNProcessing; } } catch (DirectoryException de) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, de); } setResultCode(ResultCode.PROTOCOL_ERROR); int msgID = MSGID_MODDN_CANNOT_PROCESS_ASSERTION_FILTER; appendErrorMessage(getMessage(msgID, String.valueOf(entryDN), de.getErrorMessage())); break modifyDNProcessing; } } else if (oid.equals(OID_LDAP_NOOP_OPENLDAP_ASSIGNED)) { noOp = true; } else if (oid.equals(OID_LDAP_READENTRY_PREREAD)) { if (c instanceof LDAPAssertionRequestControl) { preReadRequest = (LDAPPreReadRequestControl) c; } else { try { preReadRequest = LDAPPreReadRequestControl.decodeControl(c); requestControls.set(i, preReadRequest); } catch (LDAPException le) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, le); } setResultCode(ResultCode.valueOf(le.getResultCode())); appendErrorMessage(le.getMessage()); break modifyDNProcessing; } } } else if (oid.equals(OID_LDAP_READENTRY_POSTREAD)) { if (c instanceof LDAPAssertionRequestControl) { postReadRequest = (LDAPPostReadRequestControl) c; } else { try { postReadRequest = LDAPPostReadRequestControl.decodeControl(c); requestControls.set(i, postReadRequest); } catch (LDAPException le) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, le); } setResultCode(ResultCode.valueOf(le.getResultCode())); appendErrorMessage(le.getMessage()); break modifyDNProcessing; } } } else if (oid.equals(OID_PROXIED_AUTH_V1)) { // The requester must have the PROXIED_AUTH privilige in order to // be able to use this control. if (! clientConnection.hasPrivilege(Privilege.PROXIED_AUTH, this)) { int msgID = MSGID_PROXYAUTH_INSUFFICIENT_PRIVILEGES; appendErrorMessage(getMessage(msgID)); setResultCode(ResultCode.AUTHORIZATION_DENIED); break modifyDNProcessing; } ProxiedAuthV1Control proxyControl; if (c instanceof ProxiedAuthV1Control) { proxyControl = (ProxiedAuthV1Control) c; } else { try { proxyControl = ProxiedAuthV1Control.decodeControl(c); } catch (LDAPException le) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, le); } setResultCode(ResultCode.valueOf(le.getResultCode())); appendErrorMessage(le.getMessage()); break modifyDNProcessing; } } Entry authorizationEntry; try { authorizationEntry = proxyControl.getAuthorizationEntry(); } catch (DirectoryException de) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, de); } setResultCode(de.getResultCode()); appendErrorMessage(de.getErrorMessage()); break modifyDNProcessing; } if (AccessControlConfigManager.getInstance() .getAccessControlHandler().isProxiedAuthAllowed(this, authorizationEntry) == false) { setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS); int msgID = MSGID_MODDN_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS; appendErrorMessage(getMessage(msgID, String.valueOf(entryDN))); skipPostOperation = true; break modifyDNProcessing; } setAuthorizationEntry(authorizationEntry); if (authorizationEntry == null) { proxiedAuthorizationDN = DN.nullDN(); } else { proxiedAuthorizationDN = authorizationEntry.getDN(); } } else if (oid.equals(OID_PROXIED_AUTH_V2)) { // The requester must have the PROXIED_AUTH privilige in order to // be able to use this control. if (! clientConnection.hasPrivilege(Privilege.PROXIED_AUTH, this)) { int msgID = MSGID_PROXYAUTH_INSUFFICIENT_PRIVILEGES; appendErrorMessage(getMessage(msgID)); setResultCode(ResultCode.AUTHORIZATION_DENIED); break modifyDNProcessing; } ProxiedAuthV2Control proxyControl; if (c instanceof ProxiedAuthV2Control) { proxyControl = (ProxiedAuthV2Control) c; } else { try { proxyControl = ProxiedAuthV2Control.decodeControl(c); } catch (LDAPException le) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, le); } setResultCode(ResultCode.valueOf(le.getResultCode())); appendErrorMessage(le.getMessage()); break modifyDNProcessing; } } Entry authorizationEntry; try { authorizationEntry = proxyControl.getAuthorizationEntry(); } catch (DirectoryException de) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, de); } setResultCode(de.getResultCode()); appendErrorMessage(de.getErrorMessage()); break modifyDNProcessing; } if (AccessControlConfigManager.getInstance() .getAccessControlHandler().isProxiedAuthAllowed(this, authorizationEntry) == false) { setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS); int msgID = MSGID_MODDN_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS; appendErrorMessage(getMessage(msgID, String.valueOf(entryDN))); skipPostOperation = true; break modifyDNProcessing; } setAuthorizationEntry(authorizationEntry); if (authorizationEntry == null) { proxiedAuthorizationDN = DN.nullDN(); } else { proxiedAuthorizationDN = authorizationEntry.getDN(); } } // NYI -- Add support for additional controls. else if (c.isCritical()) { Backend backend = DirectoryServer.getBackend(entryDN); if ((backend == null) || (! backend.supportsControl(oid))) { setResultCode(ResultCode.UNAVAILABLE_CRITICAL_EXTENSION); int msgID = MSGID_MODDN_UNSUPPORTED_CRITICAL_CONTROL; appendErrorMessage(getMessage(msgID, String.valueOf(entryDN), oid)); break modifyDNProcessing; } } } } // Check to see if the client has permission to perform the // modify DN. // FIXME: for now assume that this will check all permission // pertinent to the operation. This includes proxy authorization // and any other controls specified. // FIXME: earlier checks to see if the entry or new superior // already exists may have already exposed sensitive information // to the client. if (AccessControlConfigManager.getInstance() .getAccessControlHandler().isAllowed(this) == false) { setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS); int msgID = MSGID_MODDN_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS; appendErrorMessage(getMessage(msgID, String.valueOf(entryDN))); skipPostOperation = true; break modifyDNProcessing; } // Duplicate the entry and set its new DN. Also, create an empty list // to hold the attribute-level modifications. newEntry = currentEntry.duplicate(false); newEntry.setDN(newDN); modifications = new ArrayList<Modification>(); // If we should delete the old RDN values from the entry, then do so. if (deleteOldRDN) { RDN currentRDN = entryDN.getRDN(); int numValues = currentRDN.getNumValues(); for (int i=0; i < numValues; i++) { LinkedHashSet<AttributeValue> valueSet = new LinkedHashSet<AttributeValue>(1); valueSet.add(currentRDN.getAttributeValue(i)); Attribute a = new Attribute(currentRDN.getAttributeType(i), currentRDN.getAttributeName(i), valueSet); // If the associated attribute type is marked NO-USER-MODIFICATION, // then refuse the update. if (a.getAttributeType().isNoUserModification()) { if (! (isInternalOperation() || isSynchronizationOperation())) { setResultCode(ResultCode.UNWILLING_TO_PERFORM); int msgID = MSGID_MODDN_OLD_RDN_ATTR_IS_NO_USER_MOD; appendErrorMessage(getMessage(msgID, String.valueOf(entryDN), a.getName())); break modifyDNProcessing; } } LinkedList<AttributeValue> missingValues = new LinkedList<AttributeValue>(); newEntry.removeAttribute(a, missingValues); if (missingValues.isEmpty()) { modifications.add(new Modification(ModificationType.DELETE, a)); } } } // Add the new RDN values to the entry. int newRDNValues = newRDN.getNumValues(); for (int i=0; i < newRDNValues; i++) { LinkedHashSet<AttributeValue> valueSet = new LinkedHashSet<AttributeValue>(1); valueSet.add(newRDN.getAttributeValue(i)); Attribute a = new Attribute(newRDN.getAttributeType(i), newRDN.getAttributeName(i), valueSet); LinkedList<AttributeValue> duplicateValues = new LinkedList<AttributeValue>(); newEntry.addAttribute(a, duplicateValues); if (duplicateValues.isEmpty()) { // If the associated attribute type is marked NO-USER-MODIFICATION, // then refuse the update. if (a.getAttributeType().isNoUserModification()) { if (! (isInternalOperation() || isSynchronizationOperation())) { setResultCode(ResultCode.UNWILLING_TO_PERFORM); int msgID = MSGID_MODDN_NEW_RDN_ATTR_IS_NO_USER_MOD; appendErrorMessage(getMessage(msgID, String.valueOf(entryDN), a.getName())); break modifyDNProcessing; } } else { modifications.add(new Modification(ModificationType.ADD, a)); } } } // If the server is configured to check the schema and the // operation is not a synchronization operation, // make sure that the resulting entry is valid as per the server schema. if ((DirectoryServer.checkSchema()) && (!isSynchronizationOperation()) ) { StringBuilder invalidReason = new StringBuilder(); if (! newEntry.conformsToSchema(null, false, true, true, invalidReason)) { setResultCode(ResultCode.OBJECTCLASS_VIOLATION); appendErrorMessage(getMessage(MSGID_MODDN_VIOLATES_SCHEMA, String.valueOf(entryDN), String.valueOf(invalidReason))); break modifyDNProcessing; } for (int i=0; i < newRDNValues; i++) { AttributeType at = newRDN.getAttributeType(i); if (at.isObsolete()) { setResultCode(ResultCode.CONSTRAINT_VIOLATION); appendErrorMessage(getMessage(MSGID_MODDN_NEWRDN_ATTR_IS_OBSOLETE, String.valueOf(entryDN), at.getNameOrOID())); break modifyDNProcessing; } } } // Check for and handle a request to cancel this operation. if (cancelRequest != null) { indicateCancelled(cancelRequest); setProcessingStopTime(); logModifyDNResponse(this); pluginConfigManager.invokePostResponseModifyDNPlugins(this); return; } // Get a count of the current number of modifications. The // pre-operation plugins may alter this list, and we need to be able to // identify which changes were made after they're done. int modCount = modifications.size(); // If the operation is not a synchronization operation, // Invoke the pre-operation modify DN plugins. if (!isSynchronizationOperation()) { PreOperationPluginResult preOpResult = pluginConfigManager.invokePreOperationModifyDNPlugins(this); if (preOpResult.connectionTerminated()) { // There's no point in continuing with anything. Log the request // and result and return. setResultCode(ResultCode.CANCELED); int msgID = MSGID_CANCELED_BY_PREOP_DISCONNECT; appendErrorMessage(getMessage(msgID)); setProcessingStopTime(); logModifyDNResponse(this); pluginConfigManager.invokePostResponseModifyDNPlugins(this); return; } else if (preOpResult.sendResponseImmediately()) { skipPostOperation = true; break modifyDNProcessing; } else if (preOpResult.skipCoreProcessing()) { skipPostOperation = false; break modifyDNProcessing; } } // Check to see if any of the pre-operation plugins made any changes to // the entry. If so, then apply them. if (modifications.size() > modCount) { for (int i=modCount; i < modifications.size(); i++) { Modification m = modifications.get(i); Attribute a = m.getAttribute(); switch (m.getModificationType()) { case ADD: LinkedList<AttributeValue> duplicateValues = new LinkedList<AttributeValue>(); newEntry.addAttribute(a, duplicateValues); break; case DELETE: LinkedList<AttributeValue> missingValues = new LinkedList<AttributeValue>(); newEntry.removeAttribute(a, missingValues); break; case REPLACE: duplicateValues = new LinkedList<AttributeValue>(); newEntry.removeAttribute(a.getAttributeType(), a.getOptions()); newEntry.addAttribute(a, duplicateValues); break; case INCREMENT: List<Attribute> attrList = newEntry.getAttribute(a.getAttributeType(), a.getOptions()); if ((attrList == null) || attrList.isEmpty()) { setResultCode(ResultCode.NO_SUCH_ATTRIBUTE); int msgID = MSGID_MODDN_PREOP_INCREMENT_NO_ATTR; appendErrorMessage(getMessage(msgID, String.valueOf(entryDN), a.getName())); break modifyDNProcessing; } else if (attrList.size() > 1) { setResultCode(ResultCode.CONSTRAINT_VIOLATION); int msgID = MSGID_MODDN_PREOP_INCREMENT_MULTIPLE_VALUES; appendErrorMessage(getMessage(msgID, String.valueOf(entryDN), a.getName())); break modifyDNProcessing; } LinkedHashSet<AttributeValue> values = attrList.get(0).getValues(); if ((values == null) || values.isEmpty()) { setResultCode(ResultCode.NO_SUCH_ATTRIBUTE); int msgID = MSGID_MODDN_PREOP_INCREMENT_NO_ATTR; appendErrorMessage(getMessage(msgID, String.valueOf(entryDN), a.getName())); break modifyDNProcessing; } else if (values.size() > 1) { setResultCode(ResultCode.CONSTRAINT_VIOLATION); int msgID = MSGID_MODDN_PREOP_INCREMENT_MULTIPLE_VALUES; appendErrorMessage(getMessage(msgID, String.valueOf(entryDN), a.getName())); break modifyDNProcessing; } long currentLongValue; try { AttributeValue v = values.iterator().next(); currentLongValue = Long.parseLong(v.getStringValue()); } catch (Exception e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } setResultCode(ResultCode.CONSTRAINT_VIOLATION); int msgID = MSGID_MODDN_PREOP_INCREMENT_VALUE_NOT_INTEGER; appendErrorMessage(getMessage(msgID, String.valueOf(entryDN), a.getName())); break modifyDNProcessing; } LinkedHashSet<AttributeValue> newValues = a.getValues(); if ((newValues == null) || newValues.isEmpty()) { setResultCode(ResultCode.CONSTRAINT_VIOLATION); int msgID = MSGID_MODDN_PREOP_INCREMENT_NO_AMOUNT; appendErrorMessage(getMessage(msgID, String.valueOf(entryDN), a.getName())); break modifyDNProcessing; } else if (newValues.size() > 1) { setResultCode(ResultCode.CONSTRAINT_VIOLATION); int msgID = MSGID_MODDN_PREOP_INCREMENT_MULTIPLE_AMOUNTS; appendErrorMessage(getMessage(msgID, String.valueOf(entryDN), a.getName())); break modifyDNProcessing; } long incrementAmount; try { AttributeValue v = values.iterator().next(); incrementAmount = Long.parseLong(v.getStringValue()); } catch (Exception e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } setResultCode(ResultCode.CONSTRAINT_VIOLATION); int msgID = MSGID_MODDN_PREOP_INCREMENT_AMOUNT_NOT_INTEGER; appendErrorMessage(getMessage(msgID, String.valueOf(entryDN), a.getName())); break modifyDNProcessing; } long newLongValue = currentLongValue + incrementAmount; ByteString newValueOS = new ASN1OctetString(String.valueOf(newLongValue)); newValues = new LinkedHashSet<AttributeValue>(1); newValues.add(new AttributeValue(a.getAttributeType(), newValueOS)); List<Attribute> newAttrList = new ArrayList<Attribute>(1); newAttrList.add(new Attribute(a.getAttributeType(), a.getName(), newValues)); newEntry.putAttribute(a.getAttributeType(), newAttrList); break; } } // Make sure that the updated entry still conforms to the server // schema. if (DirectoryServer.checkSchema()) { StringBuilder invalidReason = new StringBuilder(); if (! newEntry.conformsToSchema(null, false, true, true, invalidReason)) { setResultCode(ResultCode.OBJECTCLASS_VIOLATION); appendErrorMessage(getMessage(MSGID_MODDN_PREOP_VIOLATES_SCHEMA, String.valueOf(entryDN), String.valueOf(invalidReason))); break modifyDNProcessing; } } } // Check for and handle a request to cancel this operation. if (cancelRequest != null) { indicateCancelled(cancelRequest); setProcessingStopTime(); logModifyDNResponse(this); pluginConfigManager.invokePostResponseModifyDNPlugins(this); return; } // Actually perform the modify DN operation. This should include taking // care of any synchronization that might be needed. try { // If it is not a private backend, then check to see if the server or // backend is operating in read-only mode. if (! currentBackend.isPrivateBackend()) { switch (DirectoryServer.getWritabilityMode()) { case DISABLED: setResultCode(ResultCode.UNWILLING_TO_PERFORM); appendErrorMessage(getMessage(MSGID_MODDN_SERVER_READONLY, String.valueOf(entryDN))); break modifyDNProcessing; case INTERNAL_ONLY: if (! (isInternalOperation() || isSynchronizationOperation())) { setResultCode(ResultCode.UNWILLING_TO_PERFORM); appendErrorMessage(getMessage(MSGID_MODDN_SERVER_READONLY, String.valueOf(entryDN))); break modifyDNProcessing; } } switch (currentBackend.getWritabilityMode()) { case DISABLED: setResultCode(ResultCode.UNWILLING_TO_PERFORM); appendErrorMessage(getMessage(MSGID_MODDN_BACKEND_READONLY, String.valueOf(entryDN))); break modifyDNProcessing; case INTERNAL_ONLY: if (! (isInternalOperation() || isSynchronizationOperation())) { setResultCode(ResultCode.UNWILLING_TO_PERFORM); appendErrorMessage(getMessage(MSGID_MODDN_BACKEND_READONLY, String.valueOf(entryDN))); break modifyDNProcessing; } } } if (noOp) { appendErrorMessage(getMessage(MSGID_MODDN_NOOP)); setResultCode(ResultCode.NO_OPERATION); } else { for (SynchronizationProvider provider : DirectoryServer.getSynchronizationProviders()) { try { SynchronizationProviderResult result = provider.doPreOperation(this); if (! result.continueOperationProcessing()) { break modifyDNProcessing; } } catch (DirectoryException de) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, de); } logError(ErrorLogCategory.SYNCHRONIZATION, ErrorLogSeverity.SEVERE_ERROR, MSGID_MODDN_SYNCH_PREOP_FAILED, getConnectionID(), getOperationID(), getExceptionMessage(de)); setResponseData(de); break modifyDNProcessing; } } currentBackend.renameEntry(entryDN, newEntry, this); } if (preReadRequest != null) { Entry entry = currentEntry.duplicate(true); if (! preReadRequest.allowsAttribute( DirectoryServer.getObjectClassAttributeType())) { entry.removeAttribute( DirectoryServer.getObjectClassAttributeType()); } if (! preReadRequest.returnAllUserAttributes()) { Iterator<AttributeType> iterator = entry.getUserAttributes().keySet().iterator(); while (iterator.hasNext()) { AttributeType attrType = iterator.next(); if (! preReadRequest.allowsAttribute(attrType)) { iterator.remove(); } } } if (! preReadRequest.returnAllOperationalAttributes()) { Iterator<AttributeType> iterator = entry.getOperationalAttributes().keySet().iterator(); while (iterator.hasNext()) { AttributeType attrType = iterator.next(); if (! preReadRequest.allowsAttribute(attrType)) { iterator.remove(); } } } // FIXME -- Check access controls on the entry to see if it should // be returned or if any attributes need to be stripped // out.. SearchResultEntry searchEntry = new SearchResultEntry(entry); LDAPPreReadResponseControl responseControl = new LDAPPreReadResponseControl(preReadRequest.getOID(), preReadRequest.isCritical(), searchEntry); responseControls.add(responseControl); } if (postReadRequest != null) { Entry entry = newEntry.duplicate(true); if (! postReadRequest.allowsAttribute( DirectoryServer.getObjectClassAttributeType())) { entry.removeAttribute( DirectoryServer.getObjectClassAttributeType()); } if (! postReadRequest.returnAllUserAttributes()) { Iterator<AttributeType> iterator = entry.getUserAttributes().keySet().iterator(); while (iterator.hasNext()) { AttributeType attrType = iterator.next(); if (! postReadRequest.allowsAttribute(attrType)) { iterator.remove(); } } } if (! postReadRequest.returnAllOperationalAttributes()) { Iterator<AttributeType> iterator = entry.getOperationalAttributes().keySet().iterator(); while (iterator.hasNext()) { AttributeType attrType = iterator.next(); if (! postReadRequest.allowsAttribute(attrType)) { iterator.remove(); } } } // FIXME -- Check access controls on the entry to see if it should // be returned or if any attributes need to be stripped // out.. SearchResultEntry searchEntry = new SearchResultEntry(entry); LDAPPostReadResponseControl responseControl = new LDAPPostReadResponseControl(postReadRequest.getOID(), postReadRequest.isCritical(), searchEntry); responseControls.add(responseControl); } if (! noOp) { setResultCode(ResultCode.SUCCESS); } } catch (DirectoryException de) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, de); } setResultCode(de.getResultCode()); appendErrorMessage(de.getErrorMessage()); setMatchedDN(de.getMatchedDN()); setReferralURLs(de.getReferralURLs()); break modifyDNProcessing; } catch (CancelledOperationException coe) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, coe); } CancelResult cancelResult = coe.getCancelResult(); setCancelResult(cancelResult); setResultCode(cancelResult.getResultCode()); String message = coe.getMessage(); if ((message != null) && (message.length() > 0)) { appendErrorMessage(message); } break modifyDNProcessing; } } finally { LockManager.unlock(entryDN, currentLock); LockManager.unlock(newDN, newLock); for (SynchronizationProvider provider : DirectoryServer.getSynchronizationProviders()) { try { provider.doPostOperation(this); } catch (DirectoryException de) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, de); } logError(ErrorLogCategory.SYNCHRONIZATION, ErrorLogSeverity.SEVERE_ERROR, MSGID_MODDN_SYNCH_POSTOP_FAILED, getConnectionID(), getOperationID(), getExceptionMessage(de)); setResponseData(de); break; } } } } // Indicate that it is now too late to attempt to cancel the operation. setCancelResult(CancelResult.TOO_LATE); // Invoke the post-operation modify DN plugins. if (! skipPostOperation) { PostOperationPluginResult postOperationResult = pluginConfigManager.invokePostOperationModifyDNPlugins(this); if (postOperationResult.connectionTerminated()) { setResultCode(ResultCode.CANCELED); int msgID = MSGID_CANCELED_BY_POSTOP_DISCONNECT; appendErrorMessage(getMessage(msgID)); setProcessingStopTime(); logModifyDNResponse(this); pluginConfigManager.invokePostResponseModifyDNPlugins(this); return; } } // Notify any change notification listeners that might be registered with // the server. if (getResultCode() == ResultCode.SUCCESS) { for (ChangeNotificationListener changeListener : DirectoryServer.getChangeNotificationListeners()) { try { changeListener.handleModifyDNOperation(this, currentEntry, newEntry); } catch (Exception e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } int msgID = MSGID_MODDN_ERROR_NOTIFYING_CHANGE_LISTENER; String message = getMessage(msgID, getExceptionMessage(e)); logError(ErrorLogCategory.CORE_SERVER, ErrorLogSeverity.SEVERE_ERROR, message, msgID); } } } // Stop the processing timer. setProcessingStopTime(); // Send the modify DN response to the client. clientConnection.sendResponse(this); // Log the modify DN response. logModifyDNResponse(this); // Notify any persistent searches that might be registered with the server. if (getResultCode() == ResultCode.SUCCESS) { for (PersistentSearch persistentSearch : DirectoryServer.getPersistentSearches()) { try { persistentSearch.processModifyDN(this, currentEntry, newEntry); } catch (Exception e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } int msgID = MSGID_MODDN_ERROR_NOTIFYING_PERSISTENT_SEARCH; String message = getMessage(msgID, String.valueOf(persistentSearch), getExceptionMessage(e)); logError(ErrorLogCategory.CORE_SERVER, ErrorLogSeverity.SEVERE_ERROR, message, msgID); DirectoryServer.deregisterPersistentSearch(persistentSearch); } } } // Invoke the post-response modify DN plugins. pluginConfigManager.invokePostResponseModifyDNPlugins(this); } /** * {@inheritDoc} */ @Override() public final CancelResult cancel(CancelRequest cancelRequest) { this.cancelRequest = cancelRequest; CancelResult cancelResult = getCancelResult(); long stopWaitingTime = System.currentTimeMillis() + 5000; while ((cancelResult == null) && (System.currentTimeMillis() < stopWaitingTime)) { try { Thread.sleep(50); } catch (Exception e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } } cancelResult = getCancelResult(); } if (cancelResult == null) { // This can happen in some rare cases (e.g., if a client disconnects and // there is still a lot of data to send to that client), and in this case // we'll prevent the cancel thread from blocking for a long period of // time. cancelResult = CancelResult.CANNOT_CANCEL; } return cancelResult; } /** * {@inheritDoc} */ @Override() public final CancelRequest getCancelRequest() { return cancelRequest; } /** * {@inheritDoc} */ @Override() public boolean setCancelRequest(CancelRequest cancelRequest) { this.cancelRequest = cancelRequest; return true; } /** * {@inheritDoc} */ @Override() public final void toString(StringBuilder buffer) { buffer.append("ModifyDNOperation(connID="); buffer.append(clientConnection.getConnectionID()); buffer.append(", opID="); buffer.append(operationID); buffer.append(", dn="); buffer.append(rawEntryDN); buffer.append(", newRDN="); buffer.append(rawNewRDN); buffer.append(", deleteOldRDN="); buffer.append(deleteOldRDN); if (rawNewSuperior != null) { buffer.append(", newSuperior="); buffer.append(rawNewSuperior); } buffer.append(")"); } public void setProxiedAuthorizationDN(DN dn); } opends/src/server/org/opends/server/core/ModifyDNOperationBasis.java
New file @@ -0,0 +1,952 @@ /* * 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-2007 Sun Microsystems, Inc. */ package org.opends.server.core; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.opends.server.api.ClientConnection; import org.opends.server.api.plugin.PreParsePluginResult; import org.opends.server.protocols.asn1.ASN1OctetString; import org.opends.server.types.AbstractOperation; import org.opends.server.types.ByteString; import org.opends.server.types.CancelRequest; import org.opends.server.types.CancelResult; import org.opends.server.types.Control; import org.opends.server.types.DirectoryException; import org.opends.server.types.DisconnectReason; import org.opends.server.types.DN; import org.opends.server.types.Entry; import org.opends.server.types.ErrorLogCategory; import org.opends.server.types.ErrorLogSeverity; import org.opends.server.types.Modification; import org.opends.server.types.Operation; import org.opends.server.types.OperationType; import org.opends.server.types.RDN; import org.opends.server.types.ResultCode; import org.opends.server.types.operation.PostResponseModifyDNOperation; import org.opends.server.types.operation.PreParseModifyDNOperation; import static org.opends.server.core.CoreConstants.*; import static org.opends.server.loggers.AccessLogger.*; import org.opends.server.types.DebugLogLevel; import org.opends.server.workflowelement.localbackend.*; import static org.opends.server.loggers.ErrorLogger.*; import static org.opends.server.loggers.debug.DebugLogger.*; import org.opends.server.loggers.debug.DebugLogger; import org.opends.server.loggers.debug.DebugTracer; import static org.opends.server.messages.CoreMessages.*; import static org.opends.server.messages.MessageHandler.*; import static org.opends.server.util.StaticUtils.*; /** * This class defines an operation that may be used to alter the DN of an entry * in the Directory Server. */ public class ModifyDNOperationBasis extends AbstractOperation implements ModifyDNOperation, PreParseModifyDNOperation, PostResponseModifyDNOperation { /** * The tracer object for the debug logger. */ private static final DebugTracer TRACER = DebugLogger.getTracer(); // Indicates whether to delete the old RDN value from the entry. private boolean deleteOldRDN; // The raw, unprocessed current DN of the entry as included in the request // from the client. private ByteString rawEntryDN; // The raw, unprocessed newRDN as included in the request from the client. private ByteString rawNewRDN; // The raw, unprocessed newSuperior as included in the request from the // client. private ByteString rawNewSuperior; // The cancel request issued for this modify DN operation. private CancelRequest cancelRequest; // The current DN of the entry. private DN entryDN; // The new parent for the entry. private DN newSuperior; // The proxied authorization target DN for this operation. private DN proxiedAuthorizationDN; // The set of response controls for this modify DN operation. private List<Control> responseControls; // The set of modifications applied to attributes in the entry in the course // of processing the modify DN. private List<Modification> modifications; // The change number that has been assigned to this operation. private long changeNumber; // The new RDN for the entry. private RDN newRDN; // The new entry DN private DN newDN = null; /** * Creates a new modify DN operation with the provided information. * * @param clientConnection The client connection with which this operation * is associated. * @param operationID The operation ID for this operation. * @param messageID The message ID of the request with which this * operation is associated. * @param requestControls The set of controls included in the request. * @param rawEntryDN The raw, unprocessed entry DN as included in the * client request. * @param rawNewRDN The raw, unprocessed newRDN as included in the * client request. * @param deleteOldRDN Indicates whether to delete the old RDN value * from the entry. * @param rawNewSuperior The raw, unprocessed newSuperior as included in * the client request. */ public ModifyDNOperationBasis(ClientConnection clientConnection, long operationID, int messageID, List<Control> requestControls, ByteString rawEntryDN, ByteString rawNewRDN, boolean deleteOldRDN, ByteString rawNewSuperior) { super(clientConnection, operationID, messageID, requestControls); this.rawEntryDN = rawEntryDN; this.rawNewRDN = rawNewRDN; this.deleteOldRDN = deleteOldRDN; this.rawNewSuperior = rawNewSuperior; entryDN = null; newRDN = null; newSuperior = null; responseControls = new ArrayList<Control>(); cancelRequest = null; modifications = null; changeNumber = -1; } /** * Creates a new modify DN operation with the provided information. * * @param clientConnection The client connection with which this operation * is associated. * @param operationID The operation ID for this operation. * @param messageID The message ID of the request with which this * operation is associated. * @param requestControls The set of controls included in the request. * @param entryDN The current entry DN for this modify DN * operation. * @param newRDN The new RDN for this modify DN operation. * @param deleteOldRDN Indicates whether to delete the old RDN value * from the entry. * @param newSuperior The newSuperior DN for this modify DN operation. */ public ModifyDNOperationBasis(ClientConnection clientConnection, long operationID, int messageID, List<Control> requestControls, DN entryDN, RDN newRDN, boolean deleteOldRDN, DN newSuperior) { super(clientConnection, operationID, messageID, requestControls); this.entryDN = entryDN; this.newRDN = newRDN; this.deleteOldRDN = deleteOldRDN; this.newSuperior = newSuperior; rawEntryDN = new ASN1OctetString(entryDN.toString()); rawNewRDN = new ASN1OctetString(newRDN.toString()); if (newSuperior == null) { rawNewSuperior = null; } else { rawNewSuperior = new ASN1OctetString(newSuperior.toString()); } responseControls = new ArrayList<Control>(); cancelRequest = null; modifications = null; changeNumber = -1; } /** * {@inheritDoc} */ public final ByteString getRawEntryDN() { return rawEntryDN; } /** * {@inheritDoc} */ public final void setRawEntryDN(ByteString rawEntryDN) { this.rawEntryDN = rawEntryDN; entryDN = null; } /** * {@inheritDoc} */ public final DN getEntryDN() { try { if (entryDN == null) { entryDN = DN.decode(rawEntryDN); } } catch (DirectoryException de) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, de); } setResultCode(de.getResultCode()); appendErrorMessage(de.getErrorMessage()); } return entryDN; } /** * {@inheritDoc} */ public final ByteString getRawNewRDN() { return rawNewRDN; } /** * {@inheritDoc} */ public final void setRawNewRDN(ByteString rawNewRDN) { this.rawNewRDN = rawNewRDN; newRDN = null; newDN = null; } /** * {@inheritDoc} */ public final RDN getNewRDN() { try { if (newRDN == null) { newRDN = RDN.decode(rawNewRDN.stringValue()); } } catch (DirectoryException de) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, de); } setResultCode(de.getResultCode()); appendErrorMessage(de.getErrorMessage()); } return newRDN; } /** * {@inheritDoc} */ public final boolean deleteOldRDN() { return deleteOldRDN; } /** * {@inheritDoc} */ public final void setDeleteOldRDN(boolean deleteOldRDN) { this.deleteOldRDN = deleteOldRDN; } /** * {@inheritDoc} */ public final ByteString getRawNewSuperior() { return rawNewSuperior; } /** * {@inheritDoc} */ public final void setRawNewSuperior(ByteString rawNewSuperior) { this.rawNewSuperior = rawNewSuperior; newSuperior = null; newDN = null; } /** * {@inheritDoc} */ public final DN getNewSuperior() { if (rawNewSuperior == null) { newSuperior = null; } else { try { if (newSuperior == null) { newSuperior = DN.decode(rawNewSuperior); } } catch (DirectoryException de) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, de); } setResultCode(de.getResultCode()); appendErrorMessage(de.getErrorMessage()); } } return newSuperior; } /** * {@inheritDoc} */ public final List<Modification> getModifications() { return modifications; } /** * {@inheritDoc} */ public final void addModification(Modification modification) { if (modifications == null) { modifications = new ArrayList<Modification>(); } if (modification != null) { modifications.add(modification); } } /** * {@inheritDoc} */ public final Entry getOriginalEntry() { return null; } /** * {@inheritDoc} */ public final Entry getUpdatedEntry() { return null; } /** * {@inheritDoc} */ public final long getChangeNumber() { return changeNumber; } /** * {@inheritDoc} */ public final void setChangeNumber(long changeNumber) { this.changeNumber = changeNumber; } /** * {@inheritDoc} */ @Override() public final OperationType getOperationType() { // Note that no debugging will be done in this method because it is a likely // candidate for being called by the logging subsystem. return OperationType.MODIFY_DN; } /** * {@inheritDoc} */ @Override() public final void disconnectClient(DisconnectReason disconnectReason, boolean sendNotification, String message, int messageID) { // Before calling clientConnection.disconnect, we need to mark this // operation as cancelled so that the attempt to cancel it later won't cause // an unnecessary delay. setCancelResult(CancelResult.CANCELED); clientConnection.disconnect(disconnectReason, sendNotification, message, messageID); } /** * {@inheritDoc} */ @Override() public final String[][] getRequestLogElements() { // Note that no debugging will be done in this method because it is a likely // candidate for being called by the logging subsystem. String newSuperiorStr; if (rawNewSuperior == null) { newSuperiorStr = null; } else { newSuperiorStr = rawNewSuperior.stringValue(); } return new String[][] { new String[] { LOG_ELEMENT_ENTRY_DN, String.valueOf(rawEntryDN) }, new String[] { LOG_ELEMENT_NEW_RDN, String.valueOf(newRDN) }, new String[] { LOG_ELEMENT_DELETE_OLD_RDN, String.valueOf(deleteOldRDN) }, new String[] { LOG_ELEMENT_NEW_SUPERIOR, newSuperiorStr } }; } /** * {@inheritDoc} */ @Override() public final String[][] getResponseLogElements() { // Note that no debugging will be done in this method because it is a likely // candidate for being called by the logging subsystem. String resultCode = String.valueOf(getResultCode().getIntValue()); String errorMessage; StringBuilder errorMessageBuffer = getErrorMessage(); if (errorMessageBuffer == null) { errorMessage = null; } else { errorMessage = errorMessageBuffer.toString(); } String matchedDNStr; DN matchedDN = getMatchedDN(); if (matchedDN == null) { matchedDNStr = null; } else { matchedDNStr = matchedDN.toString(); } String referrals; List<String> referralURLs = getReferralURLs(); if ((referralURLs == null) || referralURLs.isEmpty()) { referrals = null; } else { StringBuilder buffer = new StringBuilder(); Iterator<String> iterator = referralURLs.iterator(); buffer.append(iterator.next()); while (iterator.hasNext()) { buffer.append(", "); buffer.append(iterator.next()); } referrals = buffer.toString(); } String processingTime = String.valueOf(getProcessingTime()); return new String[][] { new String[] { LOG_ELEMENT_RESULT_CODE, resultCode }, new String[] { LOG_ELEMENT_ERROR_MESSAGE, errorMessage }, new String[] { LOG_ELEMENT_MATCHED_DN, matchedDNStr }, new String[] { LOG_ELEMENT_REFERRAL_URLS, referrals }, new String[] { LOG_ELEMENT_PROCESSING_TIME, processingTime } }; } /** * {@inheritDoc} */ public DN getProxiedAuthorizationDN() { return proxiedAuthorizationDN; } /** * {@inheritDoc} */ @Override() public final List<Control> getResponseControls() { return responseControls; } /** * {@inheritDoc} */ @Override() public final void addResponseControl(Control control) { responseControls.add(control); } /** * {@inheritDoc} */ @Override() public final void removeResponseControl(Control control) { responseControls.remove(control); } /** * Performs the work of actually processing this operation. This * should include all processing for the operation, including * invoking plugins, logging messages, performing access control, * managing synchronization, and any other work that might need to * be done in the course of processing. */ public final void run() { setResultCode(ResultCode.UNDEFINED); boolean workflowExecuted = false; // Get the plugin config manager that will be used for invoking plugins. PluginConfigManager pluginConfigManager = DirectoryServer.getPluginConfigManager(); // Start the processing timer. setProcessingStartTime(); // Check for and handle a request to cancel this operation. if (cancelRequest != null) { indicateCancelled(cancelRequest); setProcessingStopTime(); return; } // Create a labeled block of code that we can break out of if a problem is // detected. modifyDNProcessing: { // Invoke the pre-parse modify DN plugins. PreParsePluginResult preParseResult = pluginConfigManager.invokePreParseModifyDNPlugins(this); if (preParseResult.connectionTerminated()) { // There's no point in continuing with anything. Log the request and // result and return. setResultCode(ResultCode.CANCELED); int msgID = MSGID_CANCELED_BY_PREPARSE_DISCONNECT; appendErrorMessage(getMessage(msgID)); setProcessingStopTime(); logModifyDNRequest(this); logModifyDNResponse(this); pluginConfigManager.invokePostResponseModifyDNPlugins(this); return; } else if (preParseResult.sendResponseImmediately()) { logModifyDNRequest(this); break modifyDNProcessing; } else if (preParseResult.skipCoreProcessing()) { break modifyDNProcessing; } // Log the modify DN request message. logModifyDNRequest(this); // Check for and handle a request to cancel this operation. if (cancelRequest != null) { indicateCancelled(cancelRequest); setProcessingStopTime(); logModifyDNResponse(this); pluginConfigManager.invokePostResponseModifyDNPlugins(this); return; } // Process the entry DN, newRDN, and newSuperior elements from their raw // forms as provided by the client to the forms required for the rest of // the modify DN processing. DN entryDN = getEntryDN(); if (entryDN == null) { break modifyDNProcessing; } // Retrieve the network group attached to the client connection // and get a workflow to process the operation. NetworkGroup ng = getClientConnection().getNetworkGroup(); Workflow workflow = ng.getWorkflowCandidate(entryDN); if (workflow == null) { // We have found no workflow for the requested base DN, just return // a no such entry result code and stop the processing. updateOperationErrMsgAndResCode(); break modifyDNProcessing; } workflow.execute(this); workflowExecuted = true; } // Check for and handle a request to cancel this operation. if ((getCancelRequest() != null) || (getCancelResult() == CancelResult.CANCELED)) { if (getCancelRequest() != null){ indicateCancelled(getCancelRequest()); } setProcessingStopTime(); logModifyDNResponse(this); invokePostResponsePlugins(); return; } // Stop the processing timer. setProcessingStopTime(); // Send the modify DN response to the client. clientConnection.sendResponse(this); // Log the modify DN response. logModifyDNResponse(this); // If a workflow has been executed to process the operation, then // call the post response plugins against the operations attached // to this operation. if (workflowExecuted) { // Check wether there are local operations in attachments List localOperations = (List)getAttachment(Operation.LOCALBACKENDOPERATIONS); if (localOperations != null && (! localOperations.isEmpty())){ for (Object localOperation : localOperations) { LocalBackendModifyDNOperation localOp = (LocalBackendModifyDNOperation)localOperation; // Notify any persistent searches that might be registered with // the server. if (getResultCode() == ResultCode.SUCCESS) { for (PersistentSearch persistentSearch : DirectoryServer.getPersistentSearches()) { try { persistentSearch.processModifyDN( localOp, localOp.getOriginalEntry(), localOp.getUpdatedEntry()); } catch (Exception e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } int msgID = MSGID_MODDN_ERROR_NOTIFYING_PERSISTENT_SEARCH; String message = getMessage(msgID, String.valueOf(persistentSearch), getExceptionMessage(e)); logError(ErrorLogCategory.CORE_SERVER, ErrorLogSeverity.SEVERE_ERROR, message, msgID); DirectoryServer.deregisterPersistentSearch(persistentSearch); } } } // Invoke the post-response modify DN plugins. pluginConfigManager.invokePostResponseModifyDNPlugins(localOp); } } } else { // Invoke the post-response modify DN plugins. pluginConfigManager.invokePostResponseModifyDNPlugins(this); } } /** * Updates the error message and the result code of the operation. * * This method is called because no workflows were found to process * the operation. */ private void updateOperationErrMsgAndResCode() { setResultCode(ResultCode.NO_SUCH_OBJECT); appendErrorMessage(getMessage(MSGID_MODDN_NO_BACKEND_FOR_CURRENT_ENTRY, String.valueOf(entryDN))); } /** * {@inheritDoc} */ @Override() public final CancelResult cancel(CancelRequest cancelRequest) { this.cancelRequest = cancelRequest; CancelResult cancelResult = getCancelResult(); long stopWaitingTime = System.currentTimeMillis() + 5000; while ((cancelResult == null) && (System.currentTimeMillis() < stopWaitingTime)) { try { Thread.sleep(50); } catch (Exception e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } } cancelResult = getCancelResult(); } if (cancelResult == null) { // This can happen in some rare cases (e.g., if a client disconnects and // there is still a lot of data to send to that client), and in this case // we'll prevent the cancel thread from blocking for a long period of // time. cancelResult = CancelResult.CANNOT_CANCEL; } return cancelResult; } /** * {@inheritDoc} */ @Override() public final CancelRequest getCancelRequest() { return cancelRequest; } /** * {@inheritDoc} */ @Override() public boolean setCancelRequest(CancelRequest cancelRequest) { this.cancelRequest = cancelRequest; return true; } /** * {@inheritDoc} */ @Override() public final void toString(StringBuilder buffer) { buffer.append("ModifyDNOperation(connID="); buffer.append(clientConnection.getConnectionID()); buffer.append(", opID="); buffer.append(operationID); buffer.append(", dn="); buffer.append(rawEntryDN); buffer.append(", newRDN="); buffer.append(rawNewRDN); buffer.append(", deleteOldRDN="); buffer.append(deleteOldRDN); if (rawNewSuperior != null) { buffer.append(", newSuperior="); buffer.append(rawNewSuperior); } buffer.append(")"); } /** * {@inheritDoc} */ public void setProxiedAuthorizationDN(DN dn) { proxiedAuthorizationDN = dn; } /** * Execute the postResponseModifyPlugins. */ private void invokePostResponsePlugins() { // Get the plugin config manager that will be used for invoking plugins. PluginConfigManager pluginConfigManager = DirectoryServer.getPluginConfigManager(); // Check wether there are local operations in attachments List localOperations = (List)getAttachment(Operation.LOCALBACKENDOPERATIONS); if (localOperations != null && (! localOperations.isEmpty())){ for (Object localOp : localOperations) { LocalBackendModifyDNOperation localOperation = (LocalBackendModifyDNOperation)localOp; // Invoke the post-response add plugins. pluginConfigManager.invokePostResponseModifyDNPlugins(localOperation); } } } /** * {@inheritDoc} */ public DN getNewDN() { if (newDN == null) { // Construct the new DN to use for the entry. DN parentDN = null; if (newSuperior == null) { if (getEntryDN() != null) { parentDN = entryDN.getParentDNInSuffix(); } } else { parentDN = newSuperior; } if ((parentDN == null) || parentDN.isNullDN()) { setResultCode(ResultCode.UNWILLING_TO_PERFORM); appendErrorMessage(getMessage(MSGID_MODDN_NO_PARENT, String.valueOf(entryDN))); } newDN = parentDN.concat(newRDN); } return newDN; } } opends/src/server/org/opends/server/core/ModifyDNOperationWrapper.java
New file @@ -0,0 +1,199 @@ /* * 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 2007 Sun Microsystems, Inc. */ package org.opends.server.core; import java.util.List; import org.opends.server.types.ByteString; import org.opends.server.types.DN; import org.opends.server.types.Entry; import org.opends.server.types.Modification; import org.opends.server.types.RDN; /** * This abstract class wraps/decorates a given moddn operation. * This class will be extended by sub-classes to enhance the * functionnality of the ModifyDNOperationBasis. */ public abstract class ModifyDNOperationWrapper extends OperationWrapper implements ModifyDNOperation { ModifyDNOperation modifyDN; /** * Creates a new moddn operation based on the provided moddn operation. * * @param modifyDN The moddn operation to wrap */ public ModifyDNOperationWrapper(ModifyDNOperation modifyDN) { super(modifyDN); this.modifyDN = modifyDN; } /** * {@inheritDoc} */ public void addModification(Modification modification) { modifyDN.addModification(modification); } /** * {@inheritDoc} */ public boolean deleteOldRDN() { return modifyDN.deleteOldRDN(); } /** * {@inheritDoc} */ public long getChangeNumber() { return modifyDN.getChangeNumber(); } /** * {@inheritDoc} */ public DN getEntryDN() { return modifyDN.getEntryDN(); } /** * {@inheritDoc} */ public List<Modification> getModifications() { return modifyDN.getModifications(); } /** * {@inheritDoc} */ public RDN getNewRDN() { return modifyDN.getNewRDN(); } /** * {@inheritDoc} */ public DN getNewSuperior() { return modifyDN.getNewSuperior(); } /** * {@inheritDoc} */ public Entry getOriginalEntry() { return modifyDN.getOriginalEntry(); } /** * {@inheritDoc} */ public DN getProxiedAuthorizationDN() { return modifyDN.getProxiedAuthorizationDN(); } /** * {@inheritDoc} */ public ByteString getRawEntryDN() { return modifyDN.getRawEntryDN(); } /** * {@inheritDoc} */ public ByteString getRawNewRDN() { return modifyDN.getRawNewRDN(); } /** * {@inheritDoc} */ public ByteString getRawNewSuperior() { return modifyDN.getRawNewSuperior(); } /** * {@inheritDoc} */ public Entry getUpdatedEntry() { return modifyDN.getUpdatedEntry(); } /** * {@inheritDoc} */ public void setChangeNumber(long changeNumber) { modifyDN.setChangeNumber(changeNumber); } /** * {@inheritDoc} */ public void setDeleteOldRDN(boolean deleteOldRDN) { modifyDN.setDeleteOldRDN(deleteOldRDN); } /** * {@inheritDoc} */ public void setRawEntryDN(ByteString rawEntryDN) { modifyDN.setRawEntryDN(rawEntryDN); } /** * {@inheritDoc} */ public void setRawNewRDN(ByteString rawNewRDN) { modifyDN.setRawNewRDN(rawNewRDN); } /** * {@inheritDoc} */ public void setRawNewSuperior(ByteString rawNewSuperior) { modifyDN.setRawNewSuperior(rawNewSuperior); } /** * {@inheritDoc} */ public void setProxiedAuthorizationDN(DN dn) { modifyDN.setProxiedAuthorizationDN(dn); } /** * {@inheritDoc} */ public DN getNewDN() { return modifyDN.getNewDN(); } } opends/src/server/org/opends/server/core/PersistentSearch.java
@@ -532,7 +532,7 @@ * @param oldEntry The entry before the modify DN. * @param newEntry The entry after the modify DN. */ public void processModifyDN(ModifyDNOperation modifyDNOperation, public void processModifyDN(LocalBackendModifyDNOperation modifyDNOperation, Entry oldEntry, Entry newEntry) { // See if we care about modify DN operations. opends/src/server/org/opends/server/core/PluginConfigManager.java
@@ -84,18 +84,21 @@ import org.opends.server.types.operation.PostOperationBindOperation; import org.opends.server.types.operation.PostOperationCompareOperation; import org.opends.server.types.operation.PostOperationDeleteOperation; import org.opends.server.types.operation.PostOperationModifyDNOperation; import org.opends.server.types.operation.PostOperationModifyOperation; import org.opends.server.types.operation.PostOperationSearchOperation; import org.opends.server.types.operation.PostResponseAddOperation; import org.opends.server.types.operation.PostResponseBindOperation; import org.opends.server.types.operation.PostResponseCompareOperation; import org.opends.server.types.operation.PostResponseDeleteOperation; import org.opends.server.types.operation.PostResponseModifyDNOperation; import org.opends.server.types.operation.PostResponseModifyOperation; import org.opends.server.types.operation.PostResponseSearchOperation; import org.opends.server.types.operation.PreOperationAddOperation; import org.opends.server.types.operation.PreOperationBindOperation; import org.opends.server.types.operation.PreOperationCompareOperation; import org.opends.server.types.operation.PreOperationDeleteOperation; import org.opends.server.types.operation.PreOperationModifyDNOperation; import org.opends.server.types.operation.PreOperationModifyOperation; import org.opends.server.types.operation.PreOperationSearchOperation; import org.opends.server.types.operation.PreParseAddOperation; @@ -2303,7 +2306,7 @@ * @return The result of processing the pre-parse modify DN plugins. */ public PreParsePluginResult invokePreParseModifyDNPlugins( ModifyDNOperation modifyDNOperation) ModifyDNOperationBasis modifyDNOperation) { PreParsePluginResult result = null; @@ -3037,7 +3040,7 @@ * @return The result of processing the pre-operation modify DN plugins. */ public PreOperationPluginResult invokePreOperationModifyDNPlugins( ModifyDNOperation modifyDNOperation) PreOperationModifyDNOperation modifyDNOperation) { PreOperationPluginResult result = null; @@ -3771,7 +3774,7 @@ * @return The result of processing the post-operation modify DN plugins. */ public PostOperationPluginResult invokePostOperationModifyDNPlugins( ModifyDNOperation modifyDNOperation) PostOperationModifyDNOperation modifyDNOperation) { PostOperationPluginResult result = null; @@ -4461,7 +4464,7 @@ * @return The result of processing the post-response modify DN plugins. */ public PostResponsePluginResult invokePostResponseModifyDNPlugins( ModifyDNOperation modifyDNOperation) PostResponseModifyDNOperation modifyDNOperation) { PostResponsePluginResult result = null; opends/src/server/org/opends/server/loggers/AccessLogger.java
@@ -710,7 +710,8 @@ * @param modifyDNOperation The modify DN operation containing the * information to use to log the modify DN request. */ public static void logModifyDNRequest(ModifyDNOperation modifyDNOperation) public static void logModifyDNRequest(ModifyDNOperationBasis modifyDNOperation) { for (AccessLogPublisher publisher : accessPublishers) { @@ -728,7 +729,8 @@ * information to use to log the modify DN * response. */ public static void logModifyDNResponse(ModifyDNOperation modifyDNOperation) public static void logModifyDNResponse(ModifyDNOperationBasis modifyDNOperation) { for (AccessLogPublisher publisher : accessPublishers) { opends/src/server/org/opends/server/loggers/TextAccessLogPublisher.java
@@ -44,7 +44,7 @@ import org.opends.server.core.DirectoryServer; import org.opends.server.core.ExtendedOperation; import org.opends.server.core.ModifyOperation; import org.opends.server.core.ModifyDNOperation; import org.opends.server.core.ModifyDNOperationBasis; import org.opends.server.core.SearchOperation; import org.opends.server.core.UnbindOperation; import org.opends.server.types.*; @@ -1369,7 +1369,7 @@ * @param modifyDNOperation The modify DN operation containing the * info to use to log the modify DN request. */ public void logModifyDNRequest(ModifyDNOperation modifyDNOperation) public void logModifyDNRequest(ModifyDNOperationBasis modifyDNOperation) { long connectionID = modifyDNOperation.getConnectionID(); if (connectionID < 0) @@ -1430,7 +1430,7 @@ * information to use to log the modify DN * response. */ public void logModifyDNResponse(ModifyDNOperation modifyDNOperation) public void logModifyDNResponse(ModifyDNOperationBasis modifyDNOperation) { long connectionID = modifyDNOperation.getConnectionID(); if (connectionID < 0) opends/src/server/org/opends/server/loggers/TextAuditLogPublisher.java
@@ -43,7 +43,7 @@ import org.opends.server.core.DirectoryServer; import org.opends.server.core.ExtendedOperation; import org.opends.server.core.ModifyOperation; import org.opends.server.core.ModifyDNOperation; import org.opends.server.core.ModifyDNOperationBasis; import org.opends.server.core.SearchOperation; import org.opends.server.core.UnbindOperation; import org.opends.server.types.*; @@ -738,7 +738,7 @@ * {@inheritDoc} */ @Override() public void logModifyDNRequest(ModifyDNOperation modifyDNOperation) public void logModifyDNRequest(ModifyDNOperationBasis modifyDNOperation) { } @@ -748,7 +748,7 @@ * {@inheritDoc} */ @Override() public void logModifyDNResponse(ModifyDNOperation modifyDNOperation) public void logModifyDNResponse(ModifyDNOperationBasis modifyDNOperation) { long connectionID = modifyDNOperation.getConnectionID(); if (connectionID < 0) opends/src/server/org/opends/server/protocols/internal/InternalClientConnection.java
@@ -1183,7 +1183,7 @@ * processed and contains information about the result of * the processing. */ public ModifyDNOperation processModifyDN(String rawEntryDN, public ModifyDNOperationBasis processModifyDN(String rawEntryDN, String rawNewRDN, boolean deleteOldRDN) { @@ -1207,7 +1207,7 @@ * processed and contains information about the result of * the processing. */ public ModifyDNOperation processModifyDN(ByteString rawEntryDN, public ModifyDNOperationBasis processModifyDN(ByteString rawEntryDN, ByteString rawNewRDN, boolean deleteOldRDN) { @@ -1232,7 +1232,7 @@ * processed and contains information about the result of * the processing. */ public ModifyDNOperation processModifyDN(String rawEntryDN, public ModifyDNOperationBasis processModifyDN(String rawEntryDN, String rawNewRDN, boolean deleteOldRDN, String rawNewSuperior) @@ -1261,13 +1261,13 @@ * processed and contains information about the result of * the processing. */ public ModifyDNOperation processModifyDN(ByteString rawEntryDN, public ModifyDNOperationBasis processModifyDN(ByteString rawEntryDN, ByteString rawNewRDN, boolean deleteOldRDN, ByteString rawNewSuperior) { ModifyDNOperation modifyDNOperation = new ModifyDNOperation(this, nextOperationID(), ModifyDNOperationBasis modifyDNOperation = new ModifyDNOperationBasis(this, nextOperationID(), nextMessageID(), new ArrayList<Control>(0), rawEntryDN, rawNewRDN, deleteOldRDN, @@ -1293,7 +1293,8 @@ * processed and contains information about the result of * the processing. */ public ModifyDNOperation processModifyDN(DN entryDN, RDN newRDN, public ModifyDNOperationBasis processModifyDN(DN entryDN, RDN newRDN, boolean deleteOldRDN) { return processModifyDN(entryDN, newRDN, deleteOldRDN, null); @@ -1317,12 +1318,13 @@ * processed and contains information about the result of * the processing. */ public ModifyDNOperation processModifyDN(DN entryDN, RDN newRDN, public ModifyDNOperationBasis processModifyDN(DN entryDN, RDN newRDN, boolean deleteOldRDN, DN newSuperior) { ModifyDNOperation modifyDNOperation = new ModifyDNOperation(this, nextOperationID(), ModifyDNOperationBasis modifyDNOperation = new ModifyDNOperationBasis(this, nextOperationID(), nextMessageID(), new ArrayList<Control>(0), entryDN, newRDN, deleteOldRDN, newSuperior); opends/src/server/org/opends/server/protocols/jmx/JmxClientConnection.java
@@ -744,7 +744,7 @@ * @return A reference to the modify DN operation that was processed and * contains information about the result of the processing. */ public ModifyDNOperation processModifyDN(ASN1OctetString rawEntryDN, public ModifyDNOperationBasis processModifyDN(ASN1OctetString rawEntryDN, ASN1OctetString rawNewRDN, boolean deleteOldRDN) { @@ -767,13 +767,13 @@ * @return A reference to the modify DN operation that was processed and * contains information about the result of the processing. */ public ModifyDNOperation processModifyDN(ASN1OctetString rawEntryDN, public ModifyDNOperationBasis processModifyDN(ASN1OctetString rawEntryDN, ASN1OctetString rawNewRDN, boolean deleteOldRDN, ASN1OctetString rawNewSuperior) { ModifyDNOperation modifyDNOperation = new ModifyDNOperation(this, nextOperationID(), nextMessageID(), ModifyDNOperationBasis modifyDNOperation = new ModifyDNOperationBasis(this, nextOperationID(), nextMessageID(), new ArrayList<Control>(0), rawEntryDN, rawNewRDN, deleteOldRDN, rawNewSuperior); @@ -807,12 +807,12 @@ * processed and contains information about the result of * the processing. */ public ModifyDNOperation processModifyDN(DN entryDN, RDN newRDN, public ModifyDNOperationBasis processModifyDN(DN entryDN, RDN newRDN, boolean deleteOldRDN, DN newSuperior) { ModifyDNOperation modifyDNOperation = new ModifyDNOperation(this, nextOperationID(), ModifyDNOperationBasis modifyDNOperation = new ModifyDNOperationBasis(this, nextOperationID(), nextMessageID(), new ArrayList<Control>(0), entryDN, newRDN, deleteOldRDN, newSuperior); opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java
@@ -60,7 +60,7 @@ import org.opends.server.core.DeleteOperationBasis; import org.opends.server.core.DirectoryServer; import org.opends.server.core.ExtendedOperation; import org.opends.server.core.ModifyDNOperation; import org.opends.server.core.ModifyDNOperationBasis; import org.opends.server.core.ModifyOperationBasis; import org.opends.server.core.PersistentSearch; import org.opends.server.core.PluginConfigManager; @@ -2319,8 +2319,8 @@ ModifyDNRequestProtocolOp protocolOp = message.getModifyDNRequestProtocolOp(); ModifyDNOperation modifyDNOp = new ModifyDNOperation(this, nextOperationID.getAndIncrement(), ModifyDNOperationBasis modifyDNOp = new ModifyDNOperationBasis(this, nextOperationID.getAndIncrement(), message.getMessageID(), controls, protocolOp.getEntryDN(), protocolOp.getNewRDN(), protocolOp.deleteOldRDN(), opends/src/server/org/opends/server/replication/plugin/ReplicationDomain.java
@@ -66,7 +66,7 @@ import org.opends.server.core.DeleteOperation; import org.opends.server.core.DirectoryServer; import org.opends.server.core.LockFileManager; import org.opends.server.core.ModifyDNOperation; import org.opends.server.core.ModifyDNOperationBasis; import org.opends.server.core.ModifyOperation; import org.opends.server.core.ModifyOperationBasis; import org.opends.server.protocols.asn1.ASN1Exception; @@ -1243,13 +1243,13 @@ done = solveNamingConflict(newOp, addMsg); } } else if (op instanceof ModifyDNOperation) else if (op instanceof ModifyDNOperationBasis) { ModifyDNMsg newMsg = (ModifyDNMsg) msg; dependency = remotePendingChanges.checkDependencies(newMsg); if (!dependency) { ModifyDNOperation newOp = (ModifyDNOperation) op; ModifyDNOperationBasis newOp = (ModifyDNOperationBasis) op; done = solveNamingConflict(newOp, msg); } } @@ -1570,7 +1570,7 @@ * @return true if the process is completed, false if it must continue. * @throws Exception When the operation is not valid. */ private boolean solveNamingConflict(ModifyDNOperation op, private boolean solveNamingConflict(ModifyDNOperationBasis op, UpdateMessage msg) throws Exception { ResultCode result = op.getResultCode(); @@ -1843,7 +1843,7 @@ InternalClientConnection conn = InternalClientConnection.getRootConnection(); ModifyDNOperation newOp = conn.processModifyDN( ModifyDNOperationBasis newOp = conn.processModifyDN( dn, generateDeleteConflictDn(uid, dn),false, baseDN); if (newOp.getResultCode() != ResultCode.SUCCESS) opends/src/server/org/opends/server/replication/protocol/ModifyDNMsg.java
@@ -31,7 +31,7 @@ import java.io.UnsupportedEncodingException; import java.util.zip.DataFormatException; import org.opends.server.core.ModifyDNOperation; import org.opends.server.core.ModifyDNOperationBasis; import org.opends.server.protocols.asn1.ASN1OctetString; import org.opends.server.protocols.internal.InternalClientConnection; import org.opends.server.replication.common.ChangeNumber; @@ -153,7 +153,7 @@ public AbstractOperation createOperation( InternalClientConnection connection, String newDn) { ModifyDNOperation moddn = new ModifyDNOperation(connection, ModifyDNOperationBasis moddn = new ModifyDNOperationBasis(connection, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(), null, new ASN1OctetString(newDn), new ASN1OctetString(newRDN), opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendModifyDNOperation.java
New file @@ -0,0 +1,117 @@ /* * 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 2007 Sun Microsystems, Inc. */ package org.opends.server.workflowelement.localbackend; import org.opends.server.core.ModifyDNOperation; import org.opends.server.core.ModifyDNOperationWrapper; import org.opends.server.types.Entry; import org.opends.server.types.operation.PostOperationModifyDNOperation; import org.opends.server.types.operation.PostResponseModifyDNOperation; import org.opends.server.types.operation.PreOperationModifyDNOperation; /** * This class defines an operation used to move an entry in a local backend * of the Directory Server. */ public class LocalBackendModifyDNOperation extends ModifyDNOperationWrapper implements PreOperationModifyDNOperation, PostOperationModifyDNOperation, PostResponseModifyDNOperation { // The current entry, before it is renamed. private Entry currentEntry; // The new entry, as it will appear after it has been renamed. private Entry newEntry; /** * Creates a new operation that may be used to move an entry in a * local backend of the Directory Server. * * @param operation The operation to enhance. */ public LocalBackendModifyDNOperation (ModifyDNOperation operation) { super(operation); LocalBackendWorkflowElement.attachLocalOperation (operation, this); } /** * Retrieves the current entry, before it is renamed. This will not be * available to pre-parse plugins or during the conflict resolution portion of * the synchronization processing. * * @return The current entry, or <CODE>null</CODE> if it is not yet * available. */ public final Entry getOriginalEntry() { return currentEntry; } /** * Retrieves the new entry, as it will appear after it is renamed. This will * not be available to pre-parse plugins or during the conflict resolution * portion of the synchronization processing. * * @return The updated entry, or <CODE>null</CODE> if it is not yet * available. */ public final Entry getUpdatedEntry() { return newEntry; } /** * Sets the current entry, before it is renamed. This will not be * available to pre-parse plugins or during the conflict resolution portion of * the synchronization processing. * * @param entry The current entry, or <CODE>null</CODE> if it is not yet * available. */ public final void setOriginalEntry(Entry entry) { this.currentEntry = entry; } /** * Sets the new entry, as it will appear after it is renamed. This will * not be available to pre-parse plugins or during the conflict resolution * portion of the synchronization processing. * * @param entry The updated entry, or <CODE>null</CODE> if it is not yet * available. */ public final void setUpdatedEntry(Entry entry) { this.newEntry = entry; } } opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendWorkflowElement.java
@@ -77,6 +77,7 @@ import org.opends.server.core.CompareOperation; import org.opends.server.core.DeleteOperation; import org.opends.server.core.DirectoryServer; import org.opends.server.core.ModifyDNOperation; import org.opends.server.core.ModifyOperation; import org.opends.server.core.PasswordPolicy; import org.opends.server.core.PasswordPolicyState; @@ -179,6 +180,9 @@ case MODIFY: processModify((ModifyOperation) operation); break; case MODIFY_DN: processModifyDN((ModifyDNOperation) operation); break; case COMPARE: processCompare((CompareOperation) operation); break; @@ -6679,6 +6683,7 @@ } /** * Perform a compare operation against a local backend. * @@ -7248,6 +7253,1301 @@ } } /** * Perform a moddn operation against a local backend. * * @param op The operation to perform */ public void processModifyDN(ModifyDNOperation op) { LocalBackendModifyDNOperation localOp = new LocalBackendModifyDNOperation(op); processLocalModifyDN(localOp); } /** * Perform a local moddn operation against the local backend. * * @param operation - The operation to perform */ private void processLocalModifyDN(LocalBackendModifyDNOperation op) { ClientConnection clientConnection = op.getClientConnection(); // Get the plugin config manager that will be used for invoking plugins. PluginConfigManager pluginConfigManager = DirectoryServer.getPluginConfigManager(); boolean skipPostOperation = false; // Check for and handle a request to cancel this operation. if (op.getCancelRequest() != null) { op.indicateCancelled(op.getCancelRequest()); return; } // Create a labeled block of code that we can break out of if a problem is // detected. modifyDNProcessing: { // Process the entry DN, newRDN, and newSuperior elements from their raw // forms as provided by the client to the forms required for the rest of // the modify DN processing. DN entryDN = op.getEntryDN(); RDN newRDN = op.getNewRDN(); if (newRDN == null) { skipPostOperation = true; break modifyDNProcessing; } DN newSuperior = op.getNewSuperior(); if ((newSuperior == null) && (op.getRawNewSuperior() != null)) { skipPostOperation = true; break modifyDNProcessing; } // Construct the new DN to use for the entry. DN parentDN; if (newSuperior == null) { parentDN = entryDN.getParentDNInSuffix(); } else { parentDN = newSuperior; } if ((parentDN == null) || parentDN.isNullDN()) { op.setResultCode(ResultCode.UNWILLING_TO_PERFORM); op.appendErrorMessage(getMessage(MSGID_MODDN_NO_PARENT, String.valueOf(entryDN))); break modifyDNProcessing; } 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. Backend currentBackend = backend; if (currentBackend == null) { op.setResultCode(ResultCode.NO_SUCH_OBJECT); op.appendErrorMessage(getMessage( MSGID_MODDN_NO_BACKEND_FOR_CURRENT_ENTRY, String.valueOf(entryDN))); break modifyDNProcessing; } Backend newBackend = DirectoryServer.getBackend(newDN); if (newBackend == null) { op.setResultCode(ResultCode.NO_SUCH_OBJECT); op.appendErrorMessage(getMessage(MSGID_MODDN_NO_BACKEND_FOR_NEW_ENTRY, String.valueOf(entryDN), String.valueOf(newDN))); break modifyDNProcessing; } else if (! currentBackend.equals(newBackend)) { op.setResultCode(ResultCode.UNWILLING_TO_PERFORM); op.appendErrorMessage(getMessage(MSGID_MODDN_DIFFERENT_BACKENDS, String.valueOf(entryDN), String.valueOf(newDN))); break modifyDNProcessing; } // Check for and handle a request to cancel this operation. if (op.getCancelRequest() != null) { op.indicateCancelled(op.getCancelRequest()); return; } // Acquire write locks for the current and new DN. Lock currentLock = null; for (int i=0; i < 3; i++) { currentLock = LockManager.lockWrite(entryDN); if (currentLock != null) { break; } } if (currentLock == null) { op.setResultCode(DirectoryServer.getServerErrorResultCode()); op.appendErrorMessage(getMessage(MSGID_MODDN_CANNOT_LOCK_CURRENT_DN, String.valueOf(entryDN))); skipPostOperation = true; break modifyDNProcessing; } Lock newLock = null; try { for (int i=0; i < 3; i++) { newLock = LockManager.lockWrite(newDN); if (newLock != null) { break; } } } catch (Exception e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } LockManager.unlock(entryDN, currentLock); if (newLock != null) { LockManager.unlock(newDN, newLock); } op.setResultCode(DirectoryServer.getServerErrorResultCode()); op.appendErrorMessage(getMessage(MSGID_MODDN_EXCEPTION_LOCKING_NEW_DN, String.valueOf(entryDN), String.valueOf(newDN), getExceptionMessage(e))); skipPostOperation = true; break modifyDNProcessing; } if (newLock == null) { LockManager.unlock(entryDN, currentLock); op.setResultCode(DirectoryServer.getServerErrorResultCode()); op.appendErrorMessage(getMessage(MSGID_MODDN_CANNOT_LOCK_NEW_DN, String.valueOf(entryDN), String.valueOf(newDN))); skipPostOperation = true; break modifyDNProcessing; } Entry currentEntry = null; try { // Check for and handle a request to cancel this operation. if (op.getCancelRequest() != null) { op.indicateCancelled(op.getCancelRequest()); return; } // Get the current entry from the appropriate backend. If it doesn't // exist, then fail. try { currentEntry = currentBackend.getEntry(entryDN); op.setOriginalEntry(currentEntry); } catch (DirectoryException de) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, de); } op.setResultCode(de.getResultCode()); op.appendErrorMessage(de.getErrorMessage()); op.setMatchedDN(de.getMatchedDN()); op.setReferralURLs(de.getReferralURLs()); break modifyDNProcessing; } if (op.getOriginalEntry() == null) { // See if one of the entry's ancestors exists. parentDN = entryDN.getParentDNInSuffix(); while (parentDN != null) { try { if (DirectoryServer.entryExists(parentDN)) { op.setMatchedDN(parentDN); break; } } catch (Exception e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } break; } parentDN = parentDN.getParentDNInSuffix(); } op.setResultCode(ResultCode.NO_SUCH_OBJECT); op.appendErrorMessage(getMessage(MSGID_MODDN_NO_CURRENT_ENTRY, String.valueOf(entryDN))); break modifyDNProcessing; } // Invoke any conflict resolution processing that might be needed by the // synchronization provider. for (SynchronizationProvider provider : DirectoryServer.getSynchronizationProviders()) { try { SynchronizationProviderResult result = provider.handleConflictResolution(op); if (! result.continueOperationProcessing()) { break modifyDNProcessing; } } catch (DirectoryException de) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, de); } logError(ErrorLogCategory.SYNCHRONIZATION, ErrorLogSeverity.SEVERE_ERROR, MSGID_MODDN_SYNCH_CONFLICT_RESOLUTION_FAILED, op.getConnectionID(), op.getOperationID(), getExceptionMessage(de)); op.setResponseData(de); break modifyDNProcessing; } } // Check to see if there are any controls in the request. If so, then // see if there is any special processing required. boolean noOp = false; LDAPPreReadRequestControl preReadRequest = null; LDAPPostReadRequestControl postReadRequest = null; List<Control> requestControls = op.getRequestControls(); if ((requestControls != null) && (! requestControls.isEmpty())) { for (int i=0; i < requestControls.size(); i++) { Control c = requestControls.get(i); String oid = c.getOID(); if (oid.equals(OID_LDAP_ASSERTION)) { LDAPAssertionRequestControl assertControl; if (c instanceof LDAPAssertionRequestControl) { assertControl = (LDAPAssertionRequestControl) c; } else { try { assertControl = LDAPAssertionRequestControl.decodeControl(c); requestControls.set(i, assertControl); } catch (LDAPException le) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, le); } op.setResultCode(ResultCode.valueOf(le.getResultCode())); op.appendErrorMessage(le.getMessage()); break modifyDNProcessing; } } try { // FIXME -- We need to determine whether the current user has // permission to make this determination. SearchFilter filter = assertControl.getSearchFilter(); if (! filter.matchesEntry(currentEntry)) { op.setResultCode(ResultCode.ASSERTION_FAILED); op.appendErrorMessage(getMessage(MSGID_MODDN_ASSERTION_FAILED, String.valueOf(entryDN))); break modifyDNProcessing; } } catch (DirectoryException de) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, de); } op.setResultCode(ResultCode.PROTOCOL_ERROR); int msgID = MSGID_MODDN_CANNOT_PROCESS_ASSERTION_FILTER; op.appendErrorMessage(getMessage(msgID, String.valueOf(entryDN), de.getErrorMessage())); break modifyDNProcessing; } } else if (oid.equals(OID_LDAP_NOOP_OPENLDAP_ASSIGNED)) { noOp = true; } else if (oid.equals(OID_LDAP_READENTRY_PREREAD)) { if (c instanceof LDAPAssertionRequestControl) { preReadRequest = (LDAPPreReadRequestControl) c; } else { try { preReadRequest = LDAPPreReadRequestControl.decodeControl(c); requestControls.set(i, preReadRequest); } catch (LDAPException le) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, le); } op.setResultCode(ResultCode.valueOf(le.getResultCode())); op.appendErrorMessage(le.getMessage()); break modifyDNProcessing; } } } else if (oid.equals(OID_LDAP_READENTRY_POSTREAD)) { if (c instanceof LDAPAssertionRequestControl) { postReadRequest = (LDAPPostReadRequestControl) c; } else { try { postReadRequest = LDAPPostReadRequestControl.decodeControl(c); requestControls.set(i, postReadRequest); } catch (LDAPException le) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, le); } op.setResultCode(ResultCode.valueOf(le.getResultCode())); op.appendErrorMessage(le.getMessage()); break modifyDNProcessing; } } } else if (oid.equals(OID_PROXIED_AUTH_V1)) { // The requester must have the PROXIED_AUTH privilige in order to // be able to use this control. if (! clientConnection.hasPrivilege(Privilege.PROXIED_AUTH, op)) { int msgID = MSGID_PROXYAUTH_INSUFFICIENT_PRIVILEGES; op.appendErrorMessage(getMessage(msgID)); op.setResultCode(ResultCode.AUTHORIZATION_DENIED); break modifyDNProcessing; } ProxiedAuthV1Control proxyControl; if (c instanceof ProxiedAuthV1Control) { proxyControl = (ProxiedAuthV1Control) c; } else { try { proxyControl = ProxiedAuthV1Control.decodeControl(c); } catch (LDAPException le) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, le); } op.setResultCode(ResultCode.valueOf(le.getResultCode())); op.appendErrorMessage(le.getMessage()); break modifyDNProcessing; } } Entry authorizationEntry; try { authorizationEntry = proxyControl.getAuthorizationEntry(); } catch (DirectoryException de) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, de); } op.setResultCode(de.getResultCode()); op.appendErrorMessage(de.getErrorMessage()); break modifyDNProcessing; } if (AccessControlConfigManager.getInstance() .getAccessControlHandler().isProxiedAuthAllowed(op, authorizationEntry) == false) { op.setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS); int msgID = MSGID_MODDN_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS; op.appendErrorMessage(getMessage(msgID, String.valueOf(entryDN))); skipPostOperation = true; break modifyDNProcessing; } op.setAuthorizationEntry(authorizationEntry); if (authorizationEntry == null) { op.setProxiedAuthorizationDN(DN.nullDN()); } else { op.setProxiedAuthorizationDN(authorizationEntry.getDN()); } } else if (oid.equals(OID_PROXIED_AUTH_V2)) { // The requester must have the PROXIED_AUTH privilige in order to // be able to use this control. if (! clientConnection.hasPrivilege(Privilege.PROXIED_AUTH, op)) { int msgID = MSGID_PROXYAUTH_INSUFFICIENT_PRIVILEGES; op.appendErrorMessage(getMessage(msgID)); op.setResultCode(ResultCode.AUTHORIZATION_DENIED); break modifyDNProcessing; } ProxiedAuthV2Control proxyControl; if (c instanceof ProxiedAuthV2Control) { proxyControl = (ProxiedAuthV2Control) c; } else { try { proxyControl = ProxiedAuthV2Control.decodeControl(c); } catch (LDAPException le) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, le); } op.setResultCode(ResultCode.valueOf(le.getResultCode())); op.appendErrorMessage(le.getMessage()); break modifyDNProcessing; } } Entry authorizationEntry; try { authorizationEntry = proxyControl.getAuthorizationEntry(); } catch (DirectoryException de) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, de); } op.setResultCode(de.getResultCode()); op.appendErrorMessage(de.getErrorMessage()); break modifyDNProcessing; } if (AccessControlConfigManager.getInstance() .getAccessControlHandler().isProxiedAuthAllowed(op, authorizationEntry) == false) { op.setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS); int msgID = MSGID_MODDN_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS; op.appendErrorMessage(getMessage(msgID, String.valueOf(entryDN))); skipPostOperation = true; break modifyDNProcessing; } op.setAuthorizationEntry(authorizationEntry); if (authorizationEntry == null) { op.setProxiedAuthorizationDN(DN.nullDN()); } else { op.setProxiedAuthorizationDN(authorizationEntry.getDN()); } } // NYI -- Add support for additional controls. else if (c.isCritical()) { Backend backend = DirectoryServer.getBackend(entryDN); if ((backend == null) || (! backend.supportsControl(oid))) { op.setResultCode(ResultCode.UNAVAILABLE_CRITICAL_EXTENSION); int msgID = MSGID_MODDN_UNSUPPORTED_CRITICAL_CONTROL; op.appendErrorMessage(getMessage(msgID, String.valueOf(entryDN), oid)); break modifyDNProcessing; } } } } // Check to see if the client has permission to perform the // modify DN. // FIXME: for now assume that this will check all permission // pertinent to the operation. This includes proxy authorization // and any other controls specified. // FIXME: earlier checks to see if the entry or new superior // already exists may have already exposed sensitive information // to the client. if (AccessControlConfigManager.getInstance() .getAccessControlHandler().isAllowed(op) == false) { op.setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS); int msgID = MSGID_MODDN_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS; op.appendErrorMessage(getMessage(msgID, String.valueOf(entryDN))); skipPostOperation = true; break modifyDNProcessing; } // Duplicate the entry and set its new DN. Also, create an empty list // to hold the attribute-level modifications. Entry newEntry = currentEntry.duplicate(false); newEntry.setDN(newDN); op.setUpdatedEntry(newEntry); // init the modifications op.addModification(null); List<Modification> modifications = op.getModifications(); // If we should delete the old RDN values from the entry, then do so. if (op.deleteOldRDN()) { RDN currentRDN = entryDN.getRDN(); int numValues = currentRDN.getNumValues(); for (int i=0; i < numValues; i++) { LinkedHashSet<AttributeValue> valueSet = new LinkedHashSet<AttributeValue>(1); valueSet.add(currentRDN.getAttributeValue(i)); Attribute a = new Attribute(currentRDN.getAttributeType(i), currentRDN.getAttributeName(i), valueSet); // If the associated attribute type is marked NO-USER-MODIFICATION, // then refuse the update. if (a.getAttributeType().isNoUserModification()) { if (! (op.isInternalOperation() || op.isSynchronizationOperation())) { op.setResultCode(ResultCode.UNWILLING_TO_PERFORM); int msgID = MSGID_MODDN_OLD_RDN_ATTR_IS_NO_USER_MOD; op.appendErrorMessage(getMessage(msgID, String.valueOf(entryDN), a.getName())); break modifyDNProcessing; } } LinkedList<AttributeValue> missingValues = new LinkedList<AttributeValue>(); newEntry.removeAttribute(a, missingValues); if (missingValues.isEmpty()) { modifications.add(new Modification(ModificationType.DELETE, a)); } } } // Add the new RDN values to the entry. int newRDNValues = newRDN.getNumValues(); for (int i=0; i < newRDNValues; i++) { LinkedHashSet<AttributeValue> valueSet = new LinkedHashSet<AttributeValue>(1); valueSet.add(newRDN.getAttributeValue(i)); Attribute a = new Attribute(newRDN.getAttributeType(i), newRDN.getAttributeName(i), valueSet); LinkedList<AttributeValue> duplicateValues = new LinkedList<AttributeValue>(); newEntry.addAttribute(a, duplicateValues); if (duplicateValues.isEmpty()) { // If the associated attribute type is marked NO-USER-MODIFICATION, // then refuse the update. if (a.getAttributeType().isNoUserModification()) { if (! (op.isInternalOperation() || op.isSynchronizationOperation())) { op.setResultCode(ResultCode.UNWILLING_TO_PERFORM); int msgID = MSGID_MODDN_NEW_RDN_ATTR_IS_NO_USER_MOD; op.appendErrorMessage(getMessage(msgID, String.valueOf(entryDN), a.getName())); break modifyDNProcessing; } } else { modifications.add(new Modification(ModificationType.ADD, a)); } } } // If the server is configured to check the schema and the // operation is not a synchronization operation, // make sure that the resulting entry is valid as per the server schema. if ((DirectoryServer.checkSchema()) && (!op.isSynchronizationOperation()) ) { StringBuilder invalidReason = new StringBuilder(); if (! newEntry.conformsToSchema(null, false, true, true, invalidReason)) { op.setResultCode(ResultCode.OBJECTCLASS_VIOLATION); op.appendErrorMessage(getMessage(MSGID_MODDN_VIOLATES_SCHEMA, String.valueOf(entryDN), String.valueOf(invalidReason))); break modifyDNProcessing; } for (int i=0; i < newRDNValues; i++) { AttributeType at = newRDN.getAttributeType(i); if (at.isObsolete()) { op.setResultCode(ResultCode.CONSTRAINT_VIOLATION); op.appendErrorMessage(getMessage( MSGID_MODDN_NEWRDN_ATTR_IS_OBSOLETE, String.valueOf(entryDN), at.getNameOrOID())); break modifyDNProcessing; } } } // Check for and handle a request to cancel this operation. if (op.getCancelRequest() != null) { op.indicateCancelled(op.getCancelRequest()); return; } // Get a count of the current number of modifications. The // pre-operation plugins may alter this list, and we need to be able to // identify which changes were made after they're done. int modCount = op.getModifications().size(); // If the operation is not a synchronization operation, // Invoke the pre-operation modify DN plugins. if (!op.isSynchronizationOperation()) { PreOperationPluginResult preOpResult = pluginConfigManager.invokePreOperationModifyDNPlugins(op); if (preOpResult.connectionTerminated()) { // There's no point in continuing with anything. Log the request // and result and return. op.setResultCode(ResultCode.CANCELED); int msgID = MSGID_CANCELED_BY_PREOP_DISCONNECT; op.appendErrorMessage(getMessage(msgID)); return; } else if (preOpResult.sendResponseImmediately()) { skipPostOperation = true; break modifyDNProcessing; } else if (preOpResult.skipCoreProcessing()) { skipPostOperation = false; break modifyDNProcessing; } } // Check to see if any of the pre-operation plugins made any changes to // the entry. If so, then apply them. if (modifications.size() > modCount) { for (int i=modCount; i < modifications.size(); i++) { Modification m = modifications.get(i); Attribute a = m.getAttribute(); switch (m.getModificationType()) { case ADD: LinkedList<AttributeValue> duplicateValues = new LinkedList<AttributeValue>(); newEntry.addAttribute(a, duplicateValues); break; case DELETE: LinkedList<AttributeValue> missingValues = new LinkedList<AttributeValue>(); newEntry.removeAttribute(a, missingValues); break; case REPLACE: duplicateValues = new LinkedList<AttributeValue>(); newEntry.removeAttribute(a.getAttributeType(), a.getOptions()); newEntry.addAttribute(a, duplicateValues); break; case INCREMENT: List<Attribute> attrList = newEntry.getAttribute(a.getAttributeType(), a.getOptions()); if ((attrList == null) || attrList.isEmpty()) { op.setResultCode(ResultCode.NO_SUCH_ATTRIBUTE); int msgID = MSGID_MODDN_PREOP_INCREMENT_NO_ATTR; op.appendErrorMessage(getMessage(msgID, String.valueOf(entryDN), a.getName())); break modifyDNProcessing; } else if (attrList.size() > 1) { op.setResultCode(ResultCode.CONSTRAINT_VIOLATION); int msgID = MSGID_MODDN_PREOP_INCREMENT_MULTIPLE_VALUES; op.appendErrorMessage(getMessage(msgID, String.valueOf(entryDN), a.getName())); break modifyDNProcessing; } LinkedHashSet<AttributeValue> values = attrList.get(0).getValues(); if ((values == null) || values.isEmpty()) { op.setResultCode(ResultCode.NO_SUCH_ATTRIBUTE); int msgID = MSGID_MODDN_PREOP_INCREMENT_NO_ATTR; op.appendErrorMessage(getMessage(msgID, String.valueOf(entryDN), a.getName())); break modifyDNProcessing; } else if (values.size() > 1) { op.setResultCode(ResultCode.CONSTRAINT_VIOLATION); int msgID = MSGID_MODDN_PREOP_INCREMENT_MULTIPLE_VALUES; op.appendErrorMessage(getMessage(msgID, String.valueOf(entryDN), a.getName())); break modifyDNProcessing; } long currentLongValue; try { AttributeValue v = values.iterator().next(); currentLongValue = Long.parseLong(v.getStringValue()); } catch (Exception e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } op.setResultCode(ResultCode.CONSTRAINT_VIOLATION); int msgID = MSGID_MODDN_PREOP_INCREMENT_VALUE_NOT_INTEGER; op.appendErrorMessage(getMessage(msgID, String.valueOf(entryDN), a.getName())); break modifyDNProcessing; } LinkedHashSet<AttributeValue> newValues = a.getValues(); if ((newValues == null) || newValues.isEmpty()) { op.setResultCode(ResultCode.CONSTRAINT_VIOLATION); int msgID = MSGID_MODDN_PREOP_INCREMENT_NO_AMOUNT; op.appendErrorMessage(getMessage(msgID, String.valueOf(entryDN), a.getName())); break modifyDNProcessing; } else if (newValues.size() > 1) { op.setResultCode(ResultCode.CONSTRAINT_VIOLATION); int msgID = MSGID_MODDN_PREOP_INCREMENT_MULTIPLE_AMOUNTS; op.appendErrorMessage(getMessage(msgID, String.valueOf(entryDN), a.getName())); break modifyDNProcessing; } long incrementAmount; try { AttributeValue v = values.iterator().next(); incrementAmount = Long.parseLong(v.getStringValue()); } catch (Exception e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } op.setResultCode(ResultCode.CONSTRAINT_VIOLATION); int msgID = MSGID_MODDN_PREOP_INCREMENT_AMOUNT_NOT_INTEGER; op.appendErrorMessage(getMessage(msgID, String.valueOf(entryDN), a.getName())); break modifyDNProcessing; } long newLongValue = currentLongValue + incrementAmount; ByteString newValueOS = new ASN1OctetString(String.valueOf(newLongValue)); newValues = new LinkedHashSet<AttributeValue>(1); newValues.add(new AttributeValue(a.getAttributeType(), newValueOS)); List<Attribute> newAttrList = new ArrayList<Attribute>(1); newAttrList.add(new Attribute(a.getAttributeType(), a.getName(), newValues)); newEntry.putAttribute(a.getAttributeType(), newAttrList); break; } } // Make sure that the updated entry still conforms to the server // schema. if (DirectoryServer.checkSchema()) { StringBuilder invalidReason = new StringBuilder(); if (! newEntry.conformsToSchema(null, false, true, true, invalidReason)) { op.setResultCode(ResultCode.OBJECTCLASS_VIOLATION); op.appendErrorMessage(getMessage( MSGID_MODDN_PREOP_VIOLATES_SCHEMA, String.valueOf(entryDN), String.valueOf(invalidReason))); break modifyDNProcessing; } } } // Check for and handle a request to cancel this operation. if (op.getCancelRequest() != null) { op.indicateCancelled(op.getCancelRequest()); return; } // Actually perform the modify DN operation. // This should include taking // care of any synchronization that might be needed. try { // If it is not a private backend, then check to see if the server or // backend is operating in read-only mode. if (! currentBackend.isPrivateBackend()) { switch (DirectoryServer.getWritabilityMode()) { case DISABLED: op.setResultCode(ResultCode.UNWILLING_TO_PERFORM); op.appendErrorMessage(getMessage(MSGID_MODDN_SERVER_READONLY, String.valueOf(entryDN))); break modifyDNProcessing; case INTERNAL_ONLY: if (! (op.isInternalOperation() || op.isSynchronizationOperation())) { op.setResultCode(ResultCode.UNWILLING_TO_PERFORM); op.appendErrorMessage(getMessage(MSGID_MODDN_SERVER_READONLY, String.valueOf(entryDN))); break modifyDNProcessing; } } switch (currentBackend.getWritabilityMode()) { case DISABLED: op.setResultCode(ResultCode.UNWILLING_TO_PERFORM); op.appendErrorMessage(getMessage(MSGID_MODDN_BACKEND_READONLY, String.valueOf(entryDN))); break modifyDNProcessing; case INTERNAL_ONLY: if (! (op.isInternalOperation() || op.isSynchronizationOperation())) { op.setResultCode(ResultCode.UNWILLING_TO_PERFORM); op.appendErrorMessage(getMessage(MSGID_MODDN_BACKEND_READONLY, String.valueOf(entryDN))); break modifyDNProcessing; } } } if (noOp) { op.appendErrorMessage(getMessage(MSGID_MODDN_NOOP)); op.setResultCode(ResultCode.NO_OPERATION); } else { for (SynchronizationProvider provider : DirectoryServer.getSynchronizationProviders()) { try { SynchronizationProviderResult result = provider.doPreOperation(op); if (! result.continueOperationProcessing()) { break modifyDNProcessing; } } catch (DirectoryException de) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, de); } logError(ErrorLogCategory.SYNCHRONIZATION, ErrorLogSeverity.SEVERE_ERROR, MSGID_MODDN_SYNCH_PREOP_FAILED, op.getConnectionID(), op.getOperationID(), getExceptionMessage(de)); op.setResponseData(de); break modifyDNProcessing; } } currentBackend.renameEntry(entryDN, newEntry, op); } if (preReadRequest != null) { Entry entry = currentEntry.duplicate(true); if (! preReadRequest.allowsAttribute( DirectoryServer.getObjectClassAttributeType())) { entry.removeAttribute( DirectoryServer.getObjectClassAttributeType()); } if (! preReadRequest.returnAllUserAttributes()) { Iterator<AttributeType> iterator = entry.getUserAttributes().keySet().iterator(); while (iterator.hasNext()) { AttributeType attrType = iterator.next(); if (! preReadRequest.allowsAttribute(attrType)) { iterator.remove(); } } } if (! preReadRequest.returnAllOperationalAttributes()) { Iterator<AttributeType> iterator = entry.getOperationalAttributes().keySet().iterator(); while (iterator.hasNext()) { AttributeType attrType = iterator.next(); if (! preReadRequest.allowsAttribute(attrType)) { iterator.remove(); } } } // FIXME -- Check access controls on the entry to see if it should // be returned or if any attributes need to be stripped // out.. SearchResultEntry searchEntry = new SearchResultEntry(entry); LDAPPreReadResponseControl responseControl = new LDAPPreReadResponseControl(preReadRequest.getOID(), preReadRequest.isCritical(), searchEntry); op.addResponseControl(responseControl); } if (postReadRequest != null) { Entry entry = newEntry.duplicate(true); if (! postReadRequest.allowsAttribute( DirectoryServer.getObjectClassAttributeType())) { entry.removeAttribute( DirectoryServer.getObjectClassAttributeType()); } if (! postReadRequest.returnAllUserAttributes()) { Iterator<AttributeType> iterator = entry.getUserAttributes().keySet().iterator(); while (iterator.hasNext()) { AttributeType attrType = iterator.next(); if (! postReadRequest.allowsAttribute(attrType)) { iterator.remove(); } } } if (! postReadRequest.returnAllOperationalAttributes()) { Iterator<AttributeType> iterator = entry.getOperationalAttributes().keySet().iterator(); while (iterator.hasNext()) { AttributeType attrType = iterator.next(); if (! postReadRequest.allowsAttribute(attrType)) { iterator.remove(); } } } // FIXME -- Check access controls on the entry to see if it should // be returned or if any attributes need to be stripped // out.. SearchResultEntry searchEntry = new SearchResultEntry(entry); LDAPPostReadResponseControl responseControl = new LDAPPostReadResponseControl(postReadRequest.getOID(), postReadRequest.isCritical(), searchEntry); op.addResponseControl(responseControl); } if (! noOp) { op.setResultCode(ResultCode.SUCCESS); } } catch (DirectoryException de) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, de); } op.setResultCode(de.getResultCode()); op.appendErrorMessage(de.getErrorMessage()); op.setMatchedDN(de.getMatchedDN()); op.setReferralURLs(de.getReferralURLs()); break modifyDNProcessing; } catch (CancelledOperationException coe) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, coe); } CancelResult cancelResult = coe.getCancelResult(); op.setCancelResult(cancelResult); op.setResultCode(cancelResult.getResultCode()); String message = coe.getMessage(); if ((message != null) && (message.length() > 0)) { op.appendErrorMessage(message); } break modifyDNProcessing; } } finally { LockManager.unlock(entryDN, currentLock); LockManager.unlock(newDN, newLock); for (SynchronizationProvider provider : DirectoryServer.getSynchronizationProviders()) { try { provider.doPostOperation(op); } catch (DirectoryException de) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, de); } logError(ErrorLogCategory.SYNCHRONIZATION, ErrorLogSeverity.SEVERE_ERROR, MSGID_MODDN_SYNCH_POSTOP_FAILED, op.getConnectionID(), op.getOperationID(), getExceptionMessage(de)); op.setResponseData(de); break; } } } } // Indicate that it is now too late to attempt to cancel the operation. op.setCancelResult(CancelResult.TOO_LATE); // Invoke the post-operation modify DN plugins. if (! skipPostOperation) { PostOperationPluginResult postOperationResult = pluginConfigManager.invokePostOperationModifyDNPlugins(op); if (postOperationResult.connectionTerminated()) { op.setResultCode(ResultCode.CANCELED); int msgID = MSGID_CANCELED_BY_POSTOP_DISCONNECT; op.appendErrorMessage(getMessage(msgID)); return; } } // Notify any change notification listeners that might be registered with // the server. if (op.getResultCode() == ResultCode.SUCCESS) { for (ChangeNotificationListener changeListener : DirectoryServer.getChangeNotificationListeners()) { try { changeListener.handleModifyDNOperation(op, op.getOriginalEntry(), op.getUpdatedEntry()); } catch (Exception e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } int msgID = MSGID_MODDN_ERROR_NOTIFYING_CHANGE_LISTENER; String message = getMessage(msgID, getExceptionMessage(e)); logError(ErrorLogCategory.CORE_SERVER, ErrorLogSeverity.SEVERE_ERROR, message, msgID); } } } } /** * Attaches the current local operation to the global operation so that opends/tests/unit-tests-testng/src/server/org/opends/server/backends/GenericBackendTestCase.java
@@ -40,7 +40,7 @@ import org.opends.server.core.DeleteOperation; import org.opends.server.core.DirectoryServer; import org.opends.server.core.ModifyOperation; import org.opends.server.core.ModifyDNOperation; import org.opends.server.core.ModifyDNOperationBasis; import org.opends.server.protocols.internal.InternalClientConnection; import org.opends.server.types.AttributeType; import org.opends.server.types.ByteStringFactory; opends/tests/unit-tests-testng/src/server/org/opends/server/backends/SchemaBackendTestCase.java
@@ -40,7 +40,7 @@ import org.opends.server.core.AddOperationBasis; import org.opends.server.core.DeleteOperationBasis; import org.opends.server.core.DirectoryServer; import org.opends.server.core.ModifyDNOperation; import org.opends.server.core.ModifyDNOperationBasis; import org.opends.server.core.SchemaConfigManager; import org.opends.server.protocols.internal.InternalClientConnection; import org.opends.server.protocols.internal.InternalSearchOperation; @@ -309,8 +309,8 @@ InternalClientConnection conn = InternalClientConnection.getRootConnection(); ModifyDNOperation modifyDNOperation = new ModifyDNOperation(conn, conn.nextOperationID(), ModifyDNOperationBasis modifyDNOperation = new ModifyDNOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(), null, currentSchemaDN, newSchemaDN.getRDN(), true, null); opends/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestBackendImpl.java
@@ -34,7 +34,7 @@ import org.opends.server.admin.std.meta.JEBackendCfgDefn; import org.opends.server.admin.std.meta.JEIndexCfgDefn; import org.opends.server.admin.server.AdminTestCaseUtils; import org.opends.server.core.ModifyDNOperation; import org.opends.server.core.ModifyDNOperationBasis; import org.opends.server.core.DirectoryServer; import org.opends.server.protocols.internal.InternalClientConnection; import org.opends.server.protocols.internal.InternalSearchOperation; @@ -1167,7 +1167,7 @@ InternalClientConnection conn = InternalClientConnection.getRootConnection(); ModifyDNOperation modifyDN = new ModifyDNOperation(conn, ModifyDNOperationBasis modifyDN = new ModifyDNOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(), noControls, opends/tests/unit-tests-testng/src/server/org/opends/server/core/GroupManagerTestCase.java
@@ -40,7 +40,7 @@ import org.opends.server.api.Group; import org.opends.server.core.DeleteOperation; import org.opends.server.core.ModifyOperation; import org.opends.server.core.ModifyDNOperation; import org.opends.server.core.ModifyDNOperationBasis; import org.opends.server.extensions.DynamicGroup; import org.opends.server.extensions.StaticGroup; import org.opends.server.extensions.VirtualStaticGroup; @@ -689,7 +689,7 @@ InternalClientConnection conn = InternalClientConnection.getRootConnection(); ModifyDNOperation modifyDNOperation = ModifyDNOperationBasis modifyDNOperation = conn.processModifyDN(groupDN, newRDN, true); assertEquals(modifyDNOperation.getResultCode(), ResultCode.SUCCESS); opends/tests/unit-tests-testng/src/server/org/opends/server/core/TestModifyDNOperation.java
@@ -165,7 +165,7 @@ * * @param modifyDNOperation The operation to be tested. */ private void examineCompletedOperation(ModifyDNOperation modifyDNOperation) private void examineCompletedOperation(ModifyDNOperationBasis modifyDNOperation) { assertTrue(modifyDNOperation.getProcessingStartTime() > 0); assertTrue(modifyDNOperation.getProcessingStopTime() > 0); @@ -185,7 +185,7 @@ * * @param modifyDNOperation The operation to be tested. */ private void examineIncompleteOperation(ModifyDNOperation modifyDNOperation) private void examineIncompleteOperation(ModifyDNOperationBasis modifyDNOperation) { assertTrue(modifyDNOperation.getProcessingStartTime() > 0); assertTrue(modifyDNOperation.getProcessingStopTime() > 0); @@ -206,7 +206,7 @@ * * @param modifyDNOperation The operation to be tested. */ private void examineUnparsedOperation(ModifyDNOperation modifyDNOperation) private void examineUnparsedOperation(ModifyDNOperationBasis modifyDNOperation) { assertTrue(modifyDNOperation.getProcessingStartTime() > 0); assertTrue(modifyDNOperation.getProcessingStopTime() > 0); @@ -232,13 +232,13 @@ InternalClientConnection conn = InternalClientConnection.getRootConnection(); ModifyDNOperation[] modifies = new ModifyDNOperation[] ModifyDNOperationBasis[] modifies = new ModifyDNOperationBasis[] { new ModifyDNOperation(conn, conn.nextOperationID(), conn.nextMessageID(), new ModifyDNOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(), noControls, new ASN1OctetString("cn=test,ou=test"), new ASN1OctetString("cn=test2"), true, new ASN1OctetString("dc=example,dc=com")), new ModifyDNOperation(conn, conn.nextOperationID(), conn.nextMessageID(), new ModifyDNOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(), noControls, DN.decode("cn=test,ou=test"), RDN.decode("cn=test2"), true, DN.decode("dc=example,dc=com")) @@ -256,8 +256,8 @@ InternalClientConnection conn = InternalClientConnection.getRootConnection(); ModifyDNOperation modifyDNOperation = new ModifyDNOperation(conn, conn.nextOperationID(), conn.nextMessageID(), ModifyDNOperationBasis modifyDNOperation = new ModifyDNOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(), noControls, new ASN1OctetString("uid=user.0,ou=People,dc=example,dc=com"), new ASN1OctetString("uid=user.test0"), false, @@ -282,7 +282,7 @@ InvocationCounterPlugin.resetAllCounters(); modifyDNOperation = new ModifyDNOperation(conn, conn.nextOperationID(), conn.nextMessageID(), new ModifyDNOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(), noControls, new ASN1OctetString("uid=user.test0,ou=People,dc=example,dc=com"), new ASN1OctetString("uid=user.0"), true, @@ -315,8 +315,8 @@ InternalClientConnection conn = InternalClientConnection.getRootConnection(); ModifyDNOperation modifyDNOperation = new ModifyDNOperation(conn, conn.nextOperationID(), conn.nextMessageID(), ModifyDNOperationBasis modifyDNOperation = new ModifyDNOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(), noControls, DN.decode("uid=user.0,ou=People,dc=example,dc=com"), RDN.decode("uid=user.test0"), false, @@ -341,7 +341,7 @@ InvocationCounterPlugin.resetAllCounters(); modifyDNOperation = new ModifyDNOperation(conn, conn.nextOperationID(), conn.nextMessageID(), new ModifyDNOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(), noControls, DN.decode("uid=user.test0,ou=People,dc=example,dc=com"), RDN.decode("uid=user.0"), true, @@ -374,8 +374,8 @@ InternalClientConnection conn = InternalClientConnection.getRootConnection(); ModifyDNOperation modifyDNOperation = new ModifyDNOperation(conn, conn.nextOperationID(), conn.nextMessageID(), ModifyDNOperationBasis modifyDNOperation = new ModifyDNOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(), noControls, new ASN1OctetString("uid=user.0,ou=People,dc=example,dc=com"), new ASN1OctetString("uid=user.test0"), true, @@ -400,7 +400,7 @@ InvocationCounterPlugin.resetAllCounters(); modifyDNOperation = new ModifyDNOperation(conn, conn.nextOperationID(), conn.nextMessageID(), new ModifyDNOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(), noControls, new ASN1OctetString("uid=user.test0,ou=People,dc=example,dc=com"), new ASN1OctetString("uid=user.0"), true, @@ -433,8 +433,8 @@ InternalClientConnection conn = InternalClientConnection.getRootConnection(); ModifyDNOperation modifyDNOperation = new ModifyDNOperation(conn, conn.nextOperationID(), conn.nextMessageID(), ModifyDNOperationBasis modifyDNOperation = new ModifyDNOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(), noControls, DN.decode("uid=user.0,ou=People,dc=example,dc=com"), RDN.decode("uid=user.test0"), true, @@ -459,7 +459,7 @@ InvocationCounterPlugin.resetAllCounters(); modifyDNOperation = new ModifyDNOperation(conn, conn.nextOperationID(), conn.nextMessageID(), new ModifyDNOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(), noControls, DN.decode("uid=user.test0,ou=People,dc=example,dc=com"), RDN.decode("uid=user.0"), true, @@ -492,8 +492,8 @@ InternalClientConnection conn = InternalClientConnection.getRootConnection(); ModifyDNOperation modifyDNOperation = new ModifyDNOperation(conn, conn.nextOperationID(), conn.nextMessageID(), ModifyDNOperationBasis modifyDNOperation = new ModifyDNOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(), noControls, new ASN1OctetString("uid=user.0,ou=People,dc=example,dc=com"), new ASN1OctetString("uid=user.test0"), true, @@ -518,7 +518,7 @@ InvocationCounterPlugin.resetAllCounters(); modifyDNOperation = new ModifyDNOperation(conn, conn.nextOperationID(), conn.nextMessageID(), new ModifyDNOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(), noControls, new ASN1OctetString("uid=user.test0,dc=example,dc=com"), new ASN1OctetString("uid=user.0"), true, @@ -551,8 +551,8 @@ InternalClientConnection conn = InternalClientConnection.getRootConnection(); ModifyDNOperation modifyDNOperation = new ModifyDNOperation(conn, conn.nextOperationID(), conn.nextMessageID(), ModifyDNOperationBasis modifyDNOperation = new ModifyDNOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(), noControls, DN.decode("uid=user.0,ou=People,dc=example,dc=com"), RDN.decode("uid=user.test0"), true, @@ -577,7 +577,7 @@ InvocationCounterPlugin.resetAllCounters(); modifyDNOperation = new ModifyDNOperation(conn, conn.nextOperationID(), conn.nextMessageID(), new ModifyDNOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(), noControls, DN.decode("uid=user.test0,dc=example,dc=com"), RDN.decode("uid=user.0"), true, @@ -610,8 +610,8 @@ InternalClientConnection conn = InternalClientConnection.getRootConnection(); ModifyDNOperation modifyDNOperation = new ModifyDNOperation(conn, conn.nextOperationID(), conn.nextMessageID(), ModifyDNOperationBasis modifyDNOperation = new ModifyDNOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(), noControls, DN.decode("uid=user.0,ou=People,dc=example,dc=com"), RDN.decode("cn=Aaccf Amar Test"), true, @@ -637,7 +637,7 @@ InvocationCounterPlugin.resetAllCounters(); modifyDNOperation = new ModifyDNOperation(conn, conn.nextOperationID(), conn.nextMessageID(), new ModifyDNOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(), noControls, DN.decode("cn=Aaccf Amar Test,dc=example,dc=com"), RDN.decode("uid=user.0"), false, @@ -673,8 +673,8 @@ InternalClientConnection conn = InternalClientConnection.getRootConnection(); ModifyDNOperation modifyDNOperation = new ModifyDNOperation(conn, conn.nextOperationID(), conn.nextMessageID(), ModifyDNOperationBasis modifyDNOperation = new ModifyDNOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(), noControls, DN.decode("uid=user.invalid,ou=People,dc=example,dc=com"), RDN.decode("uid=user.test0"), true, @@ -696,8 +696,8 @@ InternalClientConnection conn = InternalClientConnection.getRootConnection(); ModifyDNOperation modifyDNOperation = new ModifyDNOperation(conn, conn.nextOperationID(), conn.nextMessageID(), ModifyDNOperationBasis modifyDNOperation = new ModifyDNOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(), noControls, DN.decode("uid=user.0,ou=People,dc=example,dc=com"), RDN.decode("invalid=invalid"), true, @@ -719,8 +719,8 @@ InternalClientConnection conn = InternalClientConnection.getRootConnection(); ModifyDNOperation modifyDNOperation = new ModifyDNOperation(conn, conn.nextOperationID(), conn.nextMessageID(), ModifyDNOperationBasis modifyDNOperation = new ModifyDNOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(), noControls, DN.decode("uid=user.0,ou=People,dc=example,dc=com"), RDN.decode("uid=user.test0"), true, @@ -742,8 +742,8 @@ InternalClientConnection conn = InternalClientConnection.getRootConnection(); ModifyDNOperation modifyDNOperation = new ModifyDNOperation(conn, conn.nextOperationID(), conn.nextMessageID(), ModifyDNOperationBasis modifyDNOperation = new ModifyDNOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(), noControls, new ASN1OctetString("invalid DN"), new ASN1OctetString("uid=user.test0"), true, @@ -765,8 +765,8 @@ InternalClientConnection conn = InternalClientConnection.getRootConnection(); ModifyDNOperation modifyDNOperation = new ModifyDNOperation(conn, conn.nextOperationID(), conn.nextMessageID(), ModifyDNOperationBasis modifyDNOperation = new ModifyDNOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(), noControls, new ASN1OctetString("uid=user.0,ou=People,dc=example,dc=com"), new ASN1OctetString("invalid RDN"), true, @@ -788,8 +788,8 @@ InternalClientConnection conn = InternalClientConnection.getRootConnection(); ModifyDNOperation modifyDNOperation = new ModifyDNOperation(conn, conn.nextOperationID(), conn.nextMessageID(), ModifyDNOperationBasis modifyDNOperation = new ModifyDNOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(), noControls, new ASN1OctetString("uid=user.0,ou=People,dc=example,dc=com"), new ASN1OctetString("uid=user.test0"), true, @@ -811,8 +811,8 @@ InternalClientConnection conn = InternalClientConnection.getRootConnection(); ModifyDNOperation modifyDNOperation = new ModifyDNOperation(conn, conn.nextOperationID(), conn.nextMessageID(), ModifyDNOperationBasis modifyDNOperation = new ModifyDNOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(), noControls, DN.decode("dc=example,dc=com"), RDN.decode("dc=exampletest"), true, @@ -834,8 +834,8 @@ controls.add(authV1Control); InvocationCounterPlugin.resetAllCounters(); ModifyDNOperation modifyDNOperation = new ModifyDNOperation(proxyUserConn, proxyUserConn.nextOperationID(), ModifyDNOperationBasis modifyDNOperation = new ModifyDNOperationBasis(proxyUserConn, proxyUserConn.nextOperationID(), proxyUserConn.nextMessageID(), controls, new ASN1OctetString("uid=user.0,ou=People,dc=example,dc=com"), new ASN1OctetString("uid=user.test0"), false, @@ -860,7 +860,7 @@ InvocationCounterPlugin.resetAllCounters(); modifyDNOperation = new ModifyDNOperation(proxyUserConn, proxyUserConn.nextOperationID(), new ModifyDNOperationBasis(proxyUserConn, proxyUserConn.nextOperationID(), proxyUserConn.nextMessageID(), controls, new ASN1OctetString("uid=user.test0,ou=People,dc=example,dc=com"), new ASN1OctetString("uid=user.0"), true, @@ -893,8 +893,8 @@ controls.add(authV1Control); InvocationCounterPlugin.resetAllCounters(); ModifyDNOperation modifyDNOperation = new ModifyDNOperation(proxyUserConn, proxyUserConn.nextOperationID(), ModifyDNOperationBasis modifyDNOperation = new ModifyDNOperationBasis(proxyUserConn, proxyUserConn.nextOperationID(), proxyUserConn.nextMessageID(), controls, DN.decode("uid=user.0,ou=People,dc=example,dc=com"), RDN.decode("uid=user.test0"), false, @@ -919,7 +919,7 @@ InvocationCounterPlugin.resetAllCounters(); modifyDNOperation = new ModifyDNOperation(proxyUserConn, proxyUserConn.nextOperationID(), new ModifyDNOperationBasis(proxyUserConn, proxyUserConn.nextOperationID(), proxyUserConn.nextMessageID(), controls, DN.decode("uid=user.test0,ou=People,dc=example,dc=com"), @@ -953,8 +953,8 @@ controls.add(authV1Control); InvocationCounterPlugin.resetAllCounters(); ModifyDNOperation modifyDNOperation = new ModifyDNOperation(proxyUserConn, proxyUserConn.nextOperationID(), ModifyDNOperationBasis modifyDNOperation = new ModifyDNOperationBasis(proxyUserConn, proxyUserConn.nextOperationID(), proxyUserConn.nextMessageID(), controls, DN.decode("uid=user.0,ou=People,dc=example,dc=com"), RDN.decode("uid=user.test0"), false, @@ -978,8 +978,8 @@ controls.add(authV2Control); InvocationCounterPlugin.resetAllCounters(); ModifyDNOperation modifyDNOperation = new ModifyDNOperation(proxyUserConn, proxyUserConn.nextOperationID(), ModifyDNOperationBasis modifyDNOperation = new ModifyDNOperationBasis(proxyUserConn, proxyUserConn.nextOperationID(), proxyUserConn.nextMessageID(), controls, DN.decode("uid=user.0,ou=People,dc=example,dc=com"), RDN.decode("uid=user.test0"), false, @@ -1004,7 +1004,7 @@ InvocationCounterPlugin.resetAllCounters(); modifyDNOperation = new ModifyDNOperation(proxyUserConn, proxyUserConn.nextOperationID(), new ModifyDNOperationBasis(proxyUserConn, proxyUserConn.nextOperationID(), proxyUserConn.nextMessageID(), controls, DN.decode("uid=user.test0,ou=People,dc=example,dc=com"), RDN.decode("uid=user.0"), true, @@ -1037,8 +1037,8 @@ controls.add(authV2Control); InvocationCounterPlugin.resetAllCounters(); ModifyDNOperation modifyDNOperation = new ModifyDNOperation(proxyUserConn, proxyUserConn.nextOperationID(), ModifyDNOperationBasis modifyDNOperation = new ModifyDNOperationBasis(proxyUserConn, proxyUserConn.nextOperationID(), proxyUserConn.nextMessageID(), controls, DN.decode("uid=user.0,ou=People,dc=example,dc=com"), RDN.decode("uid=user.test0"), false, @@ -1063,8 +1063,8 @@ controls.add(authV2Control); InvocationCounterPlugin.resetAllCounters(); ModifyDNOperation modifyDNOperation = new ModifyDNOperation(proxyUserConn, proxyUserConn.nextOperationID(), ModifyDNOperationBasis modifyDNOperation = new ModifyDNOperationBasis(proxyUserConn, proxyUserConn.nextOperationID(), proxyUserConn.nextMessageID(), controls, DN.decode("uid=user.0,ou=People,dc=example,dc=com"), RDN.decode("uid=user.test0"), false, @@ -1091,8 +1091,8 @@ InternalClientConnection conn = InternalClientConnection.getRootConnection(); ModifyDNOperation modifyDNOperation = new ModifyDNOperation(conn, conn.nextOperationID(), conn.nextMessageID(), ModifyDNOperationBasis modifyDNOperation = new ModifyDNOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(), controls, DN.decode("uid=user.0,ou=People,dc=example,dc=com"), RDN.decode("uid=user.test0"), false, opends/tests/unit-tests-testng/src/server/org/opends/server/plugins/LastModPluginTestCase.java
@@ -46,7 +46,7 @@ import org.opends.server.core.AddOperation; import org.opends.server.core.DirectoryServer; import org.opends.server.core.ModifyOperation; import org.opends.server.core.ModifyDNOperation; import org.opends.server.core.ModifyDNOperationBasis; import org.opends.server.protocols.internal.InternalClientConnection; import org.opends.server.types.Attribute; import org.opends.server.types.AttributeType; @@ -390,7 +390,7 @@ assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS); ModifyDNOperation modifyDNOperation = ModifyDNOperationBasis modifyDNOperation = conn.processModifyDN(e.getDN(), RDN.decode("cn=test2"), false); assertEquals(modifyDNOperation.getResultCode(), ResultCode.SUCCESS); opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/internal/InternalClientConnectionTestCase.java
@@ -47,7 +47,7 @@ import org.opends.server.core.DeleteOperation; import org.opends.server.core.DirectoryServer; import org.opends.server.core.ExtendedOperation; import org.opends.server.core.ModifyDNOperation; import org.opends.server.core.ModifyDNOperationBasis; import org.opends.server.core.ModifyOperation; import org.opends.server.protocols.asn1.ASN1OctetString; import org.opends.server.protocols.ldap.LDAPAttribute; @@ -723,7 +723,7 @@ assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS); ModifyDNOperation modifyDNOperation = ModifyDNOperationBasis modifyDNOperation = conn.processModifyDN(new ASN1OctetString("cn=test,o=test"), new ASN1OctetString("cn=test2"), true); assertEquals(modifyDNOperation.getResultCode(), ResultCode.SUCCESS); @@ -756,7 +756,7 @@ assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS); ModifyDNOperation modifyDNOperation = ModifyDNOperationBasis modifyDNOperation = conn.processModifyDN(new ASN1OctetString("cn=test,o=test"), new ASN1OctetString("cn=test2"), true, new ASN1OctetString("dc=example,dc=com")); @@ -791,7 +791,7 @@ assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS); ModifyDNOperation modifyDNOperation = ModifyDNOperationBasis modifyDNOperation = conn.processModifyDN(DN.decode("cn=test,o=test"), RDN.decode("cn=test2"), true); assertEquals(modifyDNOperation.getResultCode(), ResultCode.SUCCESS); @@ -824,7 +824,7 @@ assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS); ModifyDNOperation modifyDNOperation = ModifyDNOperationBasis modifyDNOperation = conn.processModifyDN(DN.decode("cn=test,o=test"), RDN.decode("cn=test2"), true, DN.decode("dc=example,dc=com")); opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/jmx/JmxPrivilegeTestCase.java
@@ -56,7 +56,7 @@ import org.opends.server.core.DeleteOperation; import org.opends.server.core.DeleteOperationBasis; import org.opends.server.core.DirectoryServer; import org.opends.server.core.ModifyDNOperation; import org.opends.server.core.ModifyDNOperationBasis; import org.opends.server.core.ModifyOperation; import org.opends.server.core.ModifyOperationBasis; import org.opends.server.core.SchemaConfigManager; @@ -688,7 +688,7 @@ { assertEquals(conn.hasPrivilege(Privilege.JMX_WRITE, null), hasPrivilege); ModifyDNOperation modifyDNOperation = ModifyDNOperationBasis modifyDNOperation = conn.processModifyDN(DN.decode("cn=Work Queue,cn=config"), RDN.decode("cn=New RDN for Work Queue"), true, null); @@ -1186,8 +1186,8 @@ // Try to rename the entry. ModifyDNOperation modifyDNOperation = new ModifyDNOperation(conn, conn.nextOperationID(), ModifyDNOperationBasis modifyDNOperation = new ModifyDNOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(), controls, e.getDN(), RDN.decode("cn=Proxy V1 Test"), true, null); modifyDNOperation.run(); @@ -1196,7 +1196,7 @@ if (hasProxyPrivilege) { assertEquals(modifyDNOperation.getResultCode(), ResultCode.SUCCESS); newEntryDN = modifyDNOperation.getUpdatedEntry().getDN(); newEntryDN = modifyDNOperation.getNewDN(); } else { @@ -1388,8 +1388,8 @@ // Try to rename the entry. ModifyDNOperation modifyDNOperation = new ModifyDNOperation(conn, conn.nextOperationID(), ModifyDNOperationBasis modifyDNOperation = new ModifyDNOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(), controls, e.getDN(), RDN.decode("cn=Proxy V2 Test"), true, null); modifyDNOperation.run(); @@ -1399,7 +1399,7 @@ { assertEquals(modifyDNOperation.getResultCode(), ResultCode.SUCCESS, "Unexpected moddn failure for user " + authDN); newEntryDN = modifyDNOperation.getUpdatedEntry().getDN(); newEntryDN = modifyDNOperation.getNewDN(); } else { opends/tests/unit-tests-testng/src/server/org/opends/server/replication/UpdateOperationTest.java
@@ -45,7 +45,7 @@ import org.opends.server.core.AddOperationBasis; import org.opends.server.core.DeleteOperationBasis; import org.opends.server.core.DirectoryServer; import org.opends.server.core.ModifyDNOperation; import org.opends.server.core.ModifyDNOperationBasis; import org.opends.server.core.ModifyOperation; import org.opends.server.core.ModifyOperationBasis; import org.opends.server.plugins.ShortCircuitPlugin; @@ -975,7 +975,7 @@ personWithUUIDEntry.getAttributes(), new ArrayList<Attribute>()); // - MODDN parent entry 1 to baseDn2 in the LDAP server ModifyDNOperation modDNOp = new ModifyDNOperation(connection, ModifyDNOperationBasis modDNOp = new ModifyDNOperationBasis(connection, InternalClientConnection.nextOperationID(), InternalClientConnection .nextMessageID(), null, DN.decode("ou=baseDn1,"+baseDn), @@ -1206,7 +1206,7 @@ // Modify the entry DN DN newDN = DN.decode("uid= new person,ou=People,dc=example,dc=com") ; ModifyDNOperation modDNOp = new ModifyDNOperation(connection, ModifyDNOperationBasis modDNOp = new ModifyDNOperationBasis(connection, InternalClientConnection.nextOperationID(), InternalClientConnection .nextMessageID(), null, personEntry.getDN(), RDN .decode("uid=new person"), true, DN opends/tests/unit-tests-testng/src/server/org/opends/server/replication/protocol/SynchronizationMsgTest.java
@@ -42,7 +42,7 @@ import org.opends.server.core.AddOperationBasis; import org.opends.server.core.DeleteOperationBasis; import org.opends.server.core.DirectoryServer; import org.opends.server.core.ModifyDNOperation; import org.opends.server.core.ModifyDNOperationBasis; import org.opends.server.core.ModifyOperationBasis; import org.opends.server.protocols.internal.InternalClientConnection; import org.opends.server.replication.ReplicationTestCase; @@ -79,6 +79,7 @@ import org.opends.server.util.TimeThread; import org.opends.server.workflowelement.localbackend.LocalBackendAddOperation; import org.opends.server.workflowelement.localbackend.LocalBackendDeleteOperation; import org.opends.server.workflowelement.localbackend.LocalBackendModifyDNOperation; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -305,8 +306,8 @@ { InternalClientConnection connection = InternalClientConnection.getRootConnection(); ModifyDNOperation op = new ModifyDNOperation(connection, 1, 1, null, ModifyDNOperationBasis op = new ModifyDNOperationBasis(connection, 1, 1, null, DN.decode(rawDN), RDN.decode(newRdn), deleteOldRdn, (newSuperior.length() != 0 ? DN.decode(newSuperior) : null)); @@ -314,11 +315,13 @@ (short) 123, (short) 45); op.setAttachment(SYNCHROCONTEXT, new ModifyDnContext(cn, "uniqueid", "newparentId")); ModifyDNMsg msg = new ModifyDNMsg(op); LocalBackendModifyDNOperation localOp = new LocalBackendModifyDNOperation(op); ModifyDNMsg msg = new ModifyDNMsg(localOp); ModifyDNMsg generatedMsg = (ModifyDNMsg) ReplicationMessage .generateMsg(msg.getBytes()); Operation generatedOperation = generatedMsg.createOperation(connection); ModifyDNOperation mod2 = (ModifyDNOperation) generatedOperation; ModifyDNOperationBasis mod2 = (ModifyDNOperationBasis) generatedOperation; assertEquals(msg.getChangeNumber(), generatedMsg.getChangeNumber()); assertEquals(op.getRawEntryDN(), mod2.getRawEntryDN()); @@ -327,7 +330,8 @@ assertEquals(op.getRawNewSuperior(), mod2.getRawNewSuperior()); // Create an update message from this op ModifyDNMsg updateMsg = (ModifyDNMsg) UpdateMessage.generateMsg(op, true); ModifyDNMsg updateMsg = (ModifyDNMsg) UpdateMessage.generateMsg(localOp, true); assertEquals(msg.getChangeNumber(), updateMsg.getChangeNumber()); } opends/tests/unit-tests-testng/src/server/org/opends/server/replication/server/ReplicationServerTest.java
@@ -42,7 +42,7 @@ import java.util.TreeSet; import org.opends.server.TestCaseUtils; import org.opends.server.core.ModifyDNOperation; import org.opends.server.core.ModifyDNOperationBasis; import org.opends.server.replication.ReplicationTestCase; import org.opends.server.replication.common.ChangeNumber; import org.opends.server.replication.common.ChangeNumberGenerator; @@ -68,6 +68,7 @@ import org.opends.server.types.ModificationType; import org.opends.server.types.RDN; import org.opends.server.util.TimeThread; import org.opends.server.workflowelement.localbackend.LocalBackendModifyDNOperation; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; @@ -669,12 +670,14 @@ // - ModifyDN cn = new ChangeNumber(time, ts++, brokerIds[0]); ModifyDNOperation op = new ModifyDNOperation(connection, 1, 1, null, DN ModifyDNOperationBasis op = new ModifyDNOperationBasis(connection, 1, 1, null, DN .decode("o=test,dc=example,dc=com"), RDN.decode("o=test2"), true, null); op.setAttachment(SYNCHROCONTEXT, new ModifyDnContext(cn, "uniqueid", "newparentId")); ModifyDNMsg modDNMsg = new ModifyDNMsg(op); LocalBackendModifyDNOperation localOp = new LocalBackendModifyDNOperation(op); ModifyDNMsg modDNMsg = new ModifyDNMsg(localOp); broker1.publish(modDNMsg); if (itest > 0) opends/tests/unit-tests-testng/src/server/org/opends/server/types/PrivilegeTestCase.java
@@ -52,7 +52,7 @@ import org.opends.server.core.DeleteOperation; import org.opends.server.core.DeleteOperationBasis; import org.opends.server.core.DirectoryServer; import org.opends.server.core.ModifyDNOperation; import org.opends.server.core.ModifyDNOperationBasis; import org.opends.server.core.ModifyOperation; import org.opends.server.core.ModifyOperationBasis; import org.opends.server.core.SchemaConfigManager; @@ -597,7 +597,7 @@ { assertEquals(conn.hasPrivilege(Privilege.CONFIG_WRITE, null), hasPrivilege); ModifyDNOperation modifyDNOperation = ModifyDNOperationBasis modifyDNOperation = conn.processModifyDN(DN.decode("cn=Work Queue,cn=config"), RDN.decode("cn=New RDN for Work Queue"), true, null); @@ -1246,8 +1246,8 @@ // Try to rename the entry. ModifyDNOperation modifyDNOperation = new ModifyDNOperation(conn, conn.nextOperationID(), ModifyDNOperationBasis modifyDNOperation = new ModifyDNOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(), controls, e.getDN(), RDN.decode("cn=Proxy V1 Test"), true, null); modifyDNOperation.run(); @@ -1256,7 +1256,7 @@ if (hasProxyPrivilege) { assertEquals(modifyDNOperation.getResultCode(), ResultCode.SUCCESS); newEntryDN = modifyDNOperation.getUpdatedEntry().getDN(); newEntryDN = modifyDNOperation.getNewDN(); } else { @@ -1446,8 +1446,8 @@ // Try to rename the entry. ModifyDNOperation modifyDNOperation = new ModifyDNOperation(conn, conn.nextOperationID(), ModifyDNOperationBasis modifyDNOperation = new ModifyDNOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(), controls, e.getDN(), RDN.decode("cn=Proxy V2 Test"), true, null); modifyDNOperation.run(); @@ -1457,7 +1457,7 @@ { assertEquals(modifyDNOperation.getResultCode(), ResultCode.SUCCESS, "Unexpected moddn failure for user " + authDN); newEntryDN = modifyDNOperation.getUpdatedEntry().getDN(); newEntryDN = modifyDNOperation.getNewDN(); } else {