| | |
| | | import java.util.Map; |
| | | |
| | | 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.Entry; |
| | | import org.opends.server.types.LDAPException; |
| | | 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.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.ObjectClass; |
| | | import org.opends.server.types.Operation; |
| | | import org.opends.server.types.OperationType; |
| | | import org.opends.server.types.RawAttribute; |
| | | import org.opends.server.types.ResultCode; |
| | | import org.opends.server.types.*; |
| | | import org.opends.server.types.operation.PostResponseAddOperation; |
| | | import org.opends.server.types.operation.PreParseAddOperation; |
| | | import org.opends.server.workflowelement.localbackend.LocalBackendAddOperation; |
| | |
| | | // not be a valid DN. |
| | | private ByteString rawEntryDN; |
| | | |
| | | // The cancel request that has been issued for this add operation. |
| | | private CancelRequest cancelRequest; |
| | | |
| | | // The processed DN of the entry to add. |
| | | private DN entryDN; |
| | | |
| | |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public final void disconnectClient(DisconnectReason disconnectReason, |
| | | boolean sendNotification, Message message |
| | | ) |
| | | { |
| | | clientConnection.disconnect(disconnectReason, sendNotification, |
| | | message); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | |
| | | } |
| | | |
| | | |
| | | /** |
| | | * {@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 run() |
| | | { |
| | | // Start the processing timer. |
| | | setProcessingStartTime(); |
| | | setResultCode(ResultCode.UNDEFINED); |
| | | |
| | | // Start the processing timer. |
| | | setProcessingStartTime(); |
| | | |
| | | // Check for and handle a request to cancel this operation. |
| | | if (cancelRequest != null) |
| | | { |
| | | indicateCancelled(cancelRequest); |
| | | setProcessingStopTime(); |
| | | return; |
| | | } |
| | | |
| | | // Log the add request message. |
| | | logAddRequest(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. |
| | | addProcessing: |
| | | try |
| | | { |
| | | // Check for and handle a request to cancel this operation. |
| | | checkIfCanceled(false); |
| | | |
| | | // Invoke the pre-parse add plugins. |
| | | PreParsePluginResult preParseResult = |
| | | PluginResult.PreParse preParseResult = |
| | | pluginConfigManager.invokePreParseAddPlugins(this); |
| | | if (preParseResult.connectionTerminated()) |
| | | |
| | | 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(); |
| | | |
| | | logAddRequest(this); |
| | | logAddResponse(this); |
| | | pluginConfigManager.invokePostResponseAddPlugins(this); |
| | | setResultCode(preParseResult.getResultCode()); |
| | | appendErrorMessage(preParseResult.getErrorMessage()); |
| | | setMatchedDN(preParseResult.getMatchedDN()); |
| | | setReferralURLs(preParseResult.getReferralURLs()); |
| | | return; |
| | | } |
| | | else if (preParseResult.sendResponseImmediately()) |
| | | { |
| | | logAddRequest(this); |
| | | break addProcessing; |
| | | } |
| | | else if (preParseResult.skipCoreProcessing()) |
| | | { |
| | | break addProcessing; |
| | | } |
| | | |
| | | // Log the add request message. |
| | | logAddRequest(this); |
| | | |
| | | |
| | | // Check for a request to cancel this operation. |
| | | if (cancelRequest != null) |
| | | { |
| | | break addProcessing; |
| | | } |
| | | |
| | | // Check for and handle a request to cancel this operation. |
| | | checkIfCanceled(false); |
| | | |
| | | // Process the entry DN and set of attributes to convert them from their |
| | | // raw forms as provided by the client to the forms required for the rest |
| | | // of the add processing. |
| | | DN entryDN = getEntryDN(); |
| | | if (entryDN == null){ |
| | | break addProcessing; |
| | | return; |
| | | } |
| | | |
| | | |
| | | // Retrieve the network group attached to the client connection |
| | | // and get a workflow to process the operation. |
| | | NetworkGroup ng = getClientConnection().getNetworkGroup(); |
| | |
| | | // We have found no workflow for the requested base DN, just return |
| | | // a no such entry result code and stop the processing. |
| | | updateOperationErrMsgAndResCode(); |
| | | break addProcessing; |
| | | 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. |
| | | logAddResponse(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(); |
| | | |
| | | if(cancelRequest == null || cancelResult == null || |
| | | cancelResult.getResultCode() != ResultCode.CANCELED || |
| | | cancelRequest.notifyOriginalRequestor() || |
| | | DirectoryServer.notifyAbandonedOperations()) |
| | | { |
| | | clientConnection.sendResponse(this); |
| | | } |
| | | |
| | | |
| | | // Log the add response message. |
| | | logAddResponse(this); |
| | | |
| | | // 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 add response to the client. |
| | | clientConnection.sendResponse(this); |
| | | |
| | | // Log the add response message. |
| | | logAddResponse(this); |
| | | |
| | | // Notifies any persistent searches that might be registered with the |
| | | // server. |
| | | notifyPersistentSearches(workflowExecuted); |
| | | |
| | | // Invoke the post-response add plugins. |
| | | invokePostResponsePlugins(workflowExecuted); |
| | | } |
| | | |
| | | |