001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions Copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2007-2008 Sun Microsystems, Inc. 015 * Portions Copyright 2013-2016 ForgeRock AS. 016 */ 017package org.opends.server.core; 018 019import static org.opends.messages.CoreMessages.*; 020import static org.opends.server.core.DirectoryServer.*; 021import static org.opends.server.loggers.AccessLogger.*; 022 023import java.util.List; 024 025import org.forgerock.i18n.LocalizableMessage; 026import org.forgerock.opendj.ldap.DN; 027import org.forgerock.opendj.ldap.ResultCode; 028import org.opends.server.api.ClientConnection; 029import org.opends.server.types.*; 030import org.opends.server.types.operation.PostOperationAbandonOperation; 031import org.opends.server.types.operation.PreParseAbandonOperation; 032 033/** 034 * This class defines an operation that may be used to abandon an operation 035 * that may already be in progress in the Directory Server. 036 */ 037public class AbandonOperationBasis extends AbstractOperation 038 implements AbandonOperation, 039 PreParseAbandonOperation, 040 PostOperationAbandonOperation 041{ 042 /** The message ID of the operation that should be abandoned. */ 043 private final int idToAbandon; 044 045 /** 046 * Creates a new abandon operation with the provided information. 047 * 048 * @param clientConnection The client connection with which this operation 049 * is associated. 050 * @param operationID The operation ID for this operation. 051 * @param messageID The message ID of the request with which this 052 * operation is associated. 053 * @param requestControls The set of controls included in the request. 054 * @param idToAbandon The message ID of the operation that should be 055 * abandoned. 056 */ 057 public AbandonOperationBasis( 058 ClientConnection clientConnection, 059 long operationID, 060 int messageID, 061 List<Control> requestControls, 062 int idToAbandon) 063 { 064 super(clientConnection, operationID, messageID, requestControls); 065 066 this.idToAbandon = idToAbandon; 067 this.cancelResult = new CancelResult(ResultCode.CANNOT_CANCEL, 068 ERR_CANNOT_CANCEL_ABANDON.get()); 069 } 070 071 /** 072 * Retrieves the message ID of the operation that should be abandoned. 073 * 074 * @return The message ID of the operation that should be abandoned. 075 */ 076 @Override 077 public final int getIDToAbandon() 078 { 079 return idToAbandon; 080 } 081 082 @Override 083 public DN getProxiedAuthorizationDN() 084 { 085 return null; 086 } 087 088 @Override 089 public void setProxiedAuthorizationDN(DN proxiedAuthorizationDN) 090 { 091 } 092 093 @Override 094 public final OperationType getOperationType() 095 { 096 // Note that no debugging will be done in this method because it is a likely 097 // candidate for being called by the logging subsystem. 098 099 return OperationType.ABANDON; 100 } 101 102 @Override 103 public final List<Control> getResponseControls() 104 { 105 // An abandon operation can never have a response, so just return an empty 106 // list. 107 return NO_RESPONSE_CONTROLS; 108 } 109 110 @Override 111 public final void addResponseControl(Control control) 112 { 113 // An abandon operation can never have a response, so just ignore this. 114 } 115 116 @Override 117 public final void removeResponseControl(Control control) 118 { 119 // An abandon operation can never have a response, so just ignore this. 120 } 121 122 /** 123 * Performs the work of actually processing this operation. This 124 * should include all processing for the operation, including 125 * invoking plugins, logging messages, performing access control, 126 * managing synchronization, and any other work that might need to 127 * be done in the course of processing. 128 */ 129 @Override 130 public final void run() 131 { 132 setResultCode(ResultCode.UNDEFINED); 133 134 // Start the processing timer. 135 setProcessingStartTime(); 136 137 logAbandonRequest(this); 138 139 // Create a labeled block of code that we can break out of if a problem is detected. 140abandonProcessing: 141 { 142 // Invoke the pre-parse abandon plugins. 143 if (!processOperationResult(getPluginConfigManager().invokePreParseAbandonPlugins(this))) 144 { 145 break abandonProcessing; 146 } 147 148 // Actually perform the abandon operation. Make sure to set the result 149 // code to reflect whether the abandon was successful and an error message 150 // if it was not. Even though there is no response, the result should 151 // still be logged. 152 // Even though it is technically illegal to send a response for 153 // operations that have been abandoned, it may be a good idea to do so 154 // to ensure that the requestor isn't left hanging. This will be a 155 // configurable option in the server. 156 boolean notifyRequestor = DirectoryServer.notifyAbandonedOperations(); 157 158 LocalizableMessage cancelReason = INFO_CANCELED_BY_ABANDON_REQUEST.get(messageID); 159 160 CancelRequest _cancelRequest = new CancelRequest(notifyRequestor, 161 cancelReason); 162 163 CancelResult result = clientConnection.cancelOperation(idToAbandon, 164 _cancelRequest); 165 166 setResultCode(result.getResultCode()); 167 appendErrorMessage(result.getResponseMessage()); 168 169 if (!processOperationResult(getPluginConfigManager().invokePostOperationAbandonPlugins(this))) 170 { 171 break abandonProcessing; 172 } 173 } 174 175 // Stop the processing timer. 176 setProcessingStopTime(); 177 178 // Log the result of the abandon operation. 179 logAbandonResult(this); 180 } 181 182 @Override 183 public final void toString(StringBuilder buffer) 184 { 185 buffer.append("AbandonOperation(connID="); 186 buffer.append(clientConnection.getConnectionID()); 187 buffer.append(", opID="); 188 buffer.append(operationID); 189 buffer.append(", idToAbandon="); 190 buffer.append(idToAbandon); 191 buffer.append(")"); 192 } 193}