/*
 *  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;
    }
}
