/*
 * Copyright (c) 1999, 2005, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.jndi.ldap;

import javax.naming.*;
import javax.naming.directory.*;
import javax.naming.spi.DirectoryManager;
import javax.naming.spi.DirStateFactory;

import java.io.IOException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamClass;
import java.io.InputStream;

import java.util.Hashtable;
import java.util.Vector;
import java.util.StringTokenizer;

import sun.misc.BASE64Encoder;
import sun.misc.BASE64Decoder;

import java.lang.reflect.Proxy;
import java.lang.reflect.Modifier;

/**
  * Class containing static methods and constants for dealing with
  * encoding/decoding JNDI References and Serialized Objects
  * in LDAP.
  * @author Vincent Ryan
  * @author Rosanna Lee
  */
final class Obj {

    private Obj () {}; // Make sure no one can create one

    // package private; used by Connection
    static VersionHelper helper = VersionHelper.getVersionHelper();

    // LDAP attributes used to support Java objects.
    static final String[] JAVA_ATTRIBUTES = {
        "objectClass",
        "javaSerializedData",
        "javaClassName",
        "javaFactory",
        "javaCodeBase",
        "javaReferenceAddress",
        "javaClassNames",
        "javaRemoteLocation"     // Deprecated
    };

    static final int OBJECT_CLASS = 0;
    static final int SERIALIZED_DATA = 1;
    static final int CLASSNAME = 2;
    static final int FACTORY = 3;
    static final int CODEBASE = 4;
    static final int REF_ADDR = 5;
    static final int TYPENAME = 6;
    /**
     * @deprecated
     */
    private static final int REMOTE_LOC = 7;

    // LDAP object classes to support Java objects
    static final String[] JAVA_OBJECT_CLASSES = {
        "javaContainer",
        "javaObject",
        "javaNamingReference",
        "javaSerializedObject",
        "javaMarshalledObject",
    };

    static final String[] JAVA_OBJECT_CLASSES_LOWER = {
        "javacontainer",
        "javaobject",
        "javanamingreference",
        "javaserializedobject",
        "javamarshalledobject",
    };

    static final int STRUCTURAL = 0;    // structural object class
    static final int BASE_OBJECT = 1;   // auxiliary java object class
    static final int REF_OBJECT = 2;    // auxiliary reference object class
    static final int SER_OBJECT = 3;    // auxiliary serialized object class
    static final int MAR_OBJECT = 4;    // auxiliary marshalled object class

    /**
     * Encode an object in LDAP attributes.
     * Supports binding Referenceable or Reference, Serializable,
     * and DirContext.
     *
     * If the object supports the Referenceable interface then encode
     * the reference to the object. See encodeReference() for details.
     *<p>
     * If the object is serializable, it is stored as follows:
     * javaClassName
     *   value: Object.getClass();
     * javaSerializedData
     *   value: serialized form of Object (in binary form).
     * javaTypeName
     *   value: getTypeNames(Object.getClass());
     */
    private static Attributes encodeObject(char separator,
        Object obj, Attributes attrs,
        Attribute objectClass, boolean cloned)
        throws NamingException {
            boolean structural =
                (objectClass.size() == 0 ||
                    (objectClass.size() == 1 && objectClass.contains("top")));

            if (structural) {
                objectClass.add(JAVA_OBJECT_CLASSES[STRUCTURAL]);
            }

    // References
            if (obj instanceof Referenceable) {
                objectClass.add(JAVA_OBJECT_CLASSES[BASE_OBJECT]);
                objectClass.add(JAVA_OBJECT_CLASSES[REF_OBJECT]);
                if (!cloned) {
                    attrs = (Attributes)attrs.clone();
                }
                attrs.put(objectClass);
                return (encodeReference(separator,
                    ((Referenceable)obj).getReference(),
                    attrs, obj));

            } else if (obj instanceof Reference) {
                objectClass.add(JAVA_OBJECT_CLASSES[BASE_OBJECT]);
                objectClass.add(JAVA_OBJECT_CLASSES[REF_OBJECT]);
                if (!cloned) {
                    attrs = (Attributes)attrs.clone();
                }
                attrs.put(objectClass);
                return (encodeReference(separator, (Reference)obj, attrs, null));

    // Serializable Object
            } else if (obj instanceof java.io.Serializable) {
                objectClass.add(JAVA_OBJECT_CLASSES[BASE_OBJECT]);
                if (!(objectClass.contains(JAVA_OBJECT_CLASSES[MAR_OBJECT]) ||
                    objectClass.contains(JAVA_OBJECT_CLASSES_LOWER[MAR_OBJECT]))) {
                    objectClass.add(JAVA_OBJECT_CLASSES[SER_OBJECT]);
                }
                if (!cloned) {
                    attrs = (Attributes)attrs.clone();
                }
                attrs.put(objectClass);
                attrs.put(new BasicAttribute(JAVA_ATTRIBUTES[SERIALIZED_DATA],
                    serializeObject(obj)));
                if (attrs.get(JAVA_ATTRIBUTES[CLASSNAME]) == null) {
                    attrs.put(JAVA_ATTRIBUTES[CLASSNAME],
                        obj.getClass().getName());
                }
                if (attrs.get(JAVA_ATTRIBUTES[TYPENAME]) == null) {
                    Attribute tAttr =
                        LdapCtxFactory.createTypeNameAttr(obj.getClass());
                    if (tAttr != null) {
                        attrs.put(tAttr);
                    }
                }
    // DirContext Object
            } else if (obj instanceof DirContext) {
                // do nothing
            } else {
                throw new IllegalArgumentException(
            "can only bind Referenceable, Serializable, DirContext");
            }
            //      System.err.println(attrs);
            return attrs;
    }

