001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 *
019 */
020 package org.apache.directory.server.core.interceptor.context;
021
022
023 import java.util.Collection;
024 import java.util.Collections;
025 import java.util.HashMap;
026 import java.util.List;
027 import java.util.Map;
028
029 import org.apache.directory.server.core.CoreSession;
030 import org.apache.directory.server.core.LdapPrincipal;
031 import org.apache.directory.server.core.entry.ClonedServerEntry;
032 import org.apache.directory.server.i18n.I18n;
033 import org.apache.directory.shared.ldap.entry.Modification;
034 import org.apache.directory.shared.ldap.entry.ServerEntry;
035 import org.apache.directory.shared.ldap.message.control.Control;
036 import org.apache.directory.shared.ldap.name.DN;
037
038
039 /**
040 * This abstract class stores common context elements, like the DN, which is used
041 * in all the contexts.
042 *
043 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
044 * @version $Rev$, $Date$
045 */
046 public abstract class AbstractOperationContext implements OperationContext
047 {
048 protected static final Control[] EMPTY_CONTROLS = new Control[0];
049
050 /** The DN associated with the context */
051 protected DN dn;
052
053 /** The entry associated with the target entry of this OperationContext */
054 protected ClonedServerEntry entry;
055
056 /** The associated request's controls */
057 protected Map<String, Control> requestControls = new HashMap<String, Control>(4);
058
059 /** The associated response's controls */
060 protected Map<String, Control> responseControls = new HashMap<String, Control>(4);
061
062 /** the Interceptors bypassed by this operation */
063 protected Collection<String> byPassed;
064
065 protected LdapPrincipal authorizedPrincipal;
066
067 /** The core session */
068 protected CoreSession session;
069
070 protected OperationContext next;
071
072 protected OperationContext previous;
073
074 /** A flag used to tell if we should consider referrals as standard entries */
075 protected boolean throwReferral;
076
077
078 /**
079 * Creates a new instance of AbstractOperationContext.
080 */
081 public AbstractOperationContext( CoreSession session )
082 {
083 this.session = session;
084 }
085
086
087 /**
088 * Creates a new instance of AbstractOperationContext.
089 *
090 * @param dn The associated DN
091 */
092 public AbstractOperationContext( CoreSession session, DN dn )
093 {
094 this.dn = dn;
095 this.session = session;
096
097 // The flag is set to ignore, so that the revert operation can act on
098 // the entries, even if they are referrals.
099 ignoreReferral();
100 }
101
102
103 public CoreSession getSession()
104 {
105 return session;
106 }
107
108
109 protected void setSession( CoreSession session )
110 {
111 this.session = session;
112 }
113
114
115 protected void setAuthorizedPrincipal( LdapPrincipal authorizedPrincipal )
116 {
117 this.authorizedPrincipal = authorizedPrincipal;
118 }
119
120
121 /**
122 * @return The associated DN
123 */
124 public DN getDn()
125 {
126 return dn;
127 }
128
129
130 /**
131 * Set the context DN
132 *
133 * @param dn The DN to set
134 */
135 public void setDn( DN dn )
136 {
137 this.dn = dn;
138 }
139
140
141 public void addRequestControl( Control requestControl )
142 {
143 requestControls.put( requestControl.getOid(), requestControl );
144 }
145
146
147 public Control getRequestControl( String numericOid )
148 {
149 return requestControls.get( numericOid );
150 }
151
152
153 public boolean hasRequestControl( String numericOid )
154 {
155 return requestControls.containsKey( numericOid );
156 }
157
158
159 public boolean hasRequestControls()
160 {
161 return ! requestControls.isEmpty();
162 }
163
164
165 public void addResponseControl( Control responseControl )
166 {
167 responseControls.put( responseControl.getOid(), responseControl );
168 }
169
170
171 public Control getResponseControl( String numericOid )
172 {
173 return responseControls.get( numericOid );
174 }
175
176
177 public boolean hasResponseControl( String numericOid )
178 {
179 return responseControls.containsKey( numericOid );
180 }
181
182
183 public Control[] getResponseControls()
184 {
185 if ( responseControls.isEmpty() )
186 {
187 return EMPTY_CONTROLS;
188 }
189
190 return responseControls.values().toArray( EMPTY_CONTROLS );
191 }
192
193
194 public boolean hasResponseControls()
195 {
196 return ! responseControls.isEmpty();
197 }
198
199
200 public int getResponseControlCount()
201 {
202 return responseControls.size();
203 }
204
205
206 public void addRequestControls( Control[] requestControls )
207 {
208 for ( Control c : requestControls )
209 {
210 this.requestControls.put( c.getOid(), c );
211 }
212 }
213
214
215 public void setRequestControls( Map<String, Control> requestControls )
216 {
217 this.requestControls = requestControls;
218 }
219
220
221 /**
222 * @return the operation name
223 */
224 public abstract String getName();
225
226
227 /**
228 * Gets the set of bypassed Interceptors.
229 *
230 * @return the set of bypassed Interceptors
231 */
232 public Collection<String> getByPassed()
233 {
234 if ( byPassed == null )
235 {
236 return Collections.emptyList();
237 }
238
239 return Collections.unmodifiableCollection( byPassed );
240 }
241
242
243 /**
244 * Sets the set of bypassed Interceptors.
245 *
246 * @param byPassed the set of bypassed Interceptors
247 */
248 public void setByPassed( Collection<String> byPassed )
249 {
250 this.byPassed = byPassed;
251 }
252
253
254 /**
255 * Checks to see if an Interceptor is bypassed for this operation.
256 *
257 * @param interceptorName the interceptorName of the Interceptor to check for bypass
258 * @return true if the Interceptor should be bypassed, false otherwise
259 */
260 public boolean isBypassed( String interceptorName )
261 {
262 return byPassed != null && byPassed.contains( interceptorName );
263 }
264
265
266 /**
267 * Checks to see if any Interceptors are bypassed by this operation.
268 *
269 * @return true if at least one bypass exists
270 */
271 public boolean hasBypass()
272 {
273 return byPassed != null && !byPassed.isEmpty();
274 }
275
276
277 private void setup( AbstractOperationContext opContext )
278 {
279 opContext.setPreviousOperation( this );
280 next = opContext;
281 opContext.setByPassed( byPassed );
282 opContext.setAuthorizedPrincipal( authorizedPrincipal );
283 }
284
285
286 public boolean hasEntry( DN dn, Collection<String> byPassed ) throws Exception
287 {
288 EntryOperationContext opContext = new EntryOperationContext( session, dn );
289 setup( opContext );
290 opContext.setByPassed( byPassed );
291 return session.getDirectoryService().getOperationManager().hasEntry( opContext );
292 }
293
294
295 public void add( ServerEntry entry, Collection<String> byPassed ) throws Exception
296 {
297 AddOperationContext opContext = new AddOperationContext( session, entry );
298 setup( opContext );
299 opContext.setByPassed( byPassed );
300 session.getDirectoryService().getOperationManager().add( opContext );
301 }
302
303
304 public void delete( DN dn, Collection<String> byPassed ) throws Exception
305 {
306 DeleteOperationContext opContext = new DeleteOperationContext( session, dn );
307 setup( opContext );
308 opContext.setByPassed( byPassed );
309 session.getDirectoryService().getOperationManager().delete( opContext );
310 }
311
312
313 public void modify( DN dn, List<Modification> mods, Collection<String> byPassed ) throws Exception
314 {
315 ModifyOperationContext opContext = new ModifyOperationContext( session, dn, mods );
316 setup( opContext );
317 opContext.setByPassed( byPassed );
318 session.getDirectoryService().getOperationManager().modify( opContext );
319 }
320
321
322 // TODO - need synchronization here and where we update links
323 public LookupOperationContext newLookupContext( DN dn )
324 {
325 LookupOperationContext opContext = new LookupOperationContext( session, dn );
326 setup( opContext );
327 return opContext;
328 }
329
330
331 public ClonedServerEntry lookup( LookupOperationContext opContext ) throws Exception
332 {
333 if ( opContext != next )
334 {
335 throw new IllegalStateException( I18n.err( I18n.ERR_319 ) );
336 }
337 return session.getDirectoryService().getOperationManager().lookup( opContext );
338 }
339
340
341 public ClonedServerEntry lookup( DN dn, Collection<String> byPassed ) throws Exception
342 {
343 LookupOperationContext opContext = newLookupContext( dn );
344 opContext.setByPassed( byPassed );
345 return session.getDirectoryService().getOperationManager().lookup( opContext );
346 }
347
348
349 public LdapPrincipal getEffectivePrincipal()
350 {
351 if ( authorizedPrincipal != null )
352 {
353 return authorizedPrincipal;
354 }
355
356 return session.getEffectivePrincipal();
357 }
358
359
360 // -----------------------------------------------------------------------
361 // OperationContext Linked List Methods
362 // -----------------------------------------------------------------------
363
364
365 public boolean isFirstOperation()
366 {
367 return previous == null;
368 }
369
370
371 public OperationContext getFirstOperation()
372 {
373 if ( previous == null )
374 {
375 return this;
376 }
377
378 return previous.getFirstOperation();
379 }
380
381
382 public OperationContext getLastOperation()
383 {
384 if ( next == null )
385 {
386 return this;
387 }
388
389 return next.getLastOperation();
390 }
391
392
393 public OperationContext getNextOperation()
394 {
395 return next;
396 }
397
398
399 protected void setNextOperation( OperationContext next )
400 {
401 this.next = next;
402 }
403
404
405 public OperationContext getPreviousOperation()
406 {
407 return previous;
408 }
409
410
411 protected void setPreviousOperation( OperationContext previous )
412 {
413 this.previous = previous;
414 }
415
416
417 /**
418 * @param entry the entry to set
419 */
420 public void setEntry( ClonedServerEntry entry )
421 {
422 this.entry = entry;
423 }
424
425
426 /**
427 * @return the entry
428 */
429 public ClonedServerEntry getEntry()
430 {
431 return entry;
432 }
433
434
435 /**
436 * Set the throwReferral flag to true
437 */
438 public void throwReferral()
439 {
440 throwReferral = true;
441 }
442
443
444 /**
445 * @return <code>true</code> if the referrals are thrown
446 */
447 public boolean isReferralThrown()
448 {
449 return throwReferral;
450 }
451
452
453 /**
454 * Set the throwReferral flag to false
455 */
456 public void ignoreReferral()
457 {
458 throwReferral = false;
459 }
460
461
462 /**
463 * @return <code>true</code> if the referrals are ignored
464 */
465 public boolean isReferralIgnored()
466 {
467 return !throwReferral;
468 }
469 }