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 }