    /**
     * Each value in javaCodebase contains a list of space-separated
     * URLs. Each value is independent; we can pick any of the values
     * so we just use the first one.
     * @return an array of URL strings for the codebase
     */
    private static String[] getCodebases(Attribute codebaseAttr) throws
        NamingException {
        if (codebaseAttr == null) {
            return null;
        } else {
            StringTokenizer parser =
                new StringTokenizer((String)codebaseAttr.get());
            Vector vec = new Vector(10);
            while (parser.hasMoreTokens()) {
                vec.addElement(parser.nextToken());
            }
            String[] answer = new String[vec.size()];
            for (int i = 0; i < answer.length; i++) {
                answer[i] = (String)vec.elementAt(i);
            }
            return answer;
        }
    }

    /*
     * Decode an object from LDAP attribute(s).
     * The object may be a Reference, or a Serialized object.
     *
     * See encodeObject() and encodeReference() for details on formats
     * expected.
     */
    static Object decodeObject(Attributes attrs)
        throws NamingException {

        Attribute attr;

        // Get codebase, which is used in all 3 cases.
        String[] codebases = getCodebases(attrs.get(JAVA_ATTRIBUTES[CODEBASE]));
        try {
            if ((attr = attrs.get(JAVA_ATTRIBUTES[SERIALIZED_DATA])) != null) {
                ClassLoader cl = helper.getURLClassLoader(codebases);
                return deserializeObject((byte[])attr.get(), cl);
            } else if ((attr = attrs.get(JAVA_ATTRIBUTES[REMOTE_LOC])) != null) {
                // For backward compatibility only
                return decodeRmiObject(
                    (String)attrs.get(JAVA_ATTRIBUTES[CLASSNAME]).get(),
                    (String)attr.get(), codebases);
            }

            attr = attrs.get(JAVA_ATTRIBUTES[OBJECT_CLASS]);
            if (attr != null &&
                (attr.contains(JAVA_OBJECT_CLASSES[REF_OBJECT]) ||
                    attr.contains(JAVA_OBJECT_CLASSES_LOWER[REF_OBJECT]))) {
                return decodeReference(attrs, codebases);
            }
            return null;
        } catch (IOException e) {
            NamingException ne = new NamingException();
            ne.setRootCause(e);
            throw ne;
        }
    }

