mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

gbellato
07.19.2009 c015616756e6faa64060971753bc77978ae82dec
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
/*
 * 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
 *
 *
 *      Copyright 2008 Sun Microsystems, Inc.
 */
package org.opends.server.core;
import org.opends.messages.Message;
 
 
 
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
 
import org.opends.server.api.ChangeNotificationListener;
import org.opends.server.api.ClientConnection;
import org.opends.server.types.DisconnectReason;
import org.opends.server.types.DN;
import org.opends.server.types.Entry;
import org.opends.server.types.operation.PostResponseAddOperation;
import org.opends.server.types.operation.PostResponseDeleteOperation;
import org.opends.server.types.operation.PostResponseModifyOperation;
import org.opends.server.types.operation.PostResponseModifyDNOperation;
 
import static org.opends.messages.CoreMessages.*;
/**
 * This class provides a data structure which maps an authenticated user DN to
 * the set of client connections authenticated as that user.  Note that a single
 * client connection may be registered with two different user DNs if the client
 * has different authentication and authorization identities.
 * <BR><BR>
 * This class also provides a mechanism for detecting changes to authenticated
 * user entries and notifying the corresponding client connections so that they
 * can update their cached versions.
 */
public class AuthenticatedUsers
       implements ChangeNotificationListener
{
  // The mapping between authenticated user DNs and the associated client
  // connection objects.
  private ConcurrentHashMap<DN,CopyOnWriteArraySet<ClientConnection>>
               userMap;
 
 
 
  /**
   * Creates a new instance of this authenticated users object.
   */
  public AuthenticatedUsers()
  {
    userMap = new ConcurrentHashMap<DN,CopyOnWriteArraySet<ClientConnection>>();
 
    DirectoryServer.registerChangeNotificationListener(this);
  }
 
 
 
  /**
   * Registers the provided user DN and client connection with this object.
   *
   * @param  userDN            The DN of the user associated with the provided
   *                           client connection.
   * @param  clientConnection  The client connection over which the user is
   *                           authenticated.
   */
  public synchronized void put(DN userDN, ClientConnection clientConnection)
  {
    CopyOnWriteArraySet<ClientConnection> connectionSet = userMap.get(userDN);
    if (connectionSet == null)
    {
      connectionSet = new CopyOnWriteArraySet<ClientConnection>();
      connectionSet.add(clientConnection);
      userMap.put(userDN, connectionSet);
    }
    else
    {
      connectionSet.add(clientConnection);
    }
  }
 
 
 
  /**
   * Deregisters the provided user DN and client connection with this object.
   *
   * @param  userDN            The DN of the user associated with the provided
   *                           client connection.
   * @param  clientConnection  The client connection over which the user is
   *                           authenticated.
   */
  public synchronized void remove(DN userDN, ClientConnection clientConnection)
  {
    CopyOnWriteArraySet<ClientConnection> connectionSet = userMap.get(userDN);
    if (connectionSet != null)
    {
      connectionSet.remove(clientConnection);
      if (connectionSet.isEmpty())
      {
        userMap.remove(userDN);
      }
    }
  }
 
 
 
  /**
   * Retrieves the set of client connections authenticated as the specified
   * user.  This method is only intended for internal testing use and should not
   * be called for any other purpose.
   *
   * @param  userDN  The DN of the user for which to retrieve the corresponding
   *                 set of client connections.
   *
   * @return  The set of client connections authenticated as the specified user,
   *          or {@code null} if there are none.
   */
  synchronized CopyOnWriteArraySet<ClientConnection> get(DN userDN)
  {
    return userMap.get(userDN);
  }
 
 
 
  /**
   * Performs any processing that may be required after an add
   * operation.
   *
   * @param  addOperation  The add operation that was performed in the
   *                       server.
   * @param  entry         The entry that was added to the server.
   */
  public void handleAddOperation(
                   PostResponseAddOperation addOperation,
                   Entry entry)
  {
    // No implementation is required for add operations, since a connection
    // can't be authenticated as a user that doesn't exist yet.
  }
 
 
 
  /**
   * Performs any processing that may be required after a delete
   * operation.
   *
   * @param  deleteOperation  The delete operation that was performed
   *                          in the server.
   * @param  entry            The entry that was removed from the
   *                          server.
   */
  public void handleDeleteOperation(
                   PostResponseDeleteOperation deleteOperation,
                   Entry entry)
  {
    // Identify any client connections that may be authenticated or
    // authorized as the user whose entry has been deleted and terminate them.
    CopyOnWriteArraySet<ClientConnection> connectionSet =
         userMap.remove(entry.getDN());
    if (connectionSet != null)
    {
      for (ClientConnection conn : connectionSet)
      {
        Message message = WARN_CLIENTCONNECTION_DISCONNECT_DUE_TO_DELETE.get(
                String.valueOf(entry.getDN()));
 
        conn.disconnect(DisconnectReason.OTHER, true, message);
      }
    }
  }
 
 
 
  /**
   * Performs any processing that may be required after a modify
   * operation.
   *
   * @param  modifyOperation  The modify operation that was performed
   *                          in the server.
   * @param  oldEntry         The entry before it was updated.
   * @param  newEntry         The entry after it was updated.
   */
  public void handleModifyOperation(
                   PostResponseModifyOperation modifyOperation,
                   Entry oldEntry, Entry newEntry)
  {
    // Identify any client connections that may be authenticated or authorized
    // as the user whose entry has been modified and update them with the latest
    // version of the entry.
    CopyOnWriteArraySet<ClientConnection> connectionSet =
         userMap.get(oldEntry.getDN());
    if (connectionSet != null)
    {
      for (ClientConnection conn : connectionSet)
      {
        conn.updateAuthenticationInfo(oldEntry, newEntry);
      }
    }
  }
 
 
 
  /**
   * Performs any processing that may be required after a modify DN
   * operation.
   *
   * @param  modifyDNOperation  The modify DN operation that was
   *                            performed in the server.
   * @param  oldEntry           The entry before it was updated.
   * @param  newEntry           The entry after it was updated.
   */
  public void handleModifyDNOperation(
                   PostResponseModifyDNOperation modifyDNOperation,
                   Entry oldEntry, Entry newEntry)
  {
    // Identify any client connections that may be authenticated or authorized
    // as the user whose entry has been modified and update them with the latest
    // version of the entry.
    CopyOnWriteArraySet<ClientConnection> connectionSet =
         userMap.remove(oldEntry.getDN());
    if (connectionSet != null)
    {
      synchronized (this)
      {
        CopyOnWriteArraySet<ClientConnection> existingNewSet =
             userMap.get(newEntry.getDN());
        if (existingNewSet == null)
        {
          userMap.put(newEntry.getDN(), connectionSet);
        }
        else
        {
          existingNewSet.addAll(connectionSet);
        }
      }
 
      for (ClientConnection conn : connectionSet)
      {
        conn.updateAuthenticationInfo(oldEntry, newEntry);
      }
    }
  }
}