/* * Copyright (c) 1999. Sun Microsystems. All rights reserved. * * Creates a schema for storing Java objects according to * draft-ryan-java-schema-02.txt. After running this program, you * should verify that the schema has been updated correctly * by using the directory server's administration tool. If the * schema has not been properly updated, use the administration tool * to correct it. * * You should first turn off schema-checking at the directory server * before running this program. * * usage: * java [-Djava.naming.provider.url=] \ * CreateJavaSchema [-h|-l|-s[n|n41]] [-n] [-p] [-a] * * -h Print the usage message * -l List the Java schema in the directory * -s[n|n41] Update schema (-sn means use the workaround for schema bugs * in pre-4.1 releases of Netscape Directory Server; * -sn41 means use the workaround for schema bugs in Netscape 4.1). * -n Use as the distinguished name for authentication * -p Use as the password for authentication * -a Use as the authentication mechanism. Default is "simple". * * If neither -s, -l, nor -h has been specified, the default is "-l". * * Here is an example. * The following updates the schema (using the workaround for 4.1 * Netscape schema bugs), logging in as "cn=directory manager" with the * password "secret". * #java CreateJavaSchema -sn41 "-ncn=directory manager" -psecret * * @author Rosanna Lee */ import javax.naming.*; import javax.naming.directory.*; import java.util.Hashtable; public class CreateJavaSchema { protected static String dn, passwd, auth; protected static boolean netscapebug; // NS 4.1 has problems parsing an object class definition which contains // a MUST clause without parentheses. The workaround is to add a // superfluous value (objectClass) to each MUST clause. // // It also doesn't like the Octet String syntax (use Binary instead) // protected static boolean netscape41bug = false; protected static boolean traceLdap = false; protected static final int LIST = 0; protected static final int UPDATE = 1; private static String[] allAttrs = { "javaSerializedObject", "javaFactoryLocation", "javaReferenceAddress", "javaFactory", "javaClassName", "javaClassNames", "javaDoc", "javaSerializedData", "javaCodebase", "javaFactory", "javaReferenceAddress"}; private static String[] allOCs = { "javaObject", "javaNamingReference", "javaSerializedObject", "javaRemoteObject", "javaMarshalledObject", "javaContainer"}; public static void main(String[] args) { new CreateJavaSchema().run(args, allAttrs, allOCs); } CreateJavaSchema () { } protected void run(String[] args, String[] attrIDs, String[] ocIDs) { int cmd = processCommandLine(args); try { DirContext ctx = signOn(); switch (cmd) { case UPDATE: updateSchema(ctx, attrIDs, ocIDs); break; default: showSchema(ctx, attrIDs, ocIDs); } } catch (NamingException e) { e.printStackTrace(); } } /** * Signs on to directory server using parameters supplied to program. * @return The initial context to the server. */ private DirContext signOn() throws NamingException { if (dn != null && auth == null) { auth = "simple"; // use simple for Netscape } Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.REFERRAL, "follow"); if (auth != null) { env.put(Context.SECURITY_AUTHENTICATION, auth); env.put(Context.SECURITY_PRINCIPAL, dn); env.put(Context.SECURITY_CREDENTIALS, passwd); } // Workaround for Netscape schema bugs if (netscapebug) { env.put("com.sun.naming.netscape.schemaBugs", "true"); } // LDAP protocol tracing if (traceLdap) { env.put("com.sun.jndi.ldap.trace.ber", System.err); } return new InitialDirContext(env); } void showSchema(DirContext ctx, String[] attrs, String[] ocs) throws NamingException { DirContext attrRoot = (DirContext)ctx.getSchema("").lookup("AttributeDefinition"); printSchema(attrRoot, attrs); DirContext ocRoot = (DirContext)ctx.getSchema("").lookup("ClassDefinition"); printSchema(ocRoot, ocs); } private void printSchema(DirContext ctx, String[] ids) { for (int i = 0; i < ids.length; i++) { try { System.out.print(ids[i] + ": "); System.out.print(ctx.getAttributes(ids[i])); } catch (NamingException e) { } finally { System.out.println(); } } } /** * Updates the schema: * * Delete obsolete attributes: * javaSerializedObject * javaFactoryLocation * javaReferenceAddress * javaFactory * javaClassName * + all the new ones that we're going to add * Add new and updated attributes: * javaSerializedData * javaCodebase * javaClassName * javaClassNames * javaFactory * javaReferenceAddress * javaDoc * * Delete obsolete object classes: * javaNamingReference * javaObject * + all the new ones that we're going to add * Add new and updated object classes: * javaObject * javaSerializedObject * javaMarshalledObject * javaNamingReference */ private void updateSchema(DirContext ctx, String[] attrIDs, String[] ocIDs) throws NamingException { updateAttributes((DirContext) ctx.getSchema("").lookup("AttributeDefinition"), attrIDs); updateObjectClasses((DirContext) ctx.getSchema("").lookup("ClassDefinition"), ocIDs); System.out.println( "Please use your directory server's administration tool to verify"); System.out.println( "the correctness of the schema."); } /* Add new and updated attr definitions */ protected void updateAttributes(DirContext attrRoot, String[] attrIDs) throws NamingException { /* Get rid of old attr IDs */ for (int i = 0; i < attrIDs.length; i++) { attrRoot.destroySubcontext(attrIDs[i]); } // javaSerializedData Attributes attrs = new BasicAttributes(true); // ignore case attrs.put("NUMERICOID", "1.3.6.1.4.1.42.2.27.4.1.8"); attrs.put("NAME", "javaSerializedData"); attrs.put("DESC", "Serialized form of a Java object"); if (netscape41bug) { // DS 4.1 doesn't like Octet String attrs.put("SYNTAX", "1.3.6.1.4.1.1466.115.121.1.5"); } else { attrs.put("SYNTAX", "1.3.6.1.4.1.1466.115.121.1.40"); } attrs.put("SINGLE-VALUE", "true"); attrRoot.createSubcontext("javaSerializedData", attrs); System.out.println("Created javaSerializedData attribute"); // javaCodebase attrs = new BasicAttributes(true); attrs.put("NUMERICOID", "1.3.6.1.4.1.42.2.27.4.1.7"); attrs.put("NAME", "javaCodebase"); attrs.put("DESC", "URL(s) specifying the location of class definition"); attrs.put("EQUALITY", "caseExactIA5Match"); attrs.put("SYNTAX", "1.3.6.1.4.1.1466.115.121.1.26"); attrRoot.createSubcontext("javaCodebase", attrs); System.out.println("Created javaCodebase attribute"); // javaClassName attrs = new BasicAttributes(true); attrs.put("NUMERICOID", "1.3.6.1.4.1.42.2.27.4.1.6"); attrs.put("NAME", "javaClassName"); attrs.put("DESC", "Fully qualified name of distinguished class or interface"); attrs.put("EQUALITY", "caseExactMatch"); attrs.put("SYNTAX", "1.3.6.1.4.1.1466.115.121.1.15"); attrs.put("SINGLE-VALUE", "true"); attrRoot.createSubcontext("javaClassName", attrs); System.out.println("Created javaClassName attribute"); // javaClassNames attrs = new BasicAttributes(true); attrs.put("NUMERICOID", "1.3.6.1.4.1.42.2.27.4.1.13"); attrs.put("NAME", "javaClassNames"); attrs.put("DESC", "Fully qualified Java class or interface name"); attrs.put("EQUALITY", "caseExactMatch"); attrs.put("SYNTAX", "1.3.6.1.4.1.1466.115.121.1.15"); attrRoot.createSubcontext("javaClassNames", attrs); System.out.println("Created javaClassNames attribute"); // javaFactory attrs = new BasicAttributes(true); attrs.put("NUMERICOID", "1.3.6.1.4.1.42.2.27.4.1.10"); attrs.put("NAME", "javaFactory"); attrs.put("DESC", "Fully qualified Java class name of a JNDI object factory"); attrs.put("EQUALITY", "caseExactMatch"); attrs.put("SYNTAX", "1.3.6.1.4.1.1466.115.121.1.15"); attrs.put("SINGLE-VALUE", "true"); attrRoot.createSubcontext("javaFactory", attrs); System.out.println("Created javaFactory attribute"); // javaReferenceAddress attrs = new BasicAttributes(true); attrs.put("NUMERICOID", "1.3.6.1.4.1.42.2.27.4.1.11"); attrs.put("NAME", "javaReferenceAddress"); attrs.put("DESC", "Addresses associated with a JNDI Reference"); attrs.put("EQUALITY", "caseExactMatch"); attrs.put("SYNTAX", "1.3.6.1.4.1.1466.115.121.1.15"); attrRoot.createSubcontext("javaReferenceAddress", attrs); System.out.println("Created javaReferenceAddress attribute"); // javaDoc attrs = new BasicAttributes(true); attrs.put("NUMERICOID", "1.3.6.1.4.1.42.2.27.4.1.12"); attrs.put("NAME", "javaDoc"); attrs.put("DESC", "The Java documentation for the class"); attrs.put("EQUALITY", "caseExactIA5Match"); attrs.put("SYNTAX", "1.3.6.1.4.1.1466.115.121.1.26"); attrRoot.createSubcontext("javaDoc", attrs); System.out.println("Created javaDoc attribute"); } // Object Classes protected void updateObjectClasses(DirContext ocRoot, String[] ocIDs) throws NamingException { /* Get rid of old OCs - reverse order */ for (int i = ocIDs.length - 1; i >= 0; i--) { ocRoot.destroySubcontext(ocIDs[i]); } // javaContainer Attributes attrs = new BasicAttributes(true); attrs.put("NUMERICOID", "1.3.6.1.4.1.42.2.27.4.2.1"); attrs.put("NAME", "javaContainer"); attrs.put("DESC", "Container for a Java object"); attrs.put("SUP", "top"); attrs.put("STRUCTURAL", "true"); Attribute jcMust = new BasicAttribute("MUST", "cn"); if (netscape41bug) { jcMust.add("objectClass"); } attrs.put(jcMust); ocRoot.createSubcontext("javaContainer", attrs); System.out.println("Created javaContainer object class"); // javaObject attrs = new BasicAttributes(true); attrs.put("NUMERICOID", "1.3.6.1.4.1.42.2.27.4.2.4"); attrs.put("NAME", "javaObject"); attrs.put("DESC", "Java object representation"); attrs.put("SUP", "top"); attrs.put("ABSTRACT", "true"); Attribute joMust = new BasicAttribute("MUST", "javaClassName"); if (netscape41bug) { joMust.add("objectClass"); } attrs.put(joMust); Attribute optional = new BasicAttribute("MAY", "javaCodebase"); optional.add("javaClassNames"); optional.add("javaDoc"); optional.add("description"); attrs.put(optional); ocRoot.createSubcontext("javaObject", attrs); System.out.println("Created javaObject object class"); // javaSerializedObject attrs = new BasicAttributes(true); attrs.put("NUMERICOID", "1.3.6.1.4.1.42.2.27.4.2.5"); attrs.put("NAME", "javaSerializedObject"); attrs.put("DESC", "Java serialized object"); attrs.put("SUP", "javaObject"); attrs.put("AUXILIARY", "true"); Attribute jsoMust = new BasicAttribute("MUST", "javaSerializedData"); if (netscape41bug) { jsoMust.add("objectClass"); } if (netscapebug) { // Netscape ignores 'SUP' so we must add explicitly attrs.put(optional); jsoMust.add("javaClassName"); } attrs.put(jsoMust); ocRoot.createSubcontext("javaSerializedObject", attrs); System.out.println("Created javaSerializedObject object class"); // javaMarshalledObject attrs = new BasicAttributes(true); attrs.put("NUMERICOID", "1.3.6.1.4.1.42.2.27.4.2.8"); attrs.put("NAME", "javaMarshalledObject"); attrs.put("DESC", "Java marshalled object"); attrs.put("SUP", "javaObject"); attrs.put("AUXILIARY", "true"); if (netscapebug) { // Netscape ignores 'SUP' so we must add explicitly attrs.put(optional); } attrs.put(jsoMust); // re-use the MUST from javaSerializedObject ocRoot.createSubcontext("javaMarshalledObject", attrs); System.out.println("Created javaMarshalledObject object class"); // javaNamingReference attrs = new BasicAttributes(true); attrs.put("NUMERICOID", "1.3.6.1.4.1.42.2.27.4.2.7"); attrs.put("NAME", "javaNamingReference"); attrs.put("DESC", "JNDI reference"); attrs.put("SUP", "javaObject"); attrs.put("AUXILIARY", "true"); if (netscapebug) { // Netscape ignores 'SUP' so we must add explicitly attrs.put("MUST", "javaClassName" ); } else { optional = new BasicAttribute("MAY"); } optional.add("javaReferenceAddress"); optional.add("javaFactory"); attrs.put(optional); ocRoot.createSubcontext("javaNamingReference", attrs); System.out.println("Created javaNamingReference object class"); } private int processCommandLine(String[] args) { String option; boolean schema = false; boolean list = false; for (int i = 0; i < args.length; i++) { option = args[i]; if (option.startsWith("-h")) { printUsage(null); } if (option.startsWith("-s")) { schema = true; netscapebug = option.equals("-sn"); netscape41bug = option.equals("-sn41"); } else if (option.startsWith("-l")) { list = true; } else if (option.startsWith("-a")) { auth = option.substring(2); } else if (option.startsWith("-n")) { dn = option.substring(2); } else if (option.startsWith("-p")) { passwd = option.substring(2); } else if (option.startsWith("-trace")) { traceLdap = true; } else { // invalid option printUsage("Invalid option"); } } if (!schema) { return LIST; } else { return UPDATE; } } protected void printUsage(String msg) { printUsageAux(msg, "Java"); } protected void printUsageAux(String msg, String key) { if (msg != null) { System.out.println(msg); } System.out.print("Usage: "); System.out.println("java [-Djava.naming.provider.url=] \\"); System.out.println(" Create" + key + "Schema [-h|-l|-s[n]] [-n] [-p] [-a]"); System.out.println(); System.out.println(" -h\t\tPrint the usage message"); System.out.println(" -l\t\tList the " + key + " schema in the directory"); System.out.println(" -s[n|n41]\t\tUpdate schema"); System.out.println( "\t\t(-sn means use workaround for Netscape 4.0 and earlier schema bugs)"); System.out.println( "\t\t(-sn41 means use workaround for Netscape 4.1 schema bugs)"); System.out.println(" -n\tUse as the distinguished name for authentication"); System.out.println(" -p\tUse as the password for authentication"); System.out.println(" -a\tUse as the authentication mechanism"); System.out.println("\t\t Default is 'simple' if dn specified; otherwise 'none'"); System.exit(-1); } }