    /**
     * Convert a Reference object into several LDAP attributes.
     *
     * A Reference is stored as into the following attributes:
     * javaClassName
     *   value: Reference.getClassName();
     * javaFactory
     *   value: Reference.getFactoryClassName();
     * javaCodeBase
     *   value: Reference.getFactoryClassLocation();
     * javaReferenceAddress
     *   value: #0#typeA#valA
     *   value: #1#typeB#valB
     *   value: #2#typeC##[serialized RefAddr C]
     *   value: #3#typeD#valD
     *
     * where
     * -  the first character denotes the separator
     * -  the number following the first separator denotes the position
     *    of the RefAddr within the Reference
     * -  "typeA" is RefAddr.getType()
     * -  ## denotes that the Base64-encoded form of the non-StringRefAddr
     *    is to follow; otherwise the value that follows is
     *    StringRefAddr.getContents()
     *
     * The default separator is the hash character (#).
     * May provide property for this in future.
     */

    private static Attributes encodeReference(char separator,
        Reference ref, Attributes attrs, Object orig)
        throws NamingException {

        if (ref == null)
            return attrs;

        String s;

        if ((s = ref.getClassName()) != null) {
            attrs.put(new BasicAttribute(JAVA_ATTRIBUTES[CLASSNAME], s));
        }

        if ((s = ref.getFactoryClassName()) != null) {
            attrs.put(new BasicAttribute(JAVA_ATTRIBUTES[FACTORY], s));
        }

        if ((s = ref.getFactoryClassLocation()) != null) {
            attrs.put(new BasicAttribute(JAVA_ATTRIBUTES[CODEBASE], s));
        }

        // Get original object's types if caller has not explicitly
        // specified other type names
        if (orig != null && attrs.get(JAVA_ATTRIBUTES[TYPENAME]) != null) {
            Attribute tAttr =
                LdapCtxFactory.createTypeNameAttr(orig.getClass());
            if (tAttr != null) {
                attrs.put(tAttr);
            }
        }

        int count = ref.size();

        if (count > 0) {

            Attribute refAttr = new BasicAttribute(JAVA_ATTRIBUTES[REF_ADDR]);
            RefAddr refAddr;
            BASE64Encoder encoder = null;

            for (int i = 0; i < count; i++) {
                refAddr = ref.get(i);

                if (refAddr instanceof StringRefAddr) {
                    refAttr.add(""+ separator + i +
                        separator +     refAddr.getType() +
                        separator + refAddr.getContent());
                } else {
                    if (encoder == null)
                        encoder = new BASE64Encoder();

                    refAttr.add(""+ separator + i +
                        separator + refAddr.getType() +
                        separator + separator +
                        encoder.encodeBuffer(serializeObject(refAddr)));
                }
            }
            attrs.put(refAttr);
        }
        return attrs;
    }

    /*
     * A RMI object is stored in the directory as
     * javaClassName
     *   value: Object.getClass();
     * javaRemoteLocation
     *   value: URL of RMI object (accessed through the RMI Registry)
     * javaCodebase:
     *   value: URL of codebase of where to find classes for object
     *
     * Return the RMI Location URL itself. This will be turned into
     * an RMI object when getObjectInstance() is called on it.
     * %%% Ignore codebase for now. Depend on RMI registry to send code.-RL
     * @deprecated For backward compatibility only
     */
    private static Object decodeRmiObject(String className,
        String rmiName, String[] codebases) throws NamingException {
            return new Reference(className, new StringRefAddr("URL", rmiName));
    }

