alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (LdapSchemaCtx.java)

This example Java source code file (LdapSchemaCtx.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

attribute_root, attributes, basicattributes, cannot, ldapctx, ldapschemactx, ldapschemaparser, modificationitem, naming, namingexception, object, schema_root, schemainfo, schemaviolationexception, string, util

The LdapSchemaCtx.java Java example source code

/*
 * Copyright (c) 1999, 2011, 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 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<String,Object> 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);
                LdapSchemaParser.LDAP2JNDISchema(schemaAttrs, root);
                return root;
            } catch (NamingException e) {
                schemaEntry.close(); // cleanup
                throw e;
            }
    }

    // Called by createNewCtx
    private LdapSchemaCtx(int objectType, Hashtable<String,Object> 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<? extends Attribute> attrs = orig.getAll();
        while (attrs.hasMore()) {
            copy.put((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);
        }
    }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java LdapSchemaCtx.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.