blob: e5b8866c052f095477126f8bb3f8a4ecf0625dc1 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package org.apache.directory.server.core.interceptor.context;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.naming.ldap.Control;
import org.apache.directory.server.core.CoreSession;
import org.apache.directory.server.core.LdapPrincipal;
import org.apache.directory.server.core.entry.ClonedServerEntry;
import org.apache.directory.server.core.entry.ServerEntry;
import org.apache.directory.shared.ldap.entry.Modification;
import org.apache.directory.shared.ldap.name.LdapDN;
/**
* This abstract class stores common context elements, like the DN, which is used
* in all the contexts.
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
* @version $Rev$, $Date$
*/
public abstract class AbstractOperationContext implements OperationContext
{
protected static final Control[] EMPTY_CONTROLS = new Control[0];
/** The DN associated with the context */
protected LdapDN dn;
/** The entry associated with the target entry of this OperationContext */
protected ClonedServerEntry entry;
/** The associated request's controls */
protected Map<String, Control> requestControls = new HashMap<String, Control>(4);
/** The associated response's controls */
protected Map<String, Control> responseControls = new HashMap<String, Control>(4);
/** the Interceptors bypassed by this operation */
protected Collection<String> byPassed;
protected LdapPrincipal authorizedPrincipal;
/** The core session */
protected CoreSession session;
protected OperationContext next;
protected OperationContext previous;
/** A flag used to tell if we should consider referrals as standard entries */
protected boolean throwReferral;
/**
* Creates a new instance of AbstractOperationContext.
*/
public AbstractOperationContext( CoreSession session )
{
this.session = session;
}
/**
* Creates a new instance of AbstractOperationContext.
*
* @param dn The associated DN
*/
public AbstractOperationContext( CoreSession session, LdapDN dn )
{
this.dn = dn;
this.session = session;
// The flag is set to ignore, so that the revert operation can act on
// the entries, even if they are referrals.
ignoreReferral();
}
public CoreSession getSession()
{
return session;
}
protected void setSession( CoreSession session )
{
this.session = session;
}
protected void setAuthorizedPrincipal( LdapPrincipal authorizedPrincipal )
{
this.authorizedPrincipal = authorizedPrincipal;
}
/**
* @return The associated DN
*/
public LdapDN getDn()
{
return dn;
}
/**
* Set the context DN
*
* @param dn The DN to set
*/
public void setDn( LdapDN dn )
{
this.dn = dn;
}
public void addRequestControl( Control requestControl )
{
requestControls.put( requestControl.getID(), requestControl );
}
public Control getRequestControl( String numericOid )
{
return requestControls.get( numericOid );
}
public boolean hasRequestControl( String numericOid )
{
return requestControls.containsKey( numericOid );
}
public boolean hasRequestControls()
{
return ! requestControls.isEmpty();
}
public void addResponseControl( Control responseControl )
{
responseControls.put( responseControl.getID(), responseControl );
}
public Control getResponseControl( String numericOid )
{
return responseControls.get( numericOid );
}
public boolean hasResponseControl( String numericOid )
{
return responseControls.containsKey( numericOid );
}
public Control[] getResponseControls()
{
if ( responseControls.isEmpty() )
{
return EMPTY_CONTROLS;
}
return responseControls.values().toArray( EMPTY_CONTROLS );
}
public boolean hasResponseControls()
{
return ! responseControls.isEmpty();
}
public int getResponseControlCount()
{
return responseControls.size();
}
public void addRequestControls( Control[] requestControls )
{
for ( Control c : requestControls )
{
this.requestControls.put( c.getID(), c );
}
}
public void setRequestControls( Map<String, Control> requestControls )
{
this.requestControls = requestControls;
}
/**
* @return the operation name
*/
public abstract String getName();
/**
* Gets the set of bypassed Interceptors.
*
* @return the set of bypassed Interceptors
*/
public Collection<String> getByPassed()
{
if ( byPassed == null )
{
return Collections.emptyList();
}
return Collections.unmodifiableCollection( byPassed );
}
/**
* Sets the set of bypassed Interceptors.
*
* @param byPassed the set of bypassed Interceptors
*/
public void setByPassed( Collection<String> byPassed )
{
this.byPassed = byPassed;
}
/**
* Checks to see if an Interceptor is bypassed for this operation.
*
* @param interceptorName the interceptorName of the Interceptor to check for bypass
* @return true if the Interceptor should be bypassed, false otherwise
*/
public boolean isBypassed( String interceptorName )
{
return byPassed != null && byPassed.contains( interceptorName );
}
/**
* Checks to see if any Interceptors are bypassed by this operation.
*
* @return true if at least one bypass exists
*/
public boolean hasBypass()
{
return byPassed != null && !byPassed.isEmpty();
}
private void setup( AbstractOperationContext opContext )
{
opContext.setPreviousOperation( this );
next = opContext;
opContext.setByPassed( byPassed );
opContext.setAuthorizedPrincipal( authorizedPrincipal );
}
public boolean hasEntry( LdapDN dn, Collection<String> byPassed ) throws Exception
{
EntryOperationContext opContext = new EntryOperationContext( session, dn );
setup( opContext );
opContext.setByPassed( byPassed );
return session.getDirectoryService().getOperationManager().hasEntry( opContext );
}
public void add( ServerEntry entry, Collection<String> byPassed ) throws Exception
{
AddOperationContext opContext = new AddOperationContext( session, entry );
setup( opContext );
opContext.setByPassed( byPassed );
session.getDirectoryService().getOperationManager().add( opContext );
}
public void delete( LdapDN dn, Collection<String> byPassed ) throws Exception
{
DeleteOperationContext opContext = new DeleteOperationContext( session, dn );
setup( opContext );
opContext.setByPassed( byPassed );
session.getDirectoryService().getOperationManager().delete( opContext );
}
public void modify( LdapDN dn, List<Modification> mods, Collection<String> byPassed ) throws Exception
{
ModifyOperationContext opContext = new ModifyOperationContext( session, dn, mods );
setup( opContext );
opContext.setByPassed( byPassed );
session.getDirectoryService().getOperationManager().modify( opContext );
}
// TODO - need synchronization here and where we update links
public LookupOperationContext newLookupContext( LdapDN dn )
{
LookupOperationContext opContext = new LookupOperationContext( session, dn );
setup( opContext );
return opContext;
}
public ClonedServerEntry lookup( LookupOperationContext opContext ) throws Exception
{
if ( opContext != next )
{
throw new IllegalStateException( "Cannot execute indirect lookup if it is not the next operation." );
}
return session.getDirectoryService().getOperationManager().lookup( opContext );
}
public ClonedServerEntry lookup( LdapDN dn, Collection<String> byPassed ) throws Exception
{
LookupOperationContext opContext = newLookupContext( dn );
opContext.setByPassed( byPassed );
return session.getDirectoryService().getOperationManager().lookup( opContext );
}
public LdapPrincipal getEffectivePrincipal()
{
if ( authorizedPrincipal != null )
{
return authorizedPrincipal;
}
return session.getEffectivePrincipal();
}
// -----------------------------------------------------------------------
// OperationContext Linked List Methods
// -----------------------------------------------------------------------
public boolean isFirstOperation()
{
return previous == null;
}
public OperationContext getFirstOperation()
{
if ( previous == null )
{
return this;
}
return previous.getFirstOperation();
}
public OperationContext getLastOperation()
{
if ( next == null )
{
return this;
}
return next.getLastOperation();
}
public OperationContext getNextOperation()
{
return next;
}
protected void setNextOperation( OperationContext next )
{
this.next = next;
}
public OperationContext getPreviousOperation()
{
return previous;
}
protected void setPreviousOperation( OperationContext previous )
{
this.previous = previous;
}
/**
* @param entry the entry to set
*/
public void setEntry( ClonedServerEntry entry )
{
this.entry = entry;
}
/**
* @return the entry
*/
public ClonedServerEntry getEntry()
{
return entry;
}
/**
* Set the throwReferral flag to true
*/
public void throwReferral()
{
throwReferral = true;
}
/**
* @return <code>true</code> if the referrals are thrown
*/
public boolean isReferralThrown()
{
return throwReferral;
}
/**
* Set the throwReferral flag to false
*/
public void ignoreReferral()
{
throwReferral = false;
}
/**
* @return <code>true</code> if the referrals are ignored
*/
public boolean isReferralIgnored()
{
return !throwReferral;
}
}