    /*
     * Restore a Reference object from several LDAP attributes
     */
    private static Reference decodeReference(Attributes attrs,
        String[] codebases) throws NamingException, IOException {

        Attribute attr;
        String className;
        String factory = null;

        if ((attr = attrs.get(JAVA_ATTRIBUTES[CLASSNAME])) != null) {
            className = (String)attr.get();
        } else {
            throw new InvalidAttributesException(JAVA_ATTRIBUTES[CLASSNAME] +
                        " attribute is required");
        }

        if ((attr = attrs.get(JAVA_ATTRIBUTES[FACTORY])) != null) {
            factory = (String)attr.get();
        }

        Reference ref = new Reference(className, factory,
            (codebases != null? codebases[0] : null));

        /*
         * string encoding of a RefAddr is either:
         *
         *      #posn#<type>#<address>
         * or
         *      #posn#<type>##<base64-encoded address>
         */
        if ((attr = attrs.get(JAVA_ATTRIBUTES[REF_ADDR])) != null) {

            String val, posnStr, type;
            char separator;
            int start, sep, posn;
            BASE64Decoder decoder = null;

            ClassLoader cl = helper.getURLClassLoader(codebases);

            /*
             * Temporary Vector for decoded RefAddr addresses - used to ensure
             * unordered addresses are correctly re-ordered.
             */
            Vector refAddrList = new Vector();
            refAddrList.setSize(attr.size());

            for (NamingEnumeration vals = attr.getAll(); vals.hasMore(); ) {

                val = (String)vals.next();

                if (val.length() == 0) {
                    throw new InvalidAttributeValueException(
                        "malformed " + JAVA_ATTRIBUTES[REF_ADDR] + " attribute - "+
                        "empty attribute value");
                }
                // first character denotes encoding separator
                separator = val.charAt(0);
                start = 1;  // skip over separator

                // extract position within Reference
                if ((sep = val.indexOf(separator, start)) < 0) {
                    throw new InvalidAttributeValueException(
                        "malformed " + JAVA_ATTRIBUTES[REF_ADDR] + " attribute - " +
                        "separator '" + separator + "'" + "not found");
                }
                if ((posnStr = val.substring(start, sep)) == null) {
                    throw new InvalidAttributeValueException(
                        "malformed " + JAVA_ATTRIBUTES[REF_ADDR] + " attribute - " +
                        "empty RefAddr position");
                }
                try {
                    posn = Integer.parseInt(posnStr);
                } catch (NumberFormatException nfe) {
                    throw new InvalidAttributeValueException(
                        "malformed " + JAVA_ATTRIBUTES[REF_ADDR] + " attribute - " +
                        "RefAddr position not an integer");
                }
                start = sep + 1; // skip over position and trailing separator

                // extract type
                if ((sep = val.indexOf(separator, start)) < 0) {
                    throw new InvalidAttributeValueException(
                        "malformed " + JAVA_ATTRIBUTES[REF_ADDR] + " attribute - " +
                        "RefAddr type not found");
                }
                if ((type = val.substring(start, sep)) == null) {
                    throw new InvalidAttributeValueException(
                        "malformed " + JAVA_ATTRIBUTES[REF_ADDR] + " attribute - " +
                        "empty RefAddr type");
                }
                start = sep + 1; // skip over type and trailing separator

                // extract content
                if (start == val.length()) {
                    // Empty content
                    refAddrList.setElementAt(new StringRefAddr(type, null), posn);
                } else if (val.charAt(start) == separator) {
                    // Double separators indicate a non-StringRefAddr
                    // Content is a Base64-encoded serialized RefAddr

                    ++start;  // skip over consecutive separator
                    // %%% RL: exception if empty after double separator

                    if (decoder == null)
                        decoder = new BASE64Decoder();

                    RefAddr ra = (RefAddr)
                        deserializeObject(
                            decoder.decodeBuffer(val.substring(start)),
                            cl);

                    refAddrList.setElementAt(ra, posn);
                } else {
                    // Single separator indicates a StringRefAddr
                    refAddrList.setElementAt(new StringRefAddr(type,
                        val.substring(start)), posn);
                }
            }

            // Copy to real reference
            for (int i = 0; i < refAddrList.size(); i++) {
                ref.add((RefAddr)refAddrList.elementAt(i));
            }
        }

        return (ref);
    }

    /*
     * Serialize an object into a byte array
     */
    private static byte[] serializeObject(Object obj) throws NamingException {

        try {
            ByteArrayOutputStream bytes = new ByteArrayOutputStream();
            ObjectOutputStream serial = new ObjectOutputStream(bytes);
            serial.writeObject(obj);
            serial.close();

            return (bytes.toByteArray());

        } catch (IOException e) {
            NamingException ne = new NamingException();
            ne.setRootCause(e);
            throw ne;
        }
    }

