Package org.apache.harmony.jndi.provider.ldap

Source Code of org.apache.harmony.jndi.provider.ldap.LdapMessage

/*
*  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.harmony.jndi.provider.ldap;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import javax.naming.ldap.Control;

import org.apache.harmony.jndi.provider.ldap.asn1.ASN1Decodable;
import org.apache.harmony.jndi.provider.ldap.asn1.ASN1Encodable;
import org.apache.harmony.jndi.provider.ldap.asn1.LdapASN1Constant;
import org.apache.harmony.jndi.provider.ldap.asn1.ASN1ChoiceWrap.ChosenValue;
import org.apache.harmony.security.asn1.ASN1Integer;

/**
* Ldap Message. Refer to {@link http://www.rfc-editor.org/rfc/rfc2251.txt} for
* detailed information
*
*/
public class LdapMessage implements ASN1Encodable, ASN1Decodable {

    /**
     * operation request which could be encoded using ASN.1 BER
     */
    private ASN1Encodable requestOp;

    /**
     * operation response operation which could be decoded using ASN.1 BER
     */
    private ASN1Decodable responseOp;

    /**
     * controls for this message
     */
    private Control[] controls;

    /**
     * index of the operation, determine which operation is encapsulated in this
     * message.
     */
    private int opIndex;


    /**
     * unique request id for each session
     */
    private int messageId;

    private static int nextMessageId = 1;

    /**
     * Get next unique message id
     *
     * @return the next unique message id
     */
    public static synchronized int getNextMessageId() {
        return nextMessageId++;
    }

    /**
     * Get message id of this message
     *
     * @return id of this message
     */
    public int getMessageId() {
        return messageId;
    }

    /**
     * Construct a request message. <code>op</code> may not be
     * <code>null</code>. <code>controls</code> is <code>null</code> or a
     * array of zero length means there is no control for this message.
     *
     * @param opIndex
     *            request index to indicate which operation is encapsulated
     * @param op
     *            encodable operation
     * @param controls
     *            message controls
     */
    public LdapMessage(int opIndex, ASN1Encodable op, Control[] controls) {
        this.opIndex = opIndex;
        requestOp = op;
        this.controls = controls;
        messageId = getNextMessageId();
    }

    /**
     * Construct a response message. <code>op</code> indicate which operation
     * to be used, and the message would be initialized after calling
     * <code>decode(byte[])</code> or <code>decode(InputStream)</code>
     * method.
     *
     * @param op
     *            response index to indicate which operation to be encapsulated
     */
    public LdapMessage(ASN1Decodable op) {
        responseOp = op;
        opIndex = -1;
        messageId = -1;
    }

    /**
     * Encode this message using ASN.1 Basic Encoding Rules (BER)
     *
     * @return the encoded values of this <code>LdapMessage</code> instance
     */
    public byte[] encode() {
        return LdapASN1Constant.LDAPMessage.encode(this);
    }

    /**
     * Decode values from <code>InputStream</code> using ASN.1 BER, and the
     * decoded values will initialize this <code>LdapMessage</code> instance.
     *
     * @param in
     *
     * @throws IOException
     *             error occurs when decoding
     */
    public void decode(InputStream in) throws IOException {
        Object[] values = (Object[]) LdapASN1Constant.LDAPMessage.decode(in);
        decodeValues(values);
    }

    /**
     * Return controls of the message, if there is no control, <code>null</code>
     * will be returned.
     *
     * @return controls of the message
     */
    public Control[] getControls() {
        return controls;
    }

    @SuppressWarnings("unchecked")
    public void decodeValues(Object[] values) {
        messageId = ASN1Integer.toIntValue(values[0]);
        if (values[1] == null) {
            return;
        }

        ChosenValue chosen = (ChosenValue) values[1];
        opIndex = chosen.getIndex();
        // failed to retrieve responseOp
        responseOp = getResponseOp();
        if (responseOp == null) {
            return;
        }

        if (opIndex == LdapASN1Constant.OP_SEARCH_RESULT_DONE
                || opIndex == LdapASN1Constant.OP_SEARCH_RESULT_ENTRY
                || opIndex == LdapASN1Constant.OP_SEARCH_RESULT_REF) {
            /*
             * we use LdapSearchResult to decode all types of search responses,
             * so we need index to determine which type of response to decode
             */
            responseOp.decodeValues(new Object[] { chosen });
        } else {
            responseOp.decodeValues((Object[]) chosen.getValue());
        }

        if (values[2] != null) {
            Collection<Object[]> list = (Collection<Object[]>) values[2];
            controls = new Control[list.size()];
            int index = 0;
            for (Object[] objects : list) {
                LdapControl lcontrol = new LdapControl();
                lcontrol.decodeValues(objects);
                controls[index++] = lcontrol.getControl();
            }
        }
    }

    public void encodeValues(Object[] values) {
        values[0] = ASN1Integer.fromIntValue(messageId);
        // ABANDON, UNBIND and DELETE request are ASN.1 primitive
        if (opIndex == LdapASN1Constant.OP_ABANDON_REQUEST
                || opIndex == LdapASN1Constant.OP_DEL_REQUEST
                || opIndex == LdapASN1Constant.OP_UNBIND_REQUEST) {
            Object[] objs = new Object[1];
            requestOp.encodeValues(objs);
            values[1] = new ChosenValue(opIndex, objs[0]);
        } else {
            values[1] = new ChosenValue(opIndex, requestOp);
        }

        // encode controls, wrap to LdapControl, so it could be encoded
        if (controls != null) {
            List<LdapControl> list = new ArrayList<LdapControl>(controls.length);
            for (int i = 0; i < controls.length; ++i) {
                list.add(new LdapControl(controls[i]));
            }
            values[2] = list;
        }
    }

    /**
     * Get index of the operation, determine which operation is encapsulated in
     * this message. If this <code>LdapMessage</code> instance is not initial,
     * <code>-1</code> will be returned.
     *
     * @return index of the operation encapsulated in the message
     */
    public int getOperationIndex() {
        return opIndex;
    }

    public ASN1Decodable getResponseOp() {
        return responseOp;
    }

    public ASN1Encodable getRequestOp() {
        return requestOp;
    }

}
TOP

Related Classes of org.apache.harmony.jndi.provider.ldap.LdapMessage

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.