| | |
| | | * |
| | | * |
| | | * Copyright 2008-2009 Sun Microsystems, Inc. |
| | | * Portions Copyright 2014 ForgeRock AS |
| | | * Portions Copyright 2014-2015 ForgeRock AS |
| | | */ |
| | | package org.opends.server.tasks; |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | import org.forgerock.i18n.slf4j.LocalizedLogger; |
| | | |
| | | |
| | | |
| | | import java.util.List; |
| | | |
| | | import org.opends.server.backends.task.Task; |
| | | import org.opends.server.backends.task.TaskState; |
| | | import org.opends.server.api.ClientConnection; |
| | | import org.opends.server.api.ConnectionHandler; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.types.Attribute; |
| | | import org.opends.server.types.AttributeType; |
| | | import org.forgerock.opendj.ldap.ByteString; |
| | | import org.opends.server.types.DirectoryException; |
| | | import org.opends.server.types.DisconnectReason; |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.Operation; |
| | | import org.opends.server.types.Privilege; |
| | | import org.forgerock.opendj.ldap.ResultCode; |
| | | |
| | | import static org.opends.messages.TaskMessages.*; |
| | | import static org.opends.server.util.ServerConstants.*; |
| | | import static org.opends.server.util.StaticUtils.*; |
| | | |
| | | import java.util.List; |
| | | |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | import org.forgerock.i18n.slf4j.LocalizedLogger; |
| | | import org.forgerock.opendj.ldap.ByteString; |
| | | import org.forgerock.opendj.ldap.ResultCode; |
| | | import org.opends.server.api.ClientConnection; |
| | | import org.opends.server.api.ConnectionHandler; |
| | | import org.opends.server.backends.task.Task; |
| | | import org.opends.server.backends.task.TaskState; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.types.Attribute; |
| | | import org.opends.server.types.AttributeType; |
| | | import org.opends.server.types.DirectoryException; |
| | | import org.opends.server.types.DisconnectReason; |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.Operation; |
| | | import org.opends.server.types.Privilege; |
| | | |
| | | /** |
| | | * This class provides an implementation of a Directory Server task that can be |
| | | * used to terminate a client connection. |
| | | */ |
| | | public class DisconnectClientTask |
| | | extends Task |
| | | public class DisconnectClientTask extends Task |
| | | { |
| | | |
| | | private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); |
| | | |
| | | // Indicates whether to send a notification message to the client. |
| | | /** Indicates whether to send a notification message to the client. */ |
| | | private boolean notifyClient; |
| | | |
| | | // The connection ID for the client connection to terminate. |
| | | /** The connection ID for the client connection to terminate. */ |
| | | private long connectionID; |
| | | |
| | | // The disconnect message to send to the client. |
| | | /** The disconnect message to send to the client. */ |
| | | private LocalizableMessage disconnectMessage; |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public LocalizableMessage getDisplayName() { |
| | | return INFO_TASK_DISCONNECT_CLIENT_NAME.get(); |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void initializeTask() |
| | | throws DirectoryException |
| | | public void initializeTask() throws DirectoryException |
| | | { |
| | | // If the client connection is available, then make sure the client has the |
| | | // DISCONNECT_CLIENT privilege. |
| | |
| | | } |
| | | } |
| | | |
| | | final Entry taskEntry = getTaskEntry(); |
| | | connectionID = getConnectionID(taskEntry); |
| | | if (connectionID < 0) |
| | | { |
| | | LocalizableMessage message = |
| | | ERR_TASK_DISCONNECT_NO_CONN_ID.get(ATTR_TASK_DISCONNECT_CONN_ID); |
| | | throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, message); |
| | | } |
| | | |
| | | // Get the connection ID for the client connection. |
| | | Entry taskEntry = getTaskEntry(); |
| | | connectionID = -1L; |
| | | AttributeType attrType = |
| | | DirectoryServer.getAttributeType(ATTR_TASK_DISCONNECT_CONN_ID, true); |
| | | List<Attribute> attrList = taskEntry.getAttribute(attrType); |
| | | notifyClient = mustNotifyClient(taskEntry); |
| | | disconnectMessage = getDisconnectMessage(taskEntry); |
| | | } |
| | | |
| | | private long getConnectionID(Entry taskEntry) throws DirectoryException |
| | | { |
| | | final AttributeType attrType = DirectoryServer.getAttributeType(ATTR_TASK_DISCONNECT_CONN_ID, true); |
| | | final List<Attribute> attrList = taskEntry.getAttribute(attrType); |
| | | if (attrList != null) |
| | | { |
| | | connIDLoop: |
| | | for (Attribute a : attrList) |
| | | { |
| | | for (ByteString v : a) |
| | | { |
| | | try |
| | | { |
| | | connectionID = Long.parseLong(v.toString()); |
| | | break connIDLoop; |
| | | return Long.parseLong(v.toString()); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | LocalizableMessage message = ERR_TASK_DISCONNECT_INVALID_CONN_ID.get(v); |
| | | throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, |
| | | message, e); |
| | | throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, message, e); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | return -1; |
| | | } |
| | | |
| | | if (connectionID < 0) |
| | | private boolean mustNotifyClient(Entry taskEntry) throws DirectoryException |
| | | { |
| | | LocalizableMessage message = |
| | | ERR_TASK_DISCONNECT_NO_CONN_ID.get(ATTR_TASK_DISCONNECT_CONN_ID); |
| | | throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, |
| | | message); |
| | | } |
| | | |
| | | |
| | | // Determine whether to notify the client. |
| | | notifyClient = false; |
| | | attrType = |
| | | DirectoryServer.getAttributeType(ATTR_TASK_DISCONNECT_NOTIFY_CLIENT, |
| | | true); |
| | | attrList = taskEntry.getAttribute(attrType); |
| | | final AttributeType attrType = DirectoryServer.getAttributeType(ATTR_TASK_DISCONNECT_NOTIFY_CLIENT, true); |
| | | final List<Attribute> attrList = taskEntry.getAttribute(attrType); |
| | | if (attrList != null) |
| | | { |
| | | notifyClientLoop: |
| | | for (Attribute a : attrList) |
| | | { |
| | | for (ByteString v : a) |
| | | { |
| | | String stringValue = toLowerCase(v.toString()); |
| | | if (stringValue.equals("true")) |
| | | final String stringValue = toLowerCase(v.toString()); |
| | | if ("true".equals(stringValue)) |
| | | { |
| | | notifyClient = true; |
| | | break notifyClientLoop; |
| | | return true; |
| | | } |
| | | else if (stringValue.equals("false")) |
| | | else if ("false".equals(stringValue)) |
| | | { |
| | | break notifyClientLoop; |
| | | return false; |
| | | } |
| | | else |
| | | { |
| | | LocalizableMessage message = |
| | | ERR_TASK_DISCONNECT_INVALID_NOTIFY_CLIENT.get(stringValue); |
| | | throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, |
| | | message); |
| | | LocalizableMessage message = ERR_TASK_DISCONNECT_INVALID_NOTIFY_CLIENT.get(stringValue); |
| | | throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, message); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | |
| | | // Get the disconnect message. |
| | | disconnectMessage = INFO_TASK_DISCONNECT_GENERIC_MESSAGE.get(); |
| | | attrType = DirectoryServer.getAttributeType(ATTR_TASK_DISCONNECT_MESSAGE, |
| | | true); |
| | | attrList = taskEntry.getAttribute(attrType); |
| | | private LocalizableMessage getDisconnectMessage(Entry taskEntry) |
| | | { |
| | | AttributeType attrType = DirectoryServer.getAttributeType(ATTR_TASK_DISCONNECT_MESSAGE, true); |
| | | List<Attribute> attrList = taskEntry.getAttribute(attrType); |
| | | if (attrList != null) |
| | | { |
| | | disconnectMessageLoop: |
| | | for (Attribute a : attrList) |
| | | { |
| | | for (ByteString v : a) |
| | | { |
| | | disconnectMessage = LocalizableMessage.raw(v.toString()); |
| | | break disconnectMessageLoop; |
| | | return LocalizableMessage.raw(v.toString()); |
| | | } |
| | | } |
| | | } |
| | | return INFO_TASK_DISCONNECT_GENERIC_MESSAGE.get(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | protected TaskState runTask() |
| | | { |
| | | // Get the specified client connection. |
| | | ClientConnection clientConnection = null; |
| | | final ClientConnection clientConnection = getClientConnection(); |
| | | if (clientConnection == null) |
| | | { |
| | | logger.error(ERR_TASK_DISCONNECT_NO_SUCH_CONNECTION, connectionID); |
| | | return TaskState.COMPLETED_WITH_ERRORS; |
| | | } |
| | | |
| | | clientConnection.disconnect(DisconnectReason.ADMIN_DISCONNECT, notifyClient, disconnectMessage); |
| | | return TaskState.COMPLETED_SUCCESSFULLY; |
| | | } |
| | | |
| | | private ClientConnection getClientConnection() |
| | | { |
| | | for (ConnectionHandler<?> handler : DirectoryServer.getConnectionHandlers()) |
| | | { |
| | | for (ClientConnection c : handler.getClientConnections()) |
| | | { |
| | | if (c.getConnectionID() == connectionID) |
| | | { |
| | | clientConnection = c; |
| | | break; |
| | | return c; |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | // If there is no such client connection, then return an error. Otherwise, |
| | | // terminate it. |
| | | if (clientConnection == null) |
| | | { |
| | | logger.error(ERR_TASK_DISCONNECT_NO_SUCH_CONNECTION, connectionID); |
| | | |
| | | return TaskState.COMPLETED_WITH_ERRORS; |
| | | } |
| | | else |
| | | { |
| | | clientConnection.disconnect(DisconnectReason.ADMIN_DISCONNECT, |
| | | notifyClient, disconnectMessage); |
| | | return TaskState.COMPLETED_SUCCESSFULLY; |
| | | return null; |
| | | } |
| | | } |
| | | } |
| | | |