/*
 * Copyright 1999-2003 Sun Microsystems, Inc.  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.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package com.sun.jndi.ldap;

import javax.naming.*;
import javax.naming.directory.*;
import java.util.Hashtable;
import com.sun.jndi.toolkit.dir.HierMemDirCtx;

/**
 * This is the class used to implement LDAP's GetSchema call.
 *
 * It subclasses HierMemDirContext for most of the functionality. It
 * overrides functions that cause the schema definitions to change.
 * In such a case, it write the schema to the LdapServer and (assuming
 * there are no errors), calls it's superclass's equivalent function.
 * Thus, the schema tree and the LDAP server's schema attributes are
 * always in sync.
 */

final class LdapSchemaCtx extends HierMemDirCtx {

    static private final boolean debug = false;

    private static final int LEAF = 0;  // schema object (e.g. attribute type defn)
    private static final int SCHEMA_ROOT = 1;   // schema tree root
    static final int OBJECTCLASS_ROOT = 2;   // root of object class subtree
    static final int ATTRIBUTE_ROOT = 3;     // root of attribute type subtree
    static final int SYNTAX_ROOT = 4;        // root of syntax subtree
    static final int MATCHRULE_ROOT = 5;     // root of matching rule subtree
    static final int OBJECTCLASS = 6;   // an object class definition
    static final int ATTRIBUTE = 7;     // an attribute type definition
    static final int SYNTAX = 8;        // a syntax definition
    static final int MATCHRULE = 9;     // a matching rule definition

    private SchemaInfo info= null;
    private boolean setupMode = true;

    private int objectType;

    static DirContext createSchemaTree(Hashtable env, String subschemasubentry,
        LdapCtx schemaEntry, Attributes schemaAttrs, boolean netscapeBug)
        throws NamingException {
            try {
                LdapSchemaParser parser = new LdapSchemaParser(netscapeBug);

                SchemaInfo allinfo = new SchemaInfo(subschemasubentry,
                    schemaEntry, parser);

                LdapSchemaCtx root = new LdapSchemaCtx(SCHEMA_ROOT, env, allinfo);
                parser.LDAP2JNDISchema(schemaAttrs, root);
                return root;
            } catch (NamingException e) {
                schemaEntry.close(); // cleanup
                throw e;
            }
    }

    // Called by createNewCtx
    private LdapSchemaCtx(int objectType, Hashtable environment, SchemaInfo info) {
        super(environment, LdapClient.caseIgnore);

        this.objectType = objectType;
        this.info = info;
    }

    // override HierMemDirCtx.close to prevent premature GC of shared data
    public void close() throws NamingException {
        info.close();
    }

    // override to ignore obj and use attrs
    // treat same as createSubcontext
    final public void bind(Name name, Object obj, Attributes attrs)
        throws NamingException {
        if (!setupMode) {
            if (obj != null) {
                throw new IllegalArgumentException("obj must be null");
            }

            // Update server
            addServerSchema(attrs);
        }

        // Update in-memory copy
        LdapSchemaCtx newEntry =
            (LdapSchemaCtx)super.doCreateSubcontext(name, attrs);
    }

    final protected void doBind(Name name, Object obj, Attributes attrs,
        boolean useFactory) throws NamingException {
        if (!setupMode) {
            throw new SchemaViolationException(
                "Cannot bind arbitrary object; use createSubcontext()");
        } else {
            super.doBind(name, obj, attrs, false); // always ignore factories
        }
    }

    // override to use bind() instead
    final public void rebind(Name name, Object obj, Attributes attrs)
        throws NamingException {
        try {
            doLookup(name, false);
            throw new SchemaViolationException(
                "Cannot replace existing schema object");
        } catch (NameNotFoundException e) {
            bind(name, obj, attrs);
        }
    }

    final protected void doRebind(Name name, Object obj, Attributes attrs,
        boolean useFactory) throws NamingException {
        if (!setupMode) {
            throw new SchemaViolationException(
                "Cannot bind arbitrary object; use createSubcontext()");
        } else {
            super.doRebind(name, obj, attrs, false); // always ignore factories
        }
    }