    /*
     * Deserializes a byte array into an object.
     */
    private static Object deserializeObject(byte[] obj, ClassLoader cl)
        throws NamingException {

        try {
            // Create ObjectInputStream for deserialization
            ByteArrayInputStream bytes = new ByteArrayInputStream(obj);
            ObjectInputStream deserial = (cl == null ?
                new ObjectInputStream(bytes) :
                new LoaderInputStream(bytes, cl));

            try {
                return deserial.readObject();
            } catch (ClassNotFoundException e) {
                NamingException ne = new NamingException();
                ne.setRootCause(e);
                throw ne;
            } finally {
                deserial.close();
            }
        } catch (IOException e) {
            NamingException ne = new NamingException();
            ne.setRootCause(e);
            throw ne;
        }
    }

    /**
      * Returns the attributes to bind given an object and its attributes.
      */
    static Attributes determineBindAttrs(
        char separator, Object obj, Attributes attrs, boolean cloned,
        Name name, Context ctx, Hashtable env)
        throws NamingException {

        // Call state factories to convert object and attrs
        DirStateFactory.Result res =
            DirectoryManager.getStateToBind(obj, name, ctx, env, attrs);
        obj = res.getObject();
        attrs = res.getAttributes();

        // We're only storing attributes; no further processing required
        if (obj == null) {
            return attrs;
        }

        //if object to be bound is a DirContext extract its attributes
        if ((attrs == null) && (obj instanceof DirContext)) {
            cloned = true;
            attrs = ((DirContext)obj).getAttributes("");
        }

        boolean ocNeedsCloning = false;

        // Create "objectClass" attribute
        Attribute objectClass;
        if (attrs == null || attrs.size() == 0) {
            attrs = new BasicAttributes(LdapClient.caseIgnore);
            cloned = true;

            // No objectclasses supplied, use "top" to start
            objectClass = new BasicAttribute("objectClass", "top");

        } else {
            // Get existing objectclass attribute
            objectClass = (Attribute)attrs.get("objectClass");
            if (objectClass == null && !attrs.isCaseIgnored()) {
                // %%% workaround
                objectClass = (Attribute)attrs.get("objectclass");
            }

            // No objectclasses supplied, use "top" to start
            if (objectClass == null) {
                objectClass =  new BasicAttribute("objectClass", "top");
            } else if (ocNeedsCloning || !cloned) {
                objectClass = (Attribute)objectClass.clone();
            }
        }

        // convert the supplied object into LDAP attributes
        attrs = encodeObject(separator, obj, attrs, objectClass, cloned);

        // System.err.println("Determined: " + attrs);
        return attrs;
    }

    /**
     * An ObjectInputStream that uses a class loader to find classes.
     */
    private static final class LoaderInputStream extends ObjectInputStream {
        private ClassLoader classLoader;

        LoaderInputStream(InputStream in, ClassLoader cl) throws IOException {
            super(in);
            classLoader = cl;
        }

        protected Class resolveClass(ObjectStreamClass desc) throws IOException,
            ClassNotFoundException {
            try {
                // %%% Should use Class.forName(desc.getName(), false, classLoader);
                // except we can't because that is only available on JDK1.2
                return classLoader.loadClass(desc.getName());
            } catch (ClassNotFoundException e) {
                return super.resolveClass(desc);
            }
        }

         protected Class resolveProxyClass(String[] interfaces) throws
                IOException, ClassNotFoundException {
             ClassLoader nonPublicLoader = null;
             boolean hasNonPublicInterface = false;

             // define proxy in class loader of non-public interface(s), if any
             Class[] classObjs = new Class[interfaces.length];
             for (int i = 0; i < interfaces.length; i++) {
                 Class cl = Class.forName(interfaces[i], false, classLoader);
                 if ((cl.getModifiers() & Modifier.PUBLIC) == 0) {
                     if (hasNonPublicInterface) {
                         if (nonPublicLoader != cl.getClassLoader()) {
                             throw new IllegalAccessError(
                                "conflicting non-public interface class loaders");
                         }
                     } else {
                         nonPublicLoader = cl.getClassLoader();
                         hasNonPublicInterface = true;
                     }
                 }
                 classObjs[i] = cl;
             }
             try {
                 return Proxy.getProxyClass(hasNonPublicInterface ?
                        nonPublicLoader : classLoader, classObjs);
             } catch (IllegalArgumentException e) {
                 throw new ClassNotFoundException(null, e);
             }
         }

     }
}
