blob: 082bdd2fbbeebc31b049e42fcbf37e7a6b5b3154 [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.jndi;
import java.util.Hashtable;
import javax.naming.Name;
import javax.naming.NamingException;
import javax.naming.directory.InvalidAttributeIdentifierException;
import javax.naming.ldap.Control;
import javax.naming.ldap.ExtendedRequest;
import javax.naming.ldap.ExtendedResponse;
import javax.naming.ldap.LdapContext;
import javax.naming.ldap.LdapName;
import org.apache.directory.api.asn1.DecoderException;
import org.apache.directory.api.asn1.EncoderException;
import org.apache.directory.api.ldap.model.entry.BinaryValue;
import org.apache.directory.api.ldap.model.entry.StringValue;
import org.apache.directory.api.ldap.model.entry.Value;
import org.apache.directory.api.ldap.model.exception.LdapException;
import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
import org.apache.directory.api.ldap.model.name.Dn;
import org.apache.directory.api.ldap.model.schema.AttributeType;
import org.apache.directory.api.ldap.util.JndiUtils;
import org.apache.directory.api.util.Strings;
import org.apache.directory.api.util.exception.NotImplementedException;
import org.apache.directory.server.core.api.CoreSession;
import org.apache.directory.server.core.api.DirectoryService;
import org.apache.directory.server.core.api.LdapPrincipal;
import org.apache.directory.server.core.api.interceptor.context.CompareOperationContext;
import org.apache.directory.server.core.api.interceptor.context.UnbindOperationContext;
import org.apache.directory.server.i18n.I18n;
/**
* An implementation of a JNDI LdapContext.
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
public class ServerLdapContext extends ServerDirContext implements LdapContext
{
/**
* Creates an instance of an ServerLdapContext.
*
* @param service the parent service that manages this context
* @param env the JNDI environment parameters
* @throws NamingException the context cannot be created
*/
public ServerLdapContext( DirectoryService service, Hashtable<String, Object> env ) throws Exception
{
super( service, env );
}
/**
* Creates a new ServerDirContext with a distinguished name which is used to
* set the PROVIDER_URL to the distinguished name for this context.
*
* @param principal the directory user principal that is propagated
* @param dn the distinguished name of this context
* @param service the directory service core
* @throws NamingException if there are problems instantiating
*/
public ServerLdapContext( DirectoryService service, LdapPrincipal principal, Name dn ) throws Exception
{
super( service, principal, dn );
}
public ServerLdapContext( DirectoryService service, CoreSession session, Name bindDn ) throws Exception
{
super( service, session, bindDn );
}
/**
* @see javax.naming.ldap.LdapContext#extendedOperation(
* javax.naming.ldap.ExtendedRequest)
*/
public ExtendedResponse extendedOperation( ExtendedRequest request )
{
throw new NotImplementedException();
}
/**
* @see javax.naming.ldap.LdapContext#newInstance(
* javax.naming.ldap.Control[])
*/
public LdapContext newInstance( Control[] requestControls ) throws NamingException
{
ServerLdapContext ctx = null;
try
{
ctx = new ServerLdapContext( getService(), getSession().getEffectivePrincipal(), JndiUtils.toName( getDn() ) );
}
catch ( Exception e )
{
JndiUtils.wrap( e );
}
ctx.setRequestControls( requestControls );
return ctx;
}
/**
* @see javax.naming.ldap.LdapContext#reconnect(javax.naming.ldap.Control[])
*/
public void reconnect( Control[] connCtls ) throws NamingException
{
this.connectControls = connCtls;
}
/**
* @see javax.naming.ldap.LdapContext#getConnectControls()
*/
public Control[] getConnectControls() throws NamingException
{
return this.connectControls;
}
/**
* @see javax.naming.ldap.LdapContext#setRequestControls(
* javax.naming.ldap.Control[])
*/
public void setRequestControls( Control[] requestControls ) throws NamingException
{
this.requestControls = requestControls;
}
/**
* @see javax.naming.ldap.LdapContext#getRequestControls()
*/
public Control[] getRequestControls() throws NamingException
{
return requestControls;
}
/**
* @see javax.naming.ldap.LdapContext#getResponseControls()
*/
public Control[] getResponseControls() throws NamingException
{
return responseControls;
}
// ------------------------------------------------------------------------
// Additional ApacheDS Specific JNDI Functionality
// ------------------------------------------------------------------------
/**
* Explicitly exposes an LDAP compare operation which JNDI does not
* directly provide. All normalization and schema checking etcetera
* is handled by this call.
*
* @param name the name of the entri
* @param oid the name or object identifier for the attribute to compare
* @param value the value to compare the attribute to
* @return true if the entry has the value for the attribute, false otherwise
* @throws NamingException if the backing store cannot be accessed, or
* permission is not allowed for this operation or the oid is not recognized,
* or the attribute is not present in the entry ... you get the picture.
*/
public boolean compare( Dn name, String oid, Object value ) throws NamingException
{
Value<?> val = null;
AttributeType attributeType = null;
try
{
attributeType = getService().getSchemaManager().lookupAttributeTypeRegistry( oid );
}
catch ( LdapException le )
{
throw new InvalidAttributeIdentifierException( le.getMessage() );
}
// make sure we add the request controls to operation
try
{
if ( attributeType.getSyntax().isHumanReadable() )
{
if ( value instanceof String )
{
val = new StringValue( attributeType, ( String ) value );
}
else if ( value instanceof byte[] )
{
val = new StringValue( attributeType, Strings.utf8ToString( ( byte[] ) value ) );
}
else
{
throw new NamingException( I18n.err( I18n.ERR_309, oid ) );
}
}
else
{
if ( value instanceof String )
{
val = new BinaryValue( attributeType, Strings.getBytesUtf8( ( String ) value ) );
}
else if ( value instanceof byte[] )
{
val = new BinaryValue( attributeType, ( byte[] ) value );
}
else
{
throw new NamingException( I18n.err( I18n.ERR_309, oid ) );
}
}
}
catch ( LdapInvalidAttributeValueException liave )
{
throw new NamingException( I18n.err( I18n.ERR_309, oid ) );
}
CompareOperationContext opCtx = new CompareOperationContext( getSession(), name, oid, val );
try
{
opCtx.addRequestControls( JndiUtils.fromJndiControls( getDirectoryService().getLdapCodecService(),
requestControls ) );
}
catch ( DecoderException e1 )
{
throw new NamingException( I18n.err( I18n.ERR_309, oid ) );
}
// Inject the Referral flag
injectReferralControl( opCtx );
// execute operation
boolean result = false;
try
{
result = super.getDirectoryService().getOperationManager().compare( opCtx );
}
catch ( Exception e )
{
JndiUtils.wrap( e );
}
// extract the response controls from the operation and return
responseControls = getResponseControls();
requestControls = EMPTY_CONTROLS;
return result;
}
/**
* Calling this method tunnels an unbind call down into the partition holding
* the bindDn. The bind() counter part is not exposed because it is automatically
* called when you create a new initial context for a new connection (on wire) or
* (programatic) caller.
*
* @throws NamingException if there are failures encountered while unbinding
*/
public void ldapUnbind() throws NamingException
{
UnbindOperationContext opCtx = new UnbindOperationContext( getSession() );
try
{
opCtx.addRequestControls( JndiUtils.fromJndiControls( getDirectoryService().getLdapCodecService(),
requestControls ) );
}
catch ( DecoderException e1 )
{
throw new NamingException( I18n.err( I18n.ERR_309, "unbind encoder exception" ) );
}
try
{
super.getDirectoryService().getOperationManager().unbind( opCtx );
}
catch ( Exception e )
{
JndiUtils.wrap( e );
}
try
{
responseControls = JndiUtils.toJndiControls( getDirectoryService().getLdapCodecService(),
opCtx.getResponseControls() );
}
catch ( EncoderException e )
{
throw new NamingException( I18n.err( I18n.ERR_309, "unbind encoder exception" ) );
}
requestControls = EMPTY_CONTROLS;
}
public ServerContext getRootContext() throws NamingException
{
ServerContext ctx = null;
try
{
ctx = new ServerLdapContext( getService(), getSession().getEffectivePrincipal(), new LdapName( "" ) );
}
catch ( Exception e )
{
JndiUtils.wrap( e );
}
return ctx;
}
}