/*******************************************************************************

 * $Novell: ExtendSchema.java,v 1.12 2002/07/29 21:28:12 $

 * Copyright (c) 2000, 2001 Novell, Inc. All Rights Reserved.

 *

 * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND

 * TREATIES. USE AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO THE LICENSE

 * AGREEMENT ACCOMPANYING THE SOFTWARE DEVELOPMENT KIT (SDK) THAT CONTAINS

 * THIS WORK. PURSUANT TO THE SDK LICENSE AGREEMENT, NOVELL HEREBY GRANTS TO

 * DEVELOPER A ROYALTY-FREE, NON-EXCLUSIVE LICENSE TO INCLUDE NOVELL'S SAMPLE

 * CODE IN ITS PRODUCT. NOVELL GRANTS DEVELOPER WORLDWIDE DISTRIBUTION RIGHTS

 * TO MARKET, DISTRIBUTE, OR SELL NOVELL'S SAMPLE CODE AS A COMPONENT OF

 * DEVELOPER'S PRODUCTS. NOVELL SHALL HAVE NO OBLIGATIONS TO DEVELOPER OR

 * DEVELOPER'S CUSTOMERS WITH RESPECT TO THIS CODE.

 *

 * $name:         ExtendSchema.java

 * $description:  ExtendSchema.java demonstrates how to extend directory schema.

 *                It is used to add a new attribute definition, a

 *                new effective object class definition, and a new auxiliary

 *                class definition to the directory schema . Then it adds a

 *                test objec to the directory and add the new auxiliary class

 *                to the test object to show how to apply an auxiliary class to

 *                the test object.

 *                To extend directory schema, the user must have Admin

 *                equivalent rights. Novell recommend that users use ICE and

 *                ldif file ( Import, Conversion, and Export ) to modify schema

 *                instead of embedding schema extension commands within program

 *                files.

 ******************************************************************************/

import com.novell.ldap.*;

import java.io.UnsupportedEncodingException;



public class ExtendSchema

{



    // Create a new LDAPAttributeSchema object

    static LDAPAttributeSchema newAttrType = new LDAPAttributeSchema(

            new String[] {"testAttribute"},        // name of the new attr

            "2.16.840.1.113719.1.186.4.1",         // OID of the new attr

            "Test attr definition",                // desc of the new attr

            "1.3.6.1.4.1.1466.115.121.1.15" ,      // case-ignore string

            false,                                 // not single-valued

            null,                                  // no super attr type

            false,                                 // not obsolete

            null,                                  // no equality matching

            null,                                  // no ordering matching

            null,                                  // no substring matching

            false,                                 // not a collective attr

            true,                                  // user modifiable attr

            LDAPAttributeSchema.USER_APPLICATIONS);// user applications



     // Create a new effective class object

     static LDAPObjectClassSchema newObjClass = new LDAPObjectClassSchema(

            new String[] {"testClass"},            // name of the new obj class

            "2.16.840.1.113719.1.186.6.1",         // OID of effective class

            new String [] {"top"},                 // 'top' is super class

            "Test class definition",               // optional description

            new String [] {"cn", "title"},         // required attribute(s)

            null,                                  // optional attribute(s)

            LDAPObjectClassSchema.STRUCTURAL,      // effective class

            false);                                // not obsolete



    // Create a new auxiliary class object

    static LDAPObjectClassSchema newAuxClass =  new LDAPObjectClassSchema(

            new String[] {"testAuxClass"},         // name of the new obj class

            "2.16.840.1.113719.1.186.6.2",         // OID of this auxiliary class

            new String [] {"top"},                 // 'top' is super class

            "Test auxilliary class definition",    // optional description

            null,                                  // required attribute(s)

            new String [] {"testAttribute"},       // optional attribute

            LDAPObjectClassSchema.AUXILIARY,       // auxiliary class

            false);                                // not obsolete



    public static void main( String[] args )

