1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.directory.server.core.changelog;
20
21
22 import java.util.ArrayList;
23 import java.util.List;
24 import java.util.Set;
25
26 import org.apache.directory.server.constants.ApacheSchemaConstants;
27 import org.apache.directory.server.core.DirectoryService;
28 import org.apache.directory.server.core.entry.ClonedServerEntry;
29 import org.apache.directory.server.core.entry.ServerAttribute;
30 import org.apache.directory.server.core.entry.ServerEntry;
31 import org.apache.directory.server.core.entry.ServerEntryUtils;
32 import org.apache.directory.server.core.entry.ServerModification;
33 import org.apache.directory.server.core.interceptor.BaseInterceptor;
34 import org.apache.directory.server.core.interceptor.NextInterceptor;
35 import org.apache.directory.server.core.interceptor.context.AddOperationContext;
36 import org.apache.directory.server.core.interceptor.context.DeleteOperationContext;
37 import org.apache.directory.server.core.interceptor.context.ModifyOperationContext;
38 import org.apache.directory.server.core.interceptor.context.MoveAndRenameOperationContext;
39 import org.apache.directory.server.core.interceptor.context.MoveOperationContext;
40 import org.apache.directory.server.core.interceptor.context.OperationContext;
41 import org.apache.directory.server.core.interceptor.context.RenameOperationContext;
42 import org.apache.directory.server.core.partition.ByPassConstants;
43 import org.apache.directory.server.core.schema.SchemaService;
44 import org.apache.directory.shared.ldap.entry.Entry;
45 import org.apache.directory.shared.ldap.entry.EntryAttribute;
46 import org.apache.directory.shared.ldap.entry.Modification;
47 import org.apache.directory.shared.ldap.entry.client.DefaultClientEntry;
48 import org.apache.directory.shared.ldap.ldif.ChangeType;
49 import org.apache.directory.shared.ldap.ldif.LdifEntry;
50 import org.apache.directory.shared.ldap.ldif.LdifUtils;
51 import org.apache.directory.shared.ldap.name.LdapDN;
52 import org.apache.directory.shared.ldap.name.Rdn;
53 import org.apache.directory.shared.ldap.schema.AttributeType;
54 import org.slf4j.Logger;
55 import org.slf4j.LoggerFactory;
56
57
58
59
60
61
62
63 public class ChangeLogInterceptor extends BaseInterceptor
64 {
65
66 private static final Logger LOG = LoggerFactory.getLogger( ChangeLogInterceptor.class );
67
68
69 private AttributeType entryDeleted;
70
71
72 private ChangeLog changeLog;
73
74
75 private SchemaService schemaService;
76
77
78 private static final String REV_OID = "1.3.6.1.4.1.18060.0.4.1.2.47";
79
80
81
82
83
84
85 public void init( DirectoryService directoryService ) throws Exception
86 {
87 super.init( directoryService );
88
89 changeLog = directoryService.getChangeLog();
90 schemaService = directoryService.getSchemaService();
91 entryDeleted = directoryService.getRegistries().getAttributeTypeRegistry()
92 .lookup( ApacheSchemaConstants.ENTRY_DELETED_OID );
93 }
94
95
96
97
98
99
100
101 public void add( NextInterceptor next, AddOperationContext opContext ) throws Exception
102 {
103 next.add( opContext );
104
105 if ( ! changeLog.isEnabled() || ! opContext.isFirstOperation() )
106 {
107 return;
108 }
109
110 ServerEntry addEntry = opContext.getEntry();
111
112
113 if( addEntry.get( REV_OID ) != null )
114 {
115 return;
116 }
117
118 LdifEntry forward = new LdifEntry();
119 forward.setChangeType( ChangeType.Add );
120 forward.setDn( opContext.getDn() );
121
122 Set<AttributeType> list = addEntry.getAttributeTypes();
123
124 for ( AttributeType attributeType:list )
125 {
126 forward.addAttribute( ((ServerAttribute)addEntry.get( attributeType) ).toClientAttribute() );
127 }
128
129 LdifEntry reverse = LdifUtils.reverseAdd( opContext.getDn() );
130 opContext.setChangeLogEvent( changeLog.log( getPrincipal(), forward, reverse ) );
131 }
132
133
134
135
136
137
138 public void delete( NextInterceptor next, DeleteOperationContext opContext ) throws Exception
139 {
140
141
142 ServerEntry serverEntry = null;
143
144 if ( changeLog.isEnabled() && opContext.isFirstOperation() )
145 {
146 serverEntry = getAttributes( opContext );
147 }
148
149 next.delete( opContext );
150
151 if ( ! changeLog.isEnabled() || ! opContext.isFirstOperation() )
152 {
153 return;
154 }
155
156
157 if( serverEntry.get( REV_OID ) != null )
158 {
159 return;
160 }
161
162 LdifEntry forward = new LdifEntry();
163 forward.setChangeType( ChangeType.Delete );
164 forward.setDn( opContext.getDn() );
165
166 Entry reverseEntry = new DefaultClientEntry( serverEntry.getDn() );
167
168 for ( EntryAttribute attribute:serverEntry )
169 {
170 reverseEntry.add( ((ServerAttribute)attribute).toClientAttribute() );
171 }
172
173 LdifEntry reverse = LdifUtils.reverseDel( opContext.getDn(), reverseEntry );
174 opContext.setChangeLogEvent( changeLog.log( getPrincipal(), forward, reverse ) );
175 }
176
177
178
179
180
181
182
183
184
185 private ServerEntry getAttributes( OperationContext opContext ) throws Exception
186 {
187 LdapDN dn = opContext.getDn();
188 ClonedServerEntry serverEntry;
189
190
191 if ( schemaService.isSchemaSubentry( dn.toNormName() ) )
192 {
193 return schemaService.getSubschemaEntryCloned();
194 }
195 else
196 {
197 serverEntry = opContext.lookup( dn, ByPassConstants.LOOKUP_BYPASS );
198 }
199
200 return serverEntry;
201 }
202
203
204
205
206
207 public void modify( NextInterceptor next, ModifyOperationContext opContext ) throws Exception
208 {
209 ServerEntry serverEntry = null;
210 Modification modification = ServerEntryUtils.getModificationItem( opContext.getModItems(), entryDeleted );
211 boolean isDelete = ( modification != null );
212
213 if ( ! isDelete && ( changeLog.isEnabled() && opContext.isFirstOperation() ) )
214 {
215
216 serverEntry = getAttributes( opContext );
217 }
218
219 next.modify( opContext );
220
221
222
223 if (
224 isDelete ||
225 ! changeLog.isEnabled() ||
226 ! opContext.isFirstOperation() ||
227
228
229
230
231
232 opContext.getModItems().size() == 0 )
233 {
234 if ( isDelete )
235 {
236 LOG.debug( "Bypassing changelog on modify of entryDeleted attribute." );
237 }
238
239 return;
240 }
241
242 LdifEntry forward = new LdifEntry();
243 forward.setChangeType( ChangeType.Modify );
244 forward.setDn( opContext.getDn() );
245
246 List<Modification> mods = new ArrayList<Modification>( opContext.getModItems().size() );
247
248 for ( Modification modItem : opContext.getModItems() )
249 {
250 Modification mod = ((ServerModification)modItem).toClientModification();
251
252
253 mod.getAttribute().setId( modItem.getAttribute().getId() );
254 mods.add( mod );
255
256 forward.addModificationItem( mod );
257 }
258
259 Entry clientEntry = new DefaultClientEntry( serverEntry.getDn() );
260
261 for ( EntryAttribute attribute:serverEntry )
262 {
263 clientEntry.add( ((ServerAttribute)attribute).toClientAttribute() );
264 }
265
266 LdifEntry reverse = LdifUtils.reverseModify(
267 opContext.getDn(),
268 mods,
269 clientEntry );
270
271 opContext.setChangeLogEvent( changeLog.log( getPrincipal(), forward, reverse ) );
272 }
273
274
275
276
277
278
279
280 public void rename ( NextInterceptor next, RenameOperationContext renameContext ) throws Exception
281 {
282 ServerEntry serverEntry = null;
283
284 if ( changeLog.isEnabled() && renameContext.isFirstOperation() )
285 {
286
287 serverEntry = getAttributes( renameContext );
288 }
289
290 next.rename( renameContext );
291
292 if ( ! changeLog.isEnabled() || ! renameContext.isFirstOperation() )
293 {
294 return;
295 }
296
297 LdifEntry forward = new LdifEntry();
298 forward.setChangeType( ChangeType.ModRdn );
299 forward.setDn( renameContext.getDn() );
300 forward.setNewRdn( renameContext.getNewRdn().getUpName() );
301 forward.setDeleteOldRdn( renameContext.getDelOldDn() );
302
303 List<LdifEntry> reverses = LdifUtils.reverseModifyRdn( ServerEntryUtils.toBasicAttributes( serverEntry ),
304 null, renameContext.getDn(), new Rdn( renameContext.getNewRdn() ) );
305
306 renameContext.setChangeLogEvent( changeLog.log( getPrincipal(), forward, reverses ) );
307 }
308
309
310 public void moveAndRename( NextInterceptor next, MoveAndRenameOperationContext opCtx )
311 throws Exception
312 {
313 ClonedServerEntry serverEntry = null;
314
315 if ( changeLog.isEnabled() && opCtx.isFirstOperation() )
316 {
317
318 serverEntry = opCtx.lookup( opCtx.getDn(), ByPassConstants.LOOKUP_BYPASS );
319 }
320
321 next.moveAndRename( opCtx );
322
323 if ( ! changeLog.isEnabled() || ! opCtx.isFirstOperation() )
324 {
325 return;
326 }
327
328 LdifEntry forward = new LdifEntry();
329 forward.setChangeType( ChangeType.ModDn );
330 forward.setDn( opCtx.getDn() );
331 forward.setDeleteOldRdn( opCtx.getDelOldDn() );
332 forward.setNewRdn( opCtx.getNewRdn().getUpName() );
333 forward.setNewSuperior( opCtx.getParent().getUpName() );
334
335 List<LdifEntry> reverses = LdifUtils.reverseModifyRdn( ServerEntryUtils.toBasicAttributes( serverEntry ),
336 opCtx.getParent(), opCtx.getDn(), new Rdn( opCtx.getNewRdn() ) );
337 opCtx.setChangeLogEvent( changeLog.log( getPrincipal(), forward, reverses ) );
338 }
339
340
341 public void move ( NextInterceptor next, MoveOperationContext opCtx ) throws Exception
342 {
343 next.move( opCtx );
344
345 if ( ! changeLog.isEnabled() || ! opCtx.isFirstOperation() )
346 {
347 return;
348 }
349
350 LdifEntry forward = new LdifEntry();
351 forward.setChangeType( ChangeType.ModDn );
352 forward.setDn( opCtx.getDn() );
353 forward.setNewSuperior( opCtx.getParent().getUpName() );
354
355 LdifEntry reverse = LdifUtils.reverseModifyDn( opCtx.getParent(), opCtx.getDn() );
356 opCtx.setChangeLogEvent( changeLog.log( getPrincipal(), forward, reverse ) );
357 }
358 }