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.collective;
21
22
23 import org.apache.directory.server.core.DirectoryService;
24 import org.apache.directory.server.core.entry.ClonedServerEntry;
25 import org.apache.directory.server.core.entry.DefaultServerAttribute;
26 import org.apache.directory.server.core.entry.ServerEntry;
27 import org.apache.directory.server.core.filtering.EntryFilter;
28 import org.apache.directory.server.core.filtering.EntryFilteringCursor;
29 import org.apache.directory.server.core.interceptor.BaseInterceptor;
30 import org.apache.directory.server.core.interceptor.NextInterceptor;
31 import org.apache.directory.server.core.interceptor.context.AddOperationContext;
32 import org.apache.directory.server.core.interceptor.context.ListOperationContext;
33 import org.apache.directory.server.core.interceptor.context.LookupOperationContext;
34 import org.apache.directory.server.core.interceptor.context.ModifyOperationContext;
35 import org.apache.directory.server.core.interceptor.context.OperationContext;
36 import org.apache.directory.server.core.interceptor.context.SearchOperationContext;
37 import org.apache.directory.server.core.interceptor.context.SearchingOperationContext;
38 import org.apache.directory.server.core.partition.ByPassConstants;
39 import org.apache.directory.server.core.partition.PartitionNexus;
40 import org.apache.directory.server.schema.registries.AttributeTypeRegistry;
41 import org.apache.directory.shared.ldap.constants.SchemaConstants;
42 import org.apache.directory.shared.ldap.entry.EntryAttribute;
43 import org.apache.directory.shared.ldap.entry.Value;
44 import org.apache.directory.shared.ldap.name.LdapDN;
45 import org.apache.directory.shared.ldap.schema.AttributeType;
46
47 import java.util.HashSet;
48 import java.util.Set;
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63 public class CollectiveAttributeInterceptor extends BaseInterceptor
64 {
65
66 private AttributeTypeRegistry atRegistry;
67
68 private PartitionNexus nexus;
69
70 private CollectiveAttributesSchemaChecker collectiveAttributesSchemaChecker;
71
72
73
74
75
76 private final EntryFilter SEARCH_FILTER = new EntryFilter()
77 {
78 public boolean accept( SearchingOperationContext operation, ClonedServerEntry result )
79 throws Exception
80 {
81 LdapDN name = result.getDn();
82
83 if ( name.isNormalized() == false )
84 {
85 name = LdapDN.normalize( name, atRegistry.getNormalizerMapping() );
86 }
87
88 String[] retAttrs = operation.getSearchControls().getReturningAttributes();
89 addCollectiveAttributes( operation, result, retAttrs );
90 return true;
91 }
92 };
93
94 public void init( DirectoryService directoryService ) throws Exception
95 {
96 super.init( directoryService );
97 nexus = directoryService.getPartitionNexus();
98 atRegistry = directoryService.getRegistries().getAttributeTypeRegistry();
99 collectiveAttributesSchemaChecker = new CollectiveAttributesSchemaChecker( nexus, atRegistry );
100 }
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115 private void addCollectiveAttributes( OperationContext opContext, ClonedServerEntry entry,
116 String[] retAttrs ) throws Exception
117 {
118 EntryAttribute collectiveAttributeSubentries =
119 entry.getOriginalEntry().get( SchemaConstants.COLLECTIVE_ATTRIBUTE_SUBENTRIES_AT );
120
121
122
123
124
125 if ( collectiveAttributeSubentries == null )
126 {
127 return;
128 }
129
130
131
132
133
134
135
136 EntryAttribute collectiveExclusions =
137 entry.getOriginalEntry().get( SchemaConstants.COLLECTIVE_EXCLUSIONS_AT );
138 Set<String> exclusions = new HashSet<String>();
139
140 if ( collectiveExclusions != null )
141 {
142 if ( collectiveExclusions.contains( SchemaConstants.EXCLUDE_ALL_COLLECTIVE_ATTRIBUTES_AT_OID )
143 ||
144 collectiveExclusions.contains( SchemaConstants.EXCLUDE_ALL_COLLECTIVE_ATTRIBUTES_AT ) )
145 {
146
147
148
149
150 return;
151 }
152
153 exclusions = new HashSet<String>();
154
155 for ( Value<?> value:collectiveExclusions )
156 {
157 AttributeType attrType = atRegistry.lookup( ( String ) value.get() );
158 exclusions.add( attrType.getOid() );
159 }
160 }
161
162
163
164
165
166
167 if ( retAttrs == null )
168 {
169 retAttrs = SchemaConstants.ALL_USER_ATTRIBUTES_ARRAY;
170 }
171
172
173
174
175 Set<String> retIdsSet = new HashSet<String>( retAttrs.length );
176
177 for ( String retAttr:retAttrs )
178 {
179 if ( retAttr.equals( SchemaConstants.ALL_USER_ATTRIBUTES ) ||
180 retAttr.equals( SchemaConstants.ALL_OPERATIONAL_ATTRIBUTES ) )
181 {
182 retIdsSet.add( retAttr );
183 }
184 else
185 {
186 retIdsSet.add( atRegistry.lookup( retAttr ).getOid() );
187 }
188 }
189
190
191
192
193
194
195 for ( Value<?> value:collectiveAttributeSubentries )
196 {
197 String subentryDnStr = ( String ) value.get();
198 LdapDN subentryDn = new LdapDN( subentryDnStr );
199
200
201
202
203
204
205
206
207 ServerEntry subentry = opContext.lookup( subentryDn, ByPassConstants.LOOKUP_COLLECTIVE_BYPASS );
208
209 for ( AttributeType attributeType:subentry.getAttributeTypes() )
210 {
211 String attrId = attributeType.getName();
212
213 if ( !attributeType.isCollective() )
214 {
215 continue;
216 }
217
218
219
220
221
222 if ( exclusions.contains( attributeType.getOid() ) )
223 {
224 continue;
225 }
226
227 Set<AttributeType> allSuperTypes = getAllSuperTypes( attributeType );
228
229 for ( String retId : retIdsSet )
230 {
231 if ( retId.equals( SchemaConstants.ALL_USER_ATTRIBUTES ) || retId.equals( SchemaConstants.ALL_OPERATIONAL_ATTRIBUTES ) )
232 {
233 continue;
234 }
235
236 AttributeType retType = atRegistry.lookup( retId );
237
238 if ( allSuperTypes.contains( retType ) )
239 {
240 retIdsSet.add( atRegistry.lookup( attrId ).getOid() );
241 break;
242 }
243 }
244
245
246
247
248
249 if ( !( retIdsSet.contains( SchemaConstants.ALL_USER_ATTRIBUTES ) ||
250 retIdsSet.contains( atRegistry.lookup( attrId ).getOid() ) ) )
251 {
252 continue;
253 }
254
255 EntryAttribute subentryColAttr = subentry.get( attrId );
256 EntryAttribute entryColAttr = entry.get( attrId );
257
258
259
260
261 if ( entryColAttr == null )
262 {
263 entryColAttr = new DefaultServerAttribute( attrId, atRegistry.lookup( attrId ) );
264 entry.put( entryColAttr );
265 }
266
267
268
269
270
271 for ( Value<?> subentryColVal:subentryColAttr )
272 {
273 entryColAttr.add( (String)subentryColVal.get() );
274 }
275 }
276 }
277 }
278
279
280 private Set<AttributeType> getAllSuperTypes( AttributeType id ) throws Exception
281 {
282 Set<AttributeType> allSuperTypes = new HashSet<AttributeType>();
283 AttributeType superType = id;
284
285 while ( superType != null )
286 {
287 superType = superType.getSuperior();
288
289 if ( superType != null )
290 {
291 allSuperTypes.add( superType );
292 }
293 }
294
295 return allSuperTypes;
296 }
297
298
299
300
301
302
303
304 public ClonedServerEntry lookup( NextInterceptor nextInterceptor, LookupOperationContext opContext )
305 throws Exception
306 {
307 ClonedServerEntry result = nextInterceptor.lookup( opContext );
308
309 if ( result == null )
310 {
311 return null;
312 }
313
314 if ( ( opContext.getAttrsId() == null ) || ( opContext.getAttrsId().size() == 0 ) )
315 {
316 addCollectiveAttributes( opContext, result, SchemaConstants.ALL_USER_ATTRIBUTES_ARRAY );
317 }
318 else
319 {
320 addCollectiveAttributes( opContext, result, opContext.getAttrsIdArray() );
321 }
322
323 return result;
324 }
325
326
327 public EntryFilteringCursor list( NextInterceptor nextInterceptor, ListOperationContext opContext ) throws Exception
328 {
329 EntryFilteringCursor cursor = nextInterceptor.list( opContext );
330 cursor.addEntryFilter( SEARCH_FILTER );
331 return cursor;
332 }
333
334
335 public EntryFilteringCursor search( NextInterceptor nextInterceptor, SearchOperationContext opContext ) throws Exception
336 {
337 EntryFilteringCursor cursor = nextInterceptor.search( opContext );
338 cursor.addEntryFilter( SEARCH_FILTER );
339 return cursor;
340 }
341
342
343
344
345
346
347
348 public void add( NextInterceptor next, AddOperationContext opContext ) throws Exception
349 {
350 collectiveAttributesSchemaChecker.checkAdd( opContext.getDn(), opContext.getEntry() );
351
352 next.add( opContext );
353 }
354
355
356 public void modify( NextInterceptor next, ModifyOperationContext opContext ) throws Exception
357 {
358 collectiveAttributesSchemaChecker.checkModify( opContext,opContext.getDn(), opContext.getModItems() );
359
360 next.modify( opContext );
361 }
362 }