    {

        if (args.length != 4) {

            usage();

            System.exit(1);

        }



        int ldapPort = LDAPConnection.DEFAULT_PORT;

        int ldapVersion = LDAPConnection.LDAP_V3;

        String ldapHost =  args[0];

        String loginDN =  args[1];

        String password =  args[2];

        String testObjDN =  "cn=testObject," + args[3];

        LDAPConnection conn = new LDAPConnection();



        // Add Novell eDirectory specific flags for attribute definition

        newAttrType.setQualifier( "X-NDS_PUBLIC_READ", new String [] {"1"});

        newAttrType.setQualifier( "X-NDS_NOT_SCHED_SYNC_IMMEDIATE",

                                                          new String [] {"1"});

        // Add Novell eDirectory specific flags for object class definition

        newObjClass.setQualifier( "X-NDS_NAMING", new String [] {"cn"});

        newObjClass.setQualifier( "X-NDS_CONTAINMENT", new String []

            {"organization", "organizationalUnit", "domain", "locality",

                                                                  "treeRoot"});



        try {

            // connect to the server

            conn.connect( ldapHost, ldapPort );

            // bind to the server

            conn.bind( ldapVersion, loginDN, password.getBytes("UTF8") );



            /*

             * Adding schema extensions includes:

             *     1. add a new attribute definition to directory schema

             *     2. add a new object class definition to directory schema

             *     3. add a new auxiliary class definition to directory schema

             */

            System.out.println( "\tAdding test schema extensions...");

            // add schema extensions

            if ( extendSchema( conn ) ) {

                // add a test object to the directory tree

                if ( addTestObject( conn, testObjDN ) ) {

                    // add the auxiliary class to the test object

                    addAuxClassToTestObj( conn, testObjDN );

                }

            }



           /*

            * Removing schema extensions consists of:

            *     1. remove auxiliary class definition from schema

            *     2. remove object class definition from schema

            *     3. remove attribute definition from schema

            */

           // remove auxiliary class from test object

           if ( removeAuxClassFromTestObj( conn, testObjDN ) ) {

                // remove test object

                if ( removeTestObj( conn, testObjDN ) ) {

                    System.out.println( "\tRemoving test schema extensions...");

                    unExtendSchema( conn );

                }

           }



            // disconnect with the server

            conn.disconnect();

        }

        catch( LDAPException e ) {

            System.out.println( "Error: " + e.toString() );

        }

        catch( UnsupportedEncodingException e) {

            System.out.println( "Error: " + e.toString() );

        }

        System.exit(0);

    }



    public static void usage() {

        System.err.println("Usage:   java ExtendSchema <host name>"

                         + " <login dn> <password> <test container DN>");

        System.err.println("Example: java ExtendSchema Acme.com"

                         + " \"cn=admin,o=Acme\" secret \"o=Acme\"");

    }



    // add schema extensions

    public static boolean extendSchema( LDAPConnection conn ) {

        boolean status = true;



        try {

            // Add attribute definition

            conn.modify( conn.getSchemaDN(),

                    new LDAPModification(LDAPModification.ADD, newAttrType));



            System.out.println("\tAdded attribute schema extensions successfully");



            // Add object definitions

            LDAPModification[] modifications = new LDAPModification[2];

            modifications[0] =

                    new LDAPModification(LDAPModification.ADD, newObjClass);

            modifications[1] =

                    new LDAPModification(LDAPModification.ADD, newAuxClass);



            conn.modify( conn.getSchemaDN(), modifications );

            System.out.println( "\tAdded object schema extensions successfully.");

        }

        catch( LDAPException e ) {

            System.out.println( "\tFailed to add schema extensions.");

            System.out.println( "Error: " + e.toString() );

            status = false;

        }

        return status;

    }



    // remove schema extensions

