1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.directory.server.core.shared;
21
22
23 import java.io.IOException;
24 import java.util.Set;
25 import java.util.concurrent.locks.ReentrantReadWriteLock;
26
27 import javax.naming.directory.SearchControls;
28
29 import org.apache.directory.api.ldap.model.constants.SchemaConstants;
30 import org.apache.directory.api.ldap.model.entry.Entry;
31 import org.apache.directory.api.ldap.model.entry.Value;
32 import org.apache.directory.api.ldap.model.exception.LdapException;
33 import org.apache.directory.api.ldap.model.exception.LdapOperationException;
34 import org.apache.directory.api.ldap.model.exception.LdapOtherException;
35 import org.apache.directory.api.ldap.model.filter.EqualityNode;
36 import org.apache.directory.api.ldap.model.filter.ExprNode;
37 import org.apache.directory.api.ldap.model.message.AliasDerefMode;
38 import org.apache.directory.api.ldap.model.name.Dn;
39 import org.apache.directory.api.ldap.model.schema.AttributeType;
40 import org.apache.directory.api.ldap.util.tree.DnNode;
41 import org.apache.directory.server.core.api.CoreSession;
42 import org.apache.directory.server.core.api.DirectoryService;
43 import org.apache.directory.server.core.api.ReferralManager;
44 import org.apache.directory.server.core.api.filtering.EntryFilteringCursor;
45 import org.apache.directory.server.core.api.interceptor.context.SearchOperationContext;
46 import org.apache.directory.server.core.api.partition.Partition;
47 import org.apache.directory.server.core.api.partition.PartitionNexus;
48 import org.apache.directory.server.core.api.partition.PartitionTxn;
49
50
51
52
53
54
55
56
57
58
59 public class ReferralManagerImpl implements ReferralManager
60 {
61
62 private DnNode<Entry> referrals;
63
64
65 private ReentrantReadWriteLock mutex = new ReentrantReadWriteLock();
66
67
68 private AttributeType objectClassAT;
69
70
71
72
73
74
75
76
77
78 public ReferralManagerImpl( DirectoryService directoryService ) throws LdapException
79 {
80 lockWrite();
81
82 try
83 {
84 referrals = new DnNode<>();
85 PartitionNexus nexus = directoryService.getPartitionNexus();
86
87 Set<String> suffixes = nexus.listSuffixes();
88 objectClassAT = directoryService.getSchemaManager().getAttributeType( SchemaConstants.OBJECT_CLASS_AT );
89
90 init( directoryService, suffixes.toArray( new String[]
91 {} ) );
92 }
93 finally
94 {
95 unlock();
96 }
97 }
98
99
100
101
102
103
104
105 @Override
106 public void lockRead()
107 {
108 mutex.readLock().lock();
109 }
110
111
112
113
114
115
116
117 @Override
118 public void lockWrite()
119 {
120 mutex.writeLock().lock();
121 }
122
123
124
125
126
127
128
129 @Override
130 public void unlock()
131 {
132 if ( mutex.isWriteLockedByCurrentThread() )
133 {
134 mutex.writeLock().unlock();
135 }
136 else
137 {
138 mutex.readLock().unlock();
139 }
140 }
141
142
143
144
145
146 @Override
147 public void addReferral( Entry entry )
148 {
149 try
150 {
151 referrals.add( entry.getDn(), entry );
152 }
153 catch ( LdapException ne )
154 {
155
156 }
157 }
158
159
160
161
162
163 @Override
164 public void init( DirectoryService directoryService, String... suffixes ) throws LdapException
165 {
166 ExprNode referralFilter = new EqualityNode<String>( objectClassAT,
167 new Value( objectClassAT, SchemaConstants.REFERRAL_OC ) );
168
169
170 SearchControls searchControl = new SearchControls();
171 searchControl.setReturningObjFlag( false );
172 searchControl.setSearchScope( SearchControls.SUBTREE_SCOPE );
173
174 CoreSession adminSession = directoryService.getAdminSession();
175 PartitionNexus nexus = directoryService.getPartitionNexus();
176
177 for ( String suffix : suffixes )
178 {
179
180 Dn suffixDn = directoryService.getDnFactory().create( suffix );
181
182 SearchOperationContextxt/SearchOperationContext.html#SearchOperationContext">SearchOperationContext searchOperationContext = new SearchOperationContext( adminSession, suffixDn,
183 referralFilter, searchControl );
184
185 Partition partition = nexus.getPartition( suffixDn );
186
187 try ( PartitionTxn partitionTxn = partition.beginReadTransaction() )
188 {
189 searchOperationContext.setAliasDerefMode( AliasDerefMode.DEREF_ALWAYS );
190 searchOperationContext.setTransaction( partitionTxn );
191 searchOperationContext.setPartition( partition );
192 EntryFilteringCursor cursor = nexus.search( searchOperationContext );
193
194 try
195 {
196
197 cursor.beforeFirst();
198
199 while ( cursor.next() )
200 {
201 Entry entry = cursor.get();
202
203
204 lockWrite();
205
206 try
207 {
208
209 addReferral( entry );
210 }
211 finally
212 {
213
214 unlock();
215 }
216 }
217
218 cursor.close();
219 }
220 catch ( Exception e )
221 {
222 throw new LdapOperationException( e.getMessage(), e );
223 }
224 }
225 catch ( IOException ioe )
226 {
227 throw new LdapOtherException( ioe.getMessage(), ioe );
228 }
229 }
230 }
231
232
233
234
235
236 @Override
237 public void remove( DirectoryService directoryService, Dn suffix ) throws Exception
238 {
239 ExprNode referralFilter = new EqualityNode<String>( objectClassAT,
240 new Value( objectClassAT, SchemaConstants.REFERRAL_OC ) );
241
242
243 SearchControls searchControl = new SearchControls();
244 searchControl.setReturningObjFlag( false );
245 searchControl.setSearchScope( SearchControls.SUBTREE_SCOPE );
246
247 CoreSession adminSession = directoryService.getAdminSession();
248 PartitionNexus nexus = directoryService.getPartitionNexus();
249
250
251 SearchOperationContextxt/SearchOperationContext.html#SearchOperationContext">SearchOperationContext searchOperationContext = new SearchOperationContext( adminSession, suffix,
252 referralFilter, searchControl );
253 Partition partition = nexus.getPartition( suffix );
254 searchOperationContext.setPartition( partition );
255 searchOperationContext.setAliasDerefMode( AliasDerefMode.DEREF_ALWAYS );
256
257 try ( PartitionTxn partitionTxn = partition.beginReadTransaction() )
258 {
259 searchOperationContext.setTransaction( partitionTxn );
260 EntryFilteringCursor cursor = nexus.search( searchOperationContext );
261
262
263 cursor.beforeFirst();
264
265 while ( cursor.next() )
266 {
267 Entry entry = cursor.get();
268
269
270 removeReferral( entry );
271 }
272 }
273 }
274
275
276
277
278
279 @Override
280 public boolean hasParentReferral( Dn dn )
281 {
282 DnNode<Entry> referral = referrals.getNode( dn );
283
284 return ( referral != null ) && referral.isLeaf();
285 }
286
287
288
289
290
291 @Override
292 public Entry getParentReferral( Dn dn )
293 {
294 if ( !hasParentReferral( dn ) )
295 {
296 return null;
297 }
298
299 return referrals.getElement( dn );
300 }
301
302
303
304
305
306 @Override
307 public boolean isReferral( Dn dn )
308 {
309 Entry parent = referrals.getElement( dn );
310
311 if ( parent != null )
312 {
313 return dn.equals( parent.getDn() );
314 }
315 else
316 {
317 return false;
318 }
319 }
320
321
322
323
324
325 @Override
326 public void removeReferral( Entry entry ) throws LdapException
327 {
328 referrals.remove( entry.getDn() );
329 }
330 }