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.ldap.handlers;
21
22
23 import javax.naming.NamingException;
24
25 import org.apache.directory.server.core.event.DirectoryListener;
26 import org.apache.directory.server.core.interceptor.context.AddOperationContext;
27 import org.apache.directory.server.core.interceptor.context.ChangeOperationContext;
28 import org.apache.directory.server.core.interceptor.context.DeleteOperationContext;
29 import org.apache.directory.server.core.interceptor.context.ModifyOperationContext;
30 import org.apache.directory.server.core.interceptor.context.MoveAndRenameOperationContext;
31 import org.apache.directory.server.core.interceptor.context.MoveOperationContext;
32 import org.apache.directory.server.core.interceptor.context.RenameOperationContext;
33 import org.apache.directory.server.ldap.LdapSession;
34 import org.apache.directory.shared.ldap.codec.search.controls.ChangeType;
35 import org.apache.directory.shared.ldap.message.AbandonListener;
36 import org.apache.directory.shared.ldap.message.AbandonableRequest;
37 import org.apache.directory.shared.ldap.message.EntryChangeControl;
38 import org.apache.directory.shared.ldap.message.PersistentSearchControl;
39 import org.apache.directory.shared.ldap.message.SearchRequest;
40 import org.apache.directory.shared.ldap.message.SearchResponseEntry;
41 import org.apache.directory.shared.ldap.message.SearchResponseEntryImpl;
42
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60 public class PersistentSearchListener implements DirectoryListener, AbandonListener
61 {
62 private static final Logger LOG = LoggerFactory.getLogger( PersistentSearchListener.class );
63 final LdapSession session;
64 final SearchRequest req;
65 final PersistentSearchControl control;
66
67
68 PersistentSearchListener( LdapSession session, SearchRequest req )
69 {
70 this.session = session;
71 this.req = req;
72 req.addAbandonListener( this );
73 this.control = ( PersistentSearchControl ) req.getControls().get( PersistentSearchControl.CONTROL_OID );
74 }
75
76
77 public void abandon() throws NamingException
78 {
79
80 session.getCoreSession().getDirectoryService().getEventService().removeListener( this );
81
82
83
84
85
86
87
88
89
90
91
92
93
94 }
95
96
97 public void requestAbandoned( AbandonableRequest req )
98 {
99 try
100 {
101 abandon();
102 }
103 catch ( NamingException e )
104 {
105 LOG.error( "failed to properly abandon this persistent search", e );
106 }
107 }
108
109
110 private void setECResponseControl( SearchResponseEntry response, ChangeOperationContext opContext, ChangeType type )
111 {
112 if ( control.isReturnECs() )
113 {
114 EntryChangeControl ecControl = new EntryChangeControl();
115 ecControl.setChangeType( type );
116
117 if ( opContext.getChangeLogEvent() != null )
118 {
119 ecControl.setChangeNumber( opContext.getChangeLogEvent().getRevision() );
120 }
121
122 if ( opContext instanceof RenameOperationContext || opContext instanceof MoveOperationContext )
123 {
124 ecControl.setPreviousDn( opContext.getDn() );
125 }
126
127 response.add( ecControl );
128 }
129 }
130
131
132 public void entryAdded( AddOperationContext opContext )
133 {
134 if ( ! control.isNotificationEnabled( ChangeType.ADD ) )
135 {
136 return;
137 }
138
139 SearchResponseEntry respEntry = new SearchResponseEntryImpl( req.getMessageId() );
140 respEntry.setObjectName( opContext.getDn() );
141 respEntry.setEntry( opContext.getEntry() );
142 setECResponseControl( respEntry, opContext, ChangeType.ADD );
143 session.getIoSession().write( respEntry );
144 }
145
146
147 public void entryDeleted( DeleteOperationContext opContext )
148 {
149 if ( ! control.isNotificationEnabled( ChangeType.DELETE ) )
150 {
151 return;
152 }
153
154 SearchResponseEntry respEntry = new SearchResponseEntryImpl( req.getMessageId() );
155 respEntry.setObjectName( opContext.getDn() );
156 respEntry.setEntry( opContext.getEntry() );
157 setECResponseControl( respEntry, opContext, ChangeType.DELETE );
158 session.getIoSession().write( respEntry );
159 }
160
161
162 public void entryModified( ModifyOperationContext opContext )
163 {
164 if ( ! control.isNotificationEnabled( ChangeType.MODIFY ) )
165 {
166 return;
167 }
168
169 SearchResponseEntry respEntry = new SearchResponseEntryImpl( req.getMessageId() );
170 respEntry.setObjectName( opContext.getDn() );
171 respEntry.setEntry( opContext.getEntry() );
172 setECResponseControl( respEntry, opContext, ChangeType.MODIFY );
173 session.getIoSession().write( respEntry );
174 }
175
176
177 public void entryMoved( MoveOperationContext opContext )
178 {
179 if ( ! control.isNotificationEnabled( ChangeType.MODDN ) )
180 {
181 return;
182 }
183
184 SearchResponseEntry respEntry = new SearchResponseEntryImpl( req.getMessageId() );
185 respEntry.setObjectName( opContext.getDn() );
186 respEntry.setEntry( opContext.getEntry() );
187 setECResponseControl( respEntry, opContext, ChangeType.MODDN );
188 session.getIoSession().write( respEntry );
189 }
190
191
192 public void entryMovedAndRenamed( MoveAndRenameOperationContext opContext )
193 {
194 entryRenamed( opContext );
195 }
196
197
198 public void entryRenamed( RenameOperationContext opContext )
199 {
200 if ( ! control.isNotificationEnabled( ChangeType.MODDN ) )
201 {
202 return;
203 }
204
205 SearchResponseEntry respEntry = new SearchResponseEntryImpl( req.getMessageId() );
206 respEntry.setObjectName( opContext.getAlteredEntry().getDn() );
207 respEntry.setEntry( opContext.getAlteredEntry() );
208 setECResponseControl( respEntry, opContext, ChangeType.MODDN );
209 session.getIoSession().write( respEntry );
210 }
211 }