| | |
| | | import java.util.List; |
| | | |
| | | import org.opends.server.api.ClientConnection; |
| | | import org.opends.server.api.plugin.PreParsePluginResult; |
| | | import org.opends.server.api.plugin.PluginResult; |
| | | import org.opends.server.loggers.debug.DebugLogger; |
| | | import org.opends.server.loggers.debug.DebugTracer; |
| | | import org.opends.server.protocols.asn1.ASN1OctetString; |
| | | import org.opends.server.protocols.ldap.LDAPAttribute; |
| | | import org.opends.server.types.LDAPException; |
| | | import org.opends.server.protocols.ldap.LDAPModification; |
| | | import org.opends.server.types.AttributeValue; |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.Operation; |
| | | import org.opends.server.types.RawModification; |
| | | 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.DN; |
| | | import org.opends.server.types.DebugLogLevel; |
| | | import org.opends.server.types.DirectoryException; |
| | | import org.opends.server.types.DisconnectReason; |
| | | import org.opends.server.types.Modification; |
| | | import org.opends.server.types.OperationType; |
| | | import org.opends.server.types.ResultCode; |
| | | import org.opends.server.types.*; |
| | | import org.opends.server.types.operation.PostResponseModifyOperation; |
| | | import org.opends.server.types.operation.PreParseModifyOperation; |
| | | import org.opends.server.workflowelement.localbackend.*; |
| | |
| | | // The set of modifications for this modify operation. |
| | | private List<Modification> modifications; |
| | | |
| | | // The cancel request that has been issued for this modify operation. |
| | | CancelRequest cancelRequest; |
| | | |
| | | // The change number that has been assigned to this operation. |
| | | private long changeNumber; |
| | | |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public final void disconnectClient(DisconnectReason disconnectReason, |
| | | boolean sendNotification, Message message |
| | | ) |
| | | { |
| | | clientConnection.disconnect(disconnectReason, sendNotification, |
| | | message); |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public final OperationType getOperationType() |
| | | { |
| | | // Note that no debugging will be done in this method because it is a likely |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | 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} |
| | | */ |
| | | public final CancelRequest getCancelRequest() |
| | | { |
| | | return cancelRequest; |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean setCancelRequest(CancelRequest cancelRequest) |
| | | { |
| | | this.cancelRequest = cancelRequest; |
| | | return true; |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public final void toString(StringBuilder buffer) |
| | | { |
| | | buffer.append("ModifyOperation(connID="); |
| | |
| | | { |
| | | setResultCode(ResultCode.UNDEFINED); |
| | | |
| | | // 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; |
| | | } |
| | | // Log the modify request message. |
| | | logModifyRequest(this); |
| | | |
| | | // Get the plugin config manager that will be used for invoking plugins. |
| | | PluginConfigManager pluginConfigManager = |
| | | DirectoryServer.getPluginConfigManager(); |
| | | |
| | | // This flag is set to true as soon as a workflow has been executed. |
| | | boolean workflowExecuted = false; |
| | | |
| | | |
| | | // Create a labeled block of code that we can break out of if a problem is |
| | | // detected. |
| | | modifyProcessing: |
| | | try |
| | | { |
| | | // Check for and handle a request to cancel this operation. |
| | | checkIfCanceled(false); |
| | | |
| | | // Invoke the pre-parse modify plugins. |
| | | PreParsePluginResult preParseResult = |
| | | pluginConfigManager.invokePreParseModifyPlugins(this); |
| | | if (preParseResult.connectionTerminated()) |
| | | PluginResult.PreParse preParseResult = |
| | | pluginConfigManager.invokePreParseModifyPlugins(this); |
| | | |
| | | if(!preParseResult.continueProcessing()) |
| | | { |
| | | // There's no point in continuing with anything. Log the request and |
| | | // result and return. |
| | | setResultCode(ResultCode.CANCELED); |
| | | |
| | | appendErrorMessage(ERR_CANCELED_BY_PREPARSE_DISCONNECT.get()); |
| | | |
| | | setProcessingStopTime(); |
| | | |
| | | logModifyRequest(this); |
| | | logModifyResponse(this); |
| | | pluginConfigManager.invokePostResponseModifyPlugins(this); |
| | | setResultCode(preParseResult.getResultCode()); |
| | | appendErrorMessage(preParseResult.getErrorMessage()); |
| | | setMatchedDN(preParseResult.getMatchedDN()); |
| | | setReferralURLs(preParseResult.getReferralURLs()); |
| | | return; |
| | | } |
| | | else if (preParseResult.sendResponseImmediately()) |
| | | { |
| | | logModifyRequest(this); |
| | | break modifyProcessing; |
| | | } |
| | | else if (preParseResult.skipCoreProcessing()) |
| | | { |
| | | break modifyProcessing; |
| | | } |
| | | |
| | | // Log the modify request message. |
| | | logModifyRequest(this); |
| | | |
| | | // Check for a request to cancel this operation. |
| | | if (getCancelRequest() != null) |
| | | { |
| | | break modifyProcessing; |
| | | } |
| | | // Check for and handle a request to cancel this operation. |
| | | checkIfCanceled(false); |
| | | |
| | | |
| | | // Process the entry DN to convert it from the raw form to the form |
| | | // required for the rest of the modify processing. |
| | | DN entryDN = getEntryDN(); |
| | | if (entryDN == null){ |
| | | break modifyProcessing; |
| | | return; |
| | | } |
| | | |
| | | |
| | |
| | | // We have found no workflow for the requested base DN, just return |
| | | // a no such entry result code and stop the processing. |
| | | updateOperationErrMsgAndResCode(); |
| | | break modifyProcessing; |
| | | return; |
| | | } |
| | | workflow.execute(this); |
| | | workflowExecuted = true; |
| | | |
| | | } // end of processing block |
| | | |
| | | |
| | | // Check for a terminated connection. |
| | | if (getCancelResult() == CancelResult.CANCELED) |
| | | { |
| | | // Stop the processing timer. |
| | | setProcessingStopTime(); |
| | | |
| | | // Log the add response message. |
| | | logModifyResponse(this); |
| | | |
| | | return; |
| | | } |
| | | |
| | | // Check for and handle a request to cancel this operation. |
| | | if (cancelRequest != null) |
| | | catch(CanceledOperationException coe) |
| | | { |
| | | indicateCancelled(cancelRequest); |
| | | if (debugEnabled()) |
| | | { |
| | | TRACER.debugCaught(DebugLogLevel.ERROR, coe); |
| | | } |
| | | |
| | | setResultCode(ResultCode.CANCELED); |
| | | cancelResult = new CancelResult(ResultCode.CANCELED, null); |
| | | |
| | | appendErrorMessage(coe.getCancelRequest().getCancelReason()); |
| | | } |
| | | finally |
| | | { |
| | | // Stop the processing timer. |
| | | setProcessingStopTime(); |
| | | |
| | | // Log the modify response message. |
| | | if(cancelRequest == null || cancelResult == null || |
| | | cancelResult.getResultCode() != ResultCode.CANCELED || |
| | | cancelRequest.notifyOriginalRequestor() || |
| | | DirectoryServer.notifyAbandonedOperations()) |
| | | { |
| | | clientConnection.sendResponse(this); |
| | | } |
| | | |
| | | // Log the modify response. |
| | | logModifyResponse(this); |
| | | |
| | | // Invoke the post-response modify plugins. |
| | | // Notifies any persistent searches that might be registered with the |
| | | // server. |
| | | notifyPersistentSearches(workflowExecuted); |
| | | |
| | | // Invoke the post-response add plugins. |
| | | invokePostResponsePlugins(workflowExecuted); |
| | | |
| | | return; |
| | | // If no cancel result, set it |
| | | if(cancelResult == null) |
| | | { |
| | | cancelResult = new CancelResult(ResultCode.TOO_LATE, null); |
| | | } |
| | | } |
| | | |
| | | // Indicate that it is now too late to attempt to cancel the operation. |
| | | setCancelResult(CancelResult.TOO_LATE); |
| | | |
| | | // Stop the processing timer. |
| | | setProcessingStopTime(); |
| | | |
| | | // Send the modify response to the client. |
| | | getClientConnection().sendResponse(this); |
| | | |
| | | // Log the modify response. |
| | | logModifyResponse(this); |
| | | |
| | | // Notifies any persistent searches that might be registered with the |
| | | // server. |
| | | notifyPersistentSearches(workflowExecuted); |
| | | |
| | | // Invoke the post-response modify plugins. |
| | | invokePostResponsePlugins(workflowExecuted); |
| | | } |
| | | |
| | | |