1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.ldap.server.operational;
18
19
20 import org.apache.ldap.common.schema.AttributeType;
21 import org.apache.ldap.common.schema.UsageEnum;
22 import org.apache.ldap.common.util.DateUtils;
23 import org.apache.ldap.server.RootNexus;
24 import org.apache.ldap.server.interceptor.BaseInterceptor;
25 import org.apache.ldap.server.interceptor.InterceptorContext;
26 import org.apache.ldap.server.interceptor.NextInterceptor;
27 import org.apache.ldap.server.db.ResultFilteringEnumeration;
28 import org.apache.ldap.server.db.SearchResultFilter;
29 import org.apache.ldap.server.invocation.*;
30 import org.apache.ldap.server.schema.AttributeTypeRegistry;
31
32 import javax.naming.Name;
33 import javax.naming.NamingEnumeration;
34 import javax.naming.NamingException;
35 import javax.naming.directory.*;
36 import javax.naming.ldap.LdapContext;
37 import java.util.HashSet;
38
39
40 /***
41 * An {@link org.apache.ldap.server.interceptor.Interceptor} that adds or modifies the default attributes
42 * of entries. There are four default attributes for now;<code>'creatorsName'
43 * </code>, <code>'createTimestamp'</code>, <code>'modifiersName'</code>, and
44 * <code>'modifyTimestamp'</code>.
45 *
46 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
47 * @version $Rev: 159266 $, $Date: 2005-03-28 12:30:19 -0500 (Mon, 28 Mar 2005) $
48 */
49 public class OperationalAttributeService extends BaseInterceptor
50 {
51 /***
52 * the database search result filter to register with filter service
53 */
54 private final SearchResultFilter SEARCH_FILTER = new SearchResultFilter()
55 {
56 public boolean accept( LdapContext ctx, SearchResult result, SearchControls controls )
57 throws NamingException
58 {
59 if ( controls.getReturningAttributes() == null )
60 {
61 return filter( result.getAttributes() );
62 }
63
64 return true;
65 }
66 };
67
68 /***
69 * the root nexus of the system
70 */
71 private RootNexus nexus;
72
73 private AttributeTypeRegistry registry;
74
75
76 /***
77 * Creates the operational attribute management service interceptor.
78 */
79 public OperationalAttributeService()
80 {
81 }
82
83
84 public void init( InterceptorContext ctx ) throws NamingException
85 {
86 nexus = ctx.getRootNexus();
87 registry = ctx.getGlobalRegistries().getAttributeTypeRegistry();
88 }
89
90
91 public void destroy()
92 {
93 }
94
95
96 /***
97 * Adds extra operational attributes to the entry before it is added.
98 */
99 protected void process( NextInterceptor nextInterceptor, Add call ) throws NamingException
100 {
101 String principal = getPrincipal( call ).getName();
102 Attributes entry = call.getAttributes();
103
104 BasicAttribute attribute = new BasicAttribute( "creatorsName" );
105 attribute.add( principal );
106 entry.put( attribute );
107
108 attribute = new BasicAttribute( "createTimestamp" );
109 attribute.add( DateUtils.getGeneralizedTime() );
110 entry.put( attribute );
111
112 nextInterceptor.process( call );
113 }
114
115
116 protected void process( NextInterceptor nextInterceptor, Modify call ) throws NamingException
117 {
118 nextInterceptor.process( call );
119
120
121 Attributes attributes = new BasicAttributes();
122 BasicAttribute attribute = new BasicAttribute( "modifiersName" );
123 attribute.add( getPrincipal( call ).getName() );
124 attributes.put( attribute );
125
126 attribute = new BasicAttribute( "modifyTimestamp" );
127 attribute.add( DateUtils.getGeneralizedTime() );
128 attributes.put( attribute );
129
130 nexus.modify( call.getName(), DirContext.REPLACE_ATTRIBUTE, attributes );
131 }
132
133
134 protected void process( NextInterceptor nextInterceptor, ModifyMany call ) throws NamingException
135 {
136 nextInterceptor.process( call );
137
138
139 Attributes attributes = new BasicAttributes();
140 BasicAttribute attribute = new BasicAttribute( "modifiersName" );
141 attribute.add( getPrincipal( call ).getName() );
142 attributes.put( attribute );
143
144 attribute = new BasicAttribute( "modifyTimestamp" );
145 attribute.add( DateUtils.getGeneralizedTime() );
146 attributes.put( attribute );
147
148 nexus.modify( call.getName(), DirContext.REPLACE_ATTRIBUTE, attributes );
149 }
150
151
152 protected void process( NextInterceptor nextInterceptor, ModifyRN call ) throws NamingException
153 {
154 nextInterceptor.process( call );
155
156
157 Attributes attributes = new BasicAttributes();
158 BasicAttribute attribute = new BasicAttribute( "modifiersName" );
159 attribute.add( getPrincipal( call ).getName() );
160 attributes.put( attribute );
161
162 attribute = new BasicAttribute( "modifyTimestamp" );
163 attribute.add( DateUtils.getGeneralizedTime() );
164 attributes.put( attribute );
165
166 Name newDn = call.getName().getSuffix( 1 ).add( call.getNewRelativeName() );
167 nexus.modify( newDn, DirContext.REPLACE_ATTRIBUTE, attributes );
168 }
169
170
171 protected void process( NextInterceptor nextInterceptor, Move call ) throws NamingException
172 {
173 nextInterceptor.process( call );
174
175
176 Attributes attributes = new BasicAttributes();
177 BasicAttribute attribute = new BasicAttribute( "modifiersName" );
178 attribute.add( getPrincipal( call ).getName() );
179 attributes.put( attribute );
180
181 attribute = new BasicAttribute( "modifyTimestamp" );
182 attribute.add( DateUtils.getGeneralizedTime() );
183 attributes.put( attribute );
184
185 nexus.modify( call.getNewParentName(), DirContext.REPLACE_ATTRIBUTE, attributes );
186 }
187
188
189 protected void process( NextInterceptor nextInterceptor, MoveAndModifyRN call ) throws NamingException
190 {
191 nextInterceptor.process( call );
192
193
194 Attributes attributes = new BasicAttributes();
195 BasicAttribute attribute = new BasicAttribute( "modifiersName" );
196 attribute.add( getPrincipal( call ).getName() );
197 attributes.put( attribute );
198
199 attribute = new BasicAttribute( "modifyTimestamp" );
200 attribute.add( DateUtils.getGeneralizedTime() );
201 attributes.put( attribute );
202
203 nexus.modify( call.getNewParentName(), DirContext.REPLACE_ATTRIBUTE, attributes );
204 }
205
206
207 protected void process( NextInterceptor nextInterceptor, Lookup call ) throws NamingException
208 {
209 nextInterceptor.process( call );
210
211 Attributes attributes = ( Attributes ) call.getReturnValue();
212 Attributes retval = ( Attributes ) attributes.clone();
213 filter( retval );
214 call.setReturnValue( retval );
215 }
216
217
218 protected void process( NextInterceptor nextInterceptor, LookupWithAttrIds call ) throws NamingException
219 {
220 nextInterceptor.process( call );
221
222 Attributes attributes = ( Attributes ) call.getReturnValue();
223 if ( attributes == null )
224 {
225 return;
226 }
227
228 Attributes retval = ( Attributes ) attributes.clone();
229 filter( call.getName(), retval, call.getAttributeIds() );
230 call.setReturnValue( retval );
231 }
232
233
234 protected void process( NextInterceptor nextInterceptor, List call ) throws NamingException
235 {
236 nextInterceptor.process( call );
237
238 NamingEnumeration e;
239 ResultFilteringEnumeration retval;
240 LdapContext ctx = ( LdapContext ) call.getContextStack().peek();
241 e = ( NamingEnumeration ) call.getReturnValue();
242 retval = new ResultFilteringEnumeration( e, new SearchControls(), ctx, SEARCH_FILTER );
243 call.setReturnValue( retval );
244 }
245
246
247 protected void process( NextInterceptor nextInterceptor, Search call ) throws NamingException
248 {
249 nextInterceptor.process( call );
250
251 SearchControls searchControls = call.getControls();
252 if ( searchControls.getReturningAttributes() != null )
253 {
254 return;
255 }
256
257 NamingEnumeration e;
258 ResultFilteringEnumeration retval;
259 LdapContext ctx = ( LdapContext ) call.getContextStack().peek();
260 e = ( NamingEnumeration ) call.getReturnValue();
261 retval = new ResultFilteringEnumeration( e, searchControls, ctx, SEARCH_FILTER );
262 call.setReturnValue( retval );
263 }
264
265
266 /***
267 * Filters out the operational attributes within a search results attributes. The attributes are directly
268 * modified.
269 *
270 * @param attributes the resultant attributes to filter
271 * @return true always
272 */
273 private boolean filter( Attributes attributes ) throws NamingException
274 {
275 NamingEnumeration list = attributes.getIDs();
276
277 while ( list.hasMore() )
278 {
279 String attrId = ( String ) list.next();
280
281 AttributeType type = null;
282
283 if ( registry.hasAttributeType( attrId ) )
284 {
285 type = registry.lookup( attrId );
286 }
287
288 if ( type != null && type.getUsage() != UsageEnum.USERAPPLICATIONS )
289 {
290 attributes.remove( attrId );
291 }
292 }
293 return true;
294 }
295
296
297 private void filter( Name dn, Attributes entry, String[] ids )
298 throws NamingException
299 {
300
301 if ( ids == null )
302 {
303 OperationalAttributeService.this.filter( entry );
304 return;
305 }
306
307 if ( dn.size() == 0 )
308 {
309 HashSet idsSet = new HashSet( ids.length );
310
311 for ( int ii = 0; ii < ids.length; ii++ )
312 {
313 idsSet.add( ids[ii].toLowerCase() );
314 }
315
316 NamingEnumeration list = entry.getIDs();
317
318 while ( list.hasMore() )
319 {
320 String attrId = ( ( String ) list.nextElement() ).toLowerCase();
321
322 if ( !idsSet.contains( attrId ) )
323 {
324 entry.remove( attrId );
325 }
326 }
327 }
328
329
330
331
332 }
333 }