    public static boolean unExtendSchema( LDAPConnection conn ) {

        boolean status = true;



        try {

            // Remove auxiliary class definition

            // Add attribute definition

            LDAPModification[] modifications = new LDAPModification[2];

            modifications[1] =

                    new LDAPModification(LDAPModification.DELETE, newAuxClass);

            modifications[0] =

                    new LDAPModification(LDAPModification.DELETE, newObjClass);

            conn.modify( conn.getSchemaDN(), modifications);



            System.out.println(

                    "\tSuccessfully removed the object schema extensions");



            conn.modify( conn.getSchemaDN(),

                    new LDAPModification(LDAPModification.DELETE, newAttrType));

            System.out.println(

                    "\tSuccessfully removed the attribute schema extensions");

        }

        catch( LDAPException e ) {

            System.out.println( "\tFailed to remove the schema extensions." );

            System.out.println( "Error: " + e.toString() );

            status = false;

        }

        return status;

    }



    // add test object

    public static  boolean addTestObject( LDAPConnection conn, String dn ) {

        boolean status = true;

        LDAPAttribute     attribute = null;

        LDAPAttributeSet  attributeSet = new LDAPAttributeSet();



        attribute = new LDAPAttribute("objectclass",new String []{"testClass"});

        attributeSet.add( attribute );



        attribute = new LDAPAttribute( "cn", new String []{ "testObject",

                                                              "Test Object" });

        attributeSet.add( attribute );

        attribute = new LDAPAttribute( "title", new String []{ "testManager",

                                                              "Test Manager" });

        attributeSet.add( attribute );



        LDAPEntry newEntry = new LDAPEntry( dn, attributeSet );



         try {

            conn.add( newEntry );

            System.out.println( "\t\tAdded test object successfully.");

        }

        catch( LDAPException e ) {

            System.out.println( "\t\tFailed to add test object." );

            System.out.println( "Error: " + e.toString() );

            status = false;

        }

        return status;

    }



    // remove test object

    public static boolean removeTestObj( LDAPConnection conn, String dn ) {

        boolean status = true;



        try {

            conn.delete( dn );

            System.out.println("\t\tRemoved test object successfully.");

        }

        catch( LDAPException e ) {

            System.out.println("Failed to remove test object." );

            System.out.println( "Error: " + e.toString() );

            status = false;

        }

        return status;

    }



    // add auxiliary class to test object

    public static boolean addAuxClassToTestObj( LDAPConnection conn, String dn ) {

        boolean status = true;

        LDAPModification[]    mods = new LDAPModification[2];

        LDAPAttribute testAuxClass = new LDAPAttribute( "objectclass",

                                                               "testAuxClass" );

        mods[0] = new LDAPModification( LDAPModification.ADD, testAuxClass);

        LDAPAttribute testAttr = new LDAPAttribute("testAttribute", "pagerUser");

        mods[1] = new LDAPModification( LDAPModification.ADD, testAttr) ;



        try {

            conn.modify( dn, mods);

            System.out.println( "\t\tAdded auxiliary class to" +

                                                " test object successfully.");

        }

        catch( LDAPException e ) {

            System.out.println( "\t\tFailed to add auxiliary" +

                                                   " class to test object.");

            System.out.println( "Error: " + e.toString() );

            status = false;

        }

        return status;

    }



    // remove auxiliary class from test object

    public static boolean removeAuxClassFromTestObj( LDAPConnection conn, String dn ) {

        boolean status = true;

        LDAPModification[]  mods = new LDAPModification[2];

        LDAPAttribute testAuxClass = new LDAPAttribute( "objectclass",

                                                               "testAuxClass" );

        mods[0] = new LDAPModification( LDAPModification.DELETE, testAuxClass);

        LDAPAttribute testAttr = new LDAPAttribute("testAttribute", "pagerUser");

        mods[1] = new LDAPModification( LDAPModification.DELETE, testAttr);



        try {

            conn.modify( dn, mods );

            System.out.println( "\t\tRemoved auxiliary class from test" +

                                                     " object successfully.");

        }

        catch( LDAPException e ) {

            System.out.println( "\t\tFailed to remove auxiliary class from" +

                                                              " test object." );

            System.out.println( "Error: " + e.toString() );

            status = false;

        }

        return status;

    }

}