    final protected void doUnbind(Name name) throws NamingException {
        if (!setupMode) {
            // Update server
            try {
                // Lookup entry from memory
                LdapSchemaCtx target = (LdapSchemaCtx)doLookup(name, false);

                deleteServerSchema(target.attrs);
            } catch (NameNotFoundException e) {
                return;
            }
        }
        // Update in-memory copy
        super.doUnbind(name);
    }

    final protected void doRename(Name oldname, Name newname)
        throws NamingException {
        if (!setupMode) {
            throw new SchemaViolationException("Cannot rename a schema object");
        } else {
            super.doRename(oldname, newname);
        }
    }

    final protected void doDestroySubcontext(Name name) throws NamingException {
        if (!setupMode) {
            // Update server
            try {
                // Lookup entry from memory
                LdapSchemaCtx target = (LdapSchemaCtx)doLookup(name, false);

                deleteServerSchema(target.attrs);
            } catch (NameNotFoundException e) {
                return;
            }
        }

        // Update in-memory copy
        super.doDestroySubcontext(name);
     }

    // Called to create oc, attr, syntax or matching rule roots and leaf entries
    final LdapSchemaCtx setup(int objectType, String name, Attributes attrs)
        throws NamingException{
            try {
                setupMode = true;
                LdapSchemaCtx answer =
                    (LdapSchemaCtx) super.doCreateSubcontext(
                        new CompositeName(name), attrs);

                answer.objectType = objectType;
                answer.setupMode = false;
                return answer;
            } finally {
                setupMode = false;
            }
    }

    final protected DirContext doCreateSubcontext(Name name, Attributes attrs)
        throws NamingException {

        if (attrs == null || attrs.size() == 0) {
            throw new SchemaViolationException(
                "Must supply attributes describing schema");
        }

        if (!setupMode) {
            // Update server
            addServerSchema(attrs);
        }

        // Update in-memory copy
        LdapSchemaCtx newEntry =
            (LdapSchemaCtx) super.doCreateSubcontext(name, attrs);
        return newEntry;
    }

    final private static Attributes deepClone(Attributes orig)
        throws NamingException {
        BasicAttributes copy = new BasicAttributes(true);
        NamingEnumeration attrs = orig.getAll();
        while (attrs.hasMore()) {
            copy.put((Attribute)((Attribute)attrs.next()).clone());
        }
        return copy;
    }

    final protected void doModifyAttributes(ModificationItem[] mods)
        throws NamingException {
        if (setupMode) {
            super.doModifyAttributes(mods);
        } else {
            Attributes copy = deepClone(attrs);

            // Apply modifications to copy
            applyMods(mods, copy);

            // Update server copy
            modifyServerSchema(attrs, copy);

            // Update in-memory copy
            attrs = copy;
        }
    }

    // we override this so the superclass creates the right kind of contexts
    // Default is to create LEAF objects; caller will change after creation
    // if necessary
    final protected HierMemDirCtx createNewCtx() {
        LdapSchemaCtx ctx = new LdapSchemaCtx(LEAF, myEnv, info);
        return ctx;
    }


    final private void addServerSchema(Attributes attrs)
        throws NamingException {
        Attribute schemaAttr;

        switch (objectType) {
        case OBJECTCLASS_ROOT:
            schemaAttr = info.parser.stringifyObjDesc(attrs);
            break;

        case ATTRIBUTE_ROOT:
            schemaAttr = info.parser.stringifyAttrDesc(attrs);
            break;

        case SYNTAX_ROOT:
            schemaAttr = info.parser.stringifySyntaxDesc(attrs);
            break;

        case MATCHRULE_ROOT:
            schemaAttr = info.parser.stringifyMatchRuleDesc(attrs);
            break;

        case SCHEMA_ROOT:
            throw new SchemaViolationException(
                "Cannot create new entry under schema root");

        default:
            throw new SchemaViolationException(
                "Cannot create child of schema object");
        }

        Attributes holder = new BasicAttributes(true);
        holder.put(schemaAttr);
        //System.err.println((String)schemaAttr.get());

        info.modifyAttributes(myEnv, DirContext.ADD_ATTRIBUTE, holder);

    }

