/[Apache-SVN]/directory/apacheds/tags/1.5.3/core/src/main/java/org/apache/directory/server/core/operational/OperationalAttributeInterceptor.java
ViewVC logotype

Contents of /directory/apacheds/tags/1.5.3/core/src/main/java/org/apache/directory/server/core/operational/OperationalAttributeInterceptor.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 676403 - (show annotations) (download)
Sun Jul 13 18:42:08 2008 UTC (15 years, 8 months ago) by akarasulu
File size: 18578 byte(s)
[maven-release-plugin]  copy for tag 1.5.3
1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 *
19 */
20 package org.apache.directory.server.core.operational;
21
22 import java.util.ArrayList;
23 import java.util.HashSet;
24 import java.util.Iterator;
25 import java.util.List;
26 import java.util.Set;
27
28 import org.apache.directory.server.constants.ApacheSchemaConstants;
29 import org.apache.directory.server.core.DirectoryService;
30 import org.apache.directory.server.core.entry.DefaultServerAttribute;
31 import org.apache.directory.server.core.entry.DefaultServerEntry;
32 import org.apache.directory.server.core.entry.ServerAttribute;
33 import org.apache.directory.server.core.entry.ServerEntry;
34 import org.apache.directory.server.core.entry.ServerModification;
35 import org.apache.directory.server.core.entry.ServerSearchResult;
36 import org.apache.directory.server.core.enumeration.SearchResultFilter;
37 import org.apache.directory.server.core.enumeration.SearchResultFilteringEnumeration;
38 import org.apache.directory.server.core.interceptor.BaseInterceptor;
39 import org.apache.directory.server.core.interceptor.Interceptor;
40 import org.apache.directory.server.core.interceptor.NextInterceptor;
41 import org.apache.directory.server.core.interceptor.context.AddOperationContext;
42 import org.apache.directory.server.core.interceptor.context.ListOperationContext;
43 import org.apache.directory.server.core.interceptor.context.LookupOperationContext;
44 import org.apache.directory.server.core.interceptor.context.ModifyOperationContext;
45 import org.apache.directory.server.core.interceptor.context.MoveAndRenameOperationContext;
46 import org.apache.directory.server.core.interceptor.context.MoveOperationContext;
47 import org.apache.directory.server.core.interceptor.context.RenameOperationContext;
48 import org.apache.directory.server.core.interceptor.context.SearchOperationContext;
49 import org.apache.directory.server.core.invocation.Invocation;
50 import org.apache.directory.server.core.invocation.InvocationStack;
51 import org.apache.directory.server.schema.registries.AttributeTypeRegistry;
52 import org.apache.directory.server.schema.registries.Registries;
53 import org.apache.directory.shared.ldap.constants.SchemaConstants;
54 import org.apache.directory.shared.ldap.entry.EntryAttribute;
55 import org.apache.directory.shared.ldap.entry.Modification;
56 import org.apache.directory.shared.ldap.entry.ModificationOperation;
57 import org.apache.directory.shared.ldap.entry.Value;
58 import org.apache.directory.shared.ldap.name.AttributeTypeAndValue;
59 import org.apache.directory.shared.ldap.name.LdapDN;
60 import org.apache.directory.shared.ldap.name.Rdn;
61 import org.apache.directory.shared.ldap.schema.AttributeType;
62 import org.apache.directory.shared.ldap.schema.UsageEnum;
63 import org.apache.directory.shared.ldap.util.DateUtils;
64
65 import javax.naming.NamingEnumeration;
66 import javax.naming.NamingException;
67 import javax.naming.directory.SearchControls;
68
69
70 /**
71 * An {@link Interceptor} that adds or modifies the default attributes
72 * of entries. There are four default attributes for now;
73 * <tt>'creatorsName'</tt>, <tt>'createTimestamp'</tt>, <tt>'modifiersName'</tt>,
74 * and <tt>'modifyTimestamp'</tt>.
75 *
76 * @org.apache.xbean.XBean
77 *
78 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
79 * @version $Rev$, $Date$
80 */
81 public class OperationalAttributeInterceptor extends BaseInterceptor
82 {
83 private final SearchResultFilter DENORMALIZING_SEARCH_FILTER = new SearchResultFilter()
84 {
85 public boolean accept( Invocation invocation, ServerSearchResult result, SearchControls controls )
86 throws NamingException
87 {
88 ServerEntry serverEntry = result.getServerEntry();
89
90 if ( controls.getReturningAttributes() == null )
91 {
92 return true;
93 }
94
95 boolean denormalized = filterDenormalized( serverEntry );
96
97 result.setServerEntry( serverEntry );
98
99 return denormalized;
100 }
101 };
102
103 /**
104 * the database search result filter to register with filter service
105 */
106 private final SearchResultFilter SEARCH_FILTER = new SearchResultFilter()
107 {
108 public boolean accept( Invocation invocation, ServerSearchResult result, SearchControls controls )
109 throws NamingException
110 {
111 ServerEntry serverEntry = result.getServerEntry();
112
113 return controls.getReturningAttributes() != null || filterOperationalAttributes( serverEntry );
114 }
115 };
116
117
118 private AttributeTypeRegistry atRegistry;
119
120 private DirectoryService service;
121
122 private LdapDN subschemaSubentryDn;
123
124 private Registries registries;
125
126
127 /**
128 * Creates the operational attribute management service interceptor.
129 */
130 public OperationalAttributeInterceptor()
131 {
132 }
133
134
135 public void init( DirectoryService directoryService ) throws NamingException
136 {
137 service = directoryService;
138 registries = directoryService.getRegistries();
139 atRegistry = registries.getAttributeTypeRegistry();
140
141 // stuff for dealing with subentries (garbage for now)
142 Value<?> subschemaSubentry = service.getPartitionNexus()
143 .getRootDSE( null ).get( SchemaConstants.SUBSCHEMA_SUBENTRY_AT ).get();
144 subschemaSubentryDn = new LdapDN( (String)subschemaSubentry.get() );
145 subschemaSubentryDn.normalize( directoryService.getRegistries().getAttributeTypeRegistry().getNormalizerMapping() );
146 }
147
148
149 public void destroy()
150 {
151 }
152
153
154 /**
155 * Adds extra operational attributes to the entry before it is added.
156 */
157 public void add( NextInterceptor nextInterceptor, AddOperationContext opContext )
158 throws NamingException
159 {
160 String principal = getPrincipal().getName();
161
162 ServerEntry entry = opContext.getEntry();
163
164 entry.put( SchemaConstants.CREATORS_NAME_AT, principal );
165 entry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
166
167 nextInterceptor.add( opContext );
168 }
169
170
171 public void modify( NextInterceptor nextInterceptor, ModifyOperationContext opContext )
172 throws NamingException
173 {
174 nextInterceptor.modify( opContext );
175
176 if ( opContext.getDn().getNormName().equals( subschemaSubentryDn.getNormName() ) )
177 {
178 return;
179 }
180
181 // -------------------------------------------------------------------
182 // Add the operational attributes for the modifier first
183 // -------------------------------------------------------------------
184
185 List<Modification> modItemList = new ArrayList<Modification>(2);
186
187 AttributeType modifiersNameAt = atRegistry.lookup( SchemaConstants.MODIFIERS_NAME_AT );
188 ServerAttribute attribute = new DefaultServerAttribute(
189 SchemaConstants.MODIFIERS_NAME_AT,
190 modifiersNameAt,
191 getPrincipal().getName());
192
193 Modification modifiers = new ServerModification( ModificationOperation.REPLACE_ATTRIBUTE, attribute );
194 //modifiers.setServerModified();
195 modItemList.add( modifiers );
196
197 AttributeType modifyTimeStampAt = atRegistry.lookup( SchemaConstants.MODIFY_TIMESTAMP_AT );
198 attribute = new DefaultServerAttribute(
199 SchemaConstants.MODIFY_TIMESTAMP_AT,
200 modifyTimeStampAt,
201 DateUtils.getGeneralizedTime() );
202
203 Modification timestamp = new ServerModification( ModificationOperation.REPLACE_ATTRIBUTE, attribute );
204 //timestamp.setServerModified();
205 modItemList.add( timestamp );
206
207 // -------------------------------------------------------------------
208 // Make the modify() call happen
209 // -------------------------------------------------------------------
210
211 ModifyOperationContext newModify = new ModifyOperationContext( registries, opContext.getDn(), modItemList );
212 service.getPartitionNexus().modify( newModify );
213 }
214
215
216 public void rename( NextInterceptor nextInterceptor, RenameOperationContext opContext )
217 throws NamingException
218 {
219 nextInterceptor.rename( opContext );
220
221 // add operational attributes after call in case the operation fails
222 ServerEntry serverEntry = new DefaultServerEntry( registries, opContext.getDn() );
223 serverEntry.put( SchemaConstants.MODIFIERS_NAME_AT, getPrincipal().getName() );
224 serverEntry.put( SchemaConstants.MODIFY_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
225
226 LdapDN newDn = ( LdapDN ) opContext.getDn().clone();
227 newDn.remove( opContext.getDn().size() - 1 );
228 newDn.add( opContext.getNewRdn() );
229 newDn.normalize( atRegistry.getNormalizerMapping() );
230
231 List<Modification> items = ModifyOperationContext.createModItems( serverEntry, ModificationOperation.REPLACE_ATTRIBUTE );
232
233 ModifyOperationContext newModify = new ModifyOperationContext( registries, newDn, items );
234
235 service.getPartitionNexus().modify( newModify );
236 }
237
238
239 public void move( NextInterceptor nextInterceptor, MoveOperationContext opContext ) throws NamingException
240 {
241 nextInterceptor.move( opContext );
242
243 // add operational attributes after call in case the operation fails
244 ServerEntry serverEntry = new DefaultServerEntry( registries, opContext.getDn() );
245 serverEntry.put( SchemaConstants.MODIFIERS_NAME_AT, getPrincipal().getName() );
246 serverEntry.put( SchemaConstants.MODIFY_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
247
248 List<Modification> items = ModifyOperationContext.createModItems( serverEntry, ModificationOperation.REPLACE_ATTRIBUTE );
249
250
251 ModifyOperationContext newModify =
252 new ModifyOperationContext( registries, opContext.getParent(), items );
253
254 service.getPartitionNexus().modify( newModify );
255 }
256
257
258 public void moveAndRename( NextInterceptor nextInterceptor, MoveAndRenameOperationContext opContext )
259 throws NamingException
260 {
261 nextInterceptor.moveAndRename( opContext );
262
263 // add operational attributes after call in case the operation fails
264 ServerEntry serverEntry = new DefaultServerEntry( registries, opContext.getDn() );
265 serverEntry.put( SchemaConstants.MODIFIERS_NAME_AT, getPrincipal().getName() );
266 serverEntry.put( SchemaConstants.MODIFY_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
267
268 List<Modification> items = ModifyOperationContext.createModItems( serverEntry, ModificationOperation.REPLACE_ATTRIBUTE );
269
270 ModifyOperationContext newModify =
271 new ModifyOperationContext( registries,
272 opContext.getParent(), items );
273
274 service.getPartitionNexus().modify( newModify );
275 }
276
277
278 public ServerEntry lookup( NextInterceptor nextInterceptor, LookupOperationContext opContext ) throws NamingException
279 {
280 ServerEntry result = nextInterceptor.lookup( opContext );
281
282 if ( result == null )
283 {
284 return null;
285 }
286
287 if ( opContext.getAttrsId() == null )
288 {
289 filterOperationalAttributes( result );
290 }
291 else
292 {
293 filter( opContext, result );
294 }
295
296 return result;
297 }
298
299
300 public NamingEnumeration<ServerSearchResult> list( NextInterceptor nextInterceptor, ListOperationContext opContext ) throws NamingException
301 {
302 NamingEnumeration<ServerSearchResult> result = nextInterceptor.list( opContext );
303 Invocation invocation = InvocationStack.getInstance().peek();
304
305 return new SearchResultFilteringEnumeration( result, new SearchControls(), invocation, SEARCH_FILTER, "List Operational Filter" );
306 }
307
308
309 public NamingEnumeration<ServerSearchResult> search( NextInterceptor nextInterceptor, SearchOperationContext opContext ) throws NamingException
310 {
311 Invocation invocation = InvocationStack.getInstance().peek();
312 NamingEnumeration<ServerSearchResult> result = nextInterceptor.search( opContext );
313 SearchControls searchCtls = opContext.getSearchControls();
314
315 if ( searchCtls.getReturningAttributes() != null )
316 {
317 if ( service.isDenormalizeOpAttrsEnabled() )
318 {
319 return new SearchResultFilteringEnumeration( result, searchCtls, invocation, DENORMALIZING_SEARCH_FILTER, "Search Operational Filter denormalized" );
320 }
321
322 return result;
323 }
324
325 return new SearchResultFilteringEnumeration( result, searchCtls, invocation, SEARCH_FILTER , "Search Operational Filter");
326 }
327
328
329 /**
330 * Filters out the operational attributes within a search results attributes. The attributes are directly
331 * modified.
332 *
333 * @param attributes the resultant attributes to filter
334 * @return true always
335 * @throws NamingException if there are failures in evaluation
336 */
337 private boolean filterOperationalAttributes( ServerEntry attributes ) throws NamingException
338 {
339 Set<AttributeType> removedAttributes = new HashSet<AttributeType>();
340
341 // Build a list of attributeType to remove
342 for ( AttributeType attributeType:attributes.getAttributeTypes() )
343 {
344 if ( attributeType.getUsage() != UsageEnum.USER_APPLICATIONS )
345 {
346 removedAttributes.add( attributeType );
347 }
348 }
349
350 // Now remove the attributes which are not USERs
351 for ( AttributeType attributeType:removedAttributes )
352 {
353 attributes.removeAttributes( attributeType );
354 }
355
356 return true;
357 }
358
359
360 private void filter( LookupOperationContext lookupContext, ServerEntry entry ) throws NamingException
361 {
362 LdapDN dn = lookupContext.getDn();
363 List<String> ids = lookupContext.getAttrsId();
364
365 // still need to protect against returning op attrs when ids is null
366 if ( ids == null )
367 {
368 filterOperationalAttributes( entry );
369 return;
370 }
371
372 Set<AttributeType> attributeTypes = entry.getAttributeTypes();
373
374 if ( dn.size() == 0 )
375 {
376 for ( AttributeType attributeType:attributeTypes )
377 {
378 if ( !ids.contains( attributeType.getOid() ) )
379 {
380 entry.removeAttributes( attributeType );
381 }
382 }
383 }
384
385 denormalizeEntryOpAttrs( entry );
386
387 // do nothing past here since this explicity specifies which
388 // attributes to include - backends will automatically populate
389 // with right set of attributes using ids array
390 }
391
392
393 public void denormalizeEntryOpAttrs( ServerEntry entry ) throws NamingException
394 {
395 if ( service.isDenormalizeOpAttrsEnabled() )
396 {
397 EntryAttribute attr = entry.get( SchemaConstants.CREATORS_NAME_AT );
398
399 if ( attr != null )
400 {
401 LdapDN creatorsName = new LdapDN( attr.getString() );
402
403 attr.clear();
404 attr.add( denormalizeTypes( creatorsName ).getUpName() );
405 }
406
407 attr = entry.get( SchemaConstants.MODIFIERS_NAME_AT );
408
409 if ( attr != null )
410 {
411 LdapDN modifiersName = new LdapDN( attr.getString() );
412
413 attr.clear();
414 attr.add( denormalizeTypes( modifiersName ).getUpName() );
415 }
416
417 attr = entry.get( ApacheSchemaConstants.SCHEMA_MODIFIERS_NAME_AT );
418
419 if ( attr != null )
420 {
421 LdapDN modifiersName = new LdapDN( attr.getString() );
422
423 attr.clear();
424 attr.add( denormalizeTypes( modifiersName ).getUpName() );
425 }
426 }
427 }
428
429
430 /**
431 * Does not create a new DN but alters existing DN by using the first
432 * short name for an attributeType definition.
433 *
434 * @param dn the normalized distinguished name
435 * @return the distinuished name denormalized
436 * @throws NamingException if there are problems denormalizing
437 */
438 public LdapDN denormalizeTypes( LdapDN dn ) throws NamingException
439 {
440 LdapDN newDn = new LdapDN();
441
442 for ( int ii = 0; ii < dn.size(); ii++ )
443 {
444 Rdn rdn = dn.getRdn( ii );
445 if ( rdn.size() == 0 )
446 {
447 newDn.add( new Rdn() );
448 continue;
449 }
450 else if ( rdn.size() == 1 )
451 {
452 String name = atRegistry.lookup( rdn.getNormType() ).getName();
453 String value = (String)rdn.getAtav().getNormValue();
454 newDn.add( new Rdn( name, name, value, value ) );
455 continue;
456 }
457
458 // below we only process multi-valued rdns
459 StringBuffer buf = new StringBuffer();
460
461 for ( Iterator<AttributeTypeAndValue> atavs = rdn.iterator(); atavs.hasNext(); /**/ )
462 {
463 AttributeTypeAndValue atav = atavs.next();
464 String type = atRegistry.lookup( rdn.getNormType() ).getName();
465 buf.append( type ).append( '=' ).append( atav.getNormValue() );
466
467 if ( atavs.hasNext() )
468 {
469 buf.append( '+' );
470 }
471 }
472
473 newDn.add( new Rdn(buf.toString()) );
474 }
475
476 return newDn;
477 }
478
479
480 private boolean filterDenormalized( ServerEntry entry ) throws NamingException
481 {
482 denormalizeEntryOpAttrs( entry );
483 return true;
484 }
485 }

Properties

Name Value
svn:eol-style native
svn:keywords Rev Revision Date Id

infrastructure at apache.org
ViewVC Help
Powered by ViewVC 1.1.26