    /**
      * When we delete an entry, we use the original to make sure that
      * any formatting inconsistencies are eliminated.
      * This is because we're just deleting a value from an attribute
      * on the server and there might not be any checks for extra spaces
      * or parens.
      */
    final private void deleteServerSchema(Attributes origAttrs)
        throws NamingException {

        Attribute origAttrVal;

        switch (objectType) {
        case OBJECTCLASS_ROOT:
            origAttrVal = info.parser.stringifyObjDesc(origAttrs);
            break;

        case ATTRIBUTE_ROOT:
            origAttrVal = info.parser.stringifyAttrDesc(origAttrs);
            break;

        case SYNTAX_ROOT:
            origAttrVal = info.parser.stringifySyntaxDesc(origAttrs);
            break;

        case MATCHRULE_ROOT:
            origAttrVal = info.parser.stringifyMatchRuleDesc(origAttrs);
            break;

        case SCHEMA_ROOT:
            throw new SchemaViolationException(
                "Cannot delete schema root");

        default:
            throw new SchemaViolationException(
                "Cannot delete child of schema object");
        }

        ModificationItem[] mods = new ModificationItem[1];
        mods[0] = new ModificationItem(DirContext.REMOVE_ATTRIBUTE, origAttrVal);

        info.modifyAttributes(myEnv, mods);
    }

    /**
      * When we modify an entry, we use the original attribute value
      * in the schema to make sure that any formatting inconsistencies
      * are eliminated. A modification is done by deleting the original
      * value and adding a new value with the modification.
      */
    final private void modifyServerSchema(Attributes origAttrs,
        Attributes newAttrs) throws NamingException {

        Attribute newAttrVal;
        Attribute origAttrVal;

        switch (objectType) {
        case OBJECTCLASS:
            origAttrVal = info.parser.stringifyObjDesc(origAttrs);
            newAttrVal = info.parser.stringifyObjDesc(newAttrs);
            break;

        case ATTRIBUTE:
            origAttrVal = info.parser.stringifyAttrDesc(origAttrs);
            newAttrVal = info.parser.stringifyAttrDesc(newAttrs);
            break;

        case SYNTAX:
            origAttrVal = info.parser.stringifySyntaxDesc(origAttrs);
            newAttrVal = info.parser.stringifySyntaxDesc(newAttrs);
            break;

        case MATCHRULE:
            origAttrVal = info.parser.stringifyMatchRuleDesc(origAttrs);
            newAttrVal = info.parser.stringifyMatchRuleDesc(newAttrs);
            break;

        default:
            throw new SchemaViolationException(
                "Cannot modify schema root");
        }

        ModificationItem[] mods = new ModificationItem[2];
        mods[0] = new ModificationItem(DirContext.REMOVE_ATTRIBUTE, origAttrVal);
        mods[1] = new ModificationItem(DirContext.ADD_ATTRIBUTE, newAttrVal);

        info.modifyAttributes(myEnv, mods);
    }

    final static private class SchemaInfo {
        private LdapCtx schemaEntry;
        private String schemaEntryName;
        LdapSchemaParser parser;
        private String host;
        private int port;
        private boolean hasLdapsScheme;

        SchemaInfo(String schemaEntryName, LdapCtx schemaEntry,
            LdapSchemaParser parser) {
            this.schemaEntryName = schemaEntryName;
            this.schemaEntry = schemaEntry;
            this.parser = parser;
            this.port = schemaEntry.port_number;
            this.host = schemaEntry.hostname;
            this.hasLdapsScheme = schemaEntry.hasLdapsScheme;
        }

        synchronized void close() throws NamingException {
            if (schemaEntry != null) {
                schemaEntry.close();
                schemaEntry = null;
            }
        }

        private LdapCtx reopenEntry(Hashtable env) throws NamingException {
            // Use subschemasubentry name as DN
            return new LdapCtx(schemaEntryName, host, port,
                                env, hasLdapsScheme);
        }

        synchronized void modifyAttributes(Hashtable env, ModificationItem[] mods)
            throws NamingException {
            if (schemaEntry == null) {
                schemaEntry = reopenEntry(env);
            }
            schemaEntry.modifyAttributes("", mods);
        }

        synchronized void modifyAttributes(Hashtable env, int mod,
            Attributes attrs) throws NamingException {
            if (schemaEntry == null) {
                schemaEntry = reopenEntry(env);
            }
            schemaEntry.modifyAttributes("", mod, attrs);
        }
    }
}
