summaryrefslogtreecommitdiffstats
path: root/ldap/admin/src/java
diff options
context:
space:
mode:
Diffstat (limited to 'ldap/admin/src/java')
-rw-r--r--ldap/admin/src/java/com/netscape/xmltools/DSML2LDIF.java234
-rw-r--r--ldap/admin/src/java/com/netscape/xmltools/DSMLReader.java47
-rw-r--r--ldap/admin/src/java/com/netscape/xmltools/DSMLSAXBuilder.java86
-rw-r--r--ldap/admin/src/java/com/netscape/xmltools/DSMLSAXHandler.java299
-rw-r--r--ldap/admin/src/java/com/netscape/xmltools/DSMLWriter.java315
-rw-r--r--ldap/admin/src/java/com/netscape/xmltools/GetOpt.java222
-rw-r--r--ldap/admin/src/java/com/netscape/xmltools/LDIF2DSML.java214
-rw-r--r--ldap/admin/src/java/com/netscape/xmltools/Makefile67
-rwxr-xr-xldap/admin/src/java/install17
-rwxr-xr-xldap/admin/src/java/mcc38
-rw-r--r--ldap/admin/src/java/mcc.bat45
11 files changed, 1584 insertions, 0 deletions
diff --git a/ldap/admin/src/java/com/netscape/xmltools/DSML2LDIF.java b/ldap/admin/src/java/com/netscape/xmltools/DSML2LDIF.java
new file mode 100644
index 00000000..42eb02fb
--- /dev/null
+++ b/ldap/admin/src/java/com/netscape/xmltools/DSML2LDIF.java
@@ -0,0 +1,234 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+
+package com.netscape.xmltools;
+
+import java.util.*;
+import java.io.*;
+import org.xml.sax.SAXException;
+import netscape.ldap.*;
+import netscape.ldap.util.*;
+
+/**
+ * Tool for converting DSML document to LDIF document
+ */
+public class DSML2LDIF {
+
+ /**
+ * Default no argument constructor.
+ */
+ public DSML2LDIF() {
+ }
+
+ /**
+ * Parse the command line parameters and setup the options parameters
+ */
+ static private GetOpt parseParameters( String[] args ) {
+
+ GetOpt options = new GetOpt("H?so:", args);
+
+ if (options.hasOption('H') || options.hasOption('?')) {
+ usage();
+ System.exit(0);
+ }
+
+ if (options.hasOption('v')) {
+ m_verbose = true;
+ }
+
+ if (options.hasOption('o')) {
+ m_outfile = options.getOptionParam('o');
+ if (m_outfile == null) {
+ System.err.println( "Missing argument for output filename" );
+ usage();
+ System.exit(0);
+ }
+
+ try {
+ m_pw = null;
+ m_pw = new PrintWriter( new FileOutputStream(m_outfile), true );
+ } catch (IOException e) {
+ System.err.println( "Can't open " + m_outfile );
+ System.err.println( e.toString() );
+ System.exit(1);
+ }
+ }
+
+ Vector extras = options.getParameters();
+ if (extras.size() == 1 ) {
+ m_infile = new String( (String)extras.get(0) );
+ } else {
+ if ( options.hasOption('s') ) {
+ // Use standard input for input of dsml file
+ m_infile = null;
+ } else {
+ usage();
+ System.exit(0);
+ }
+
+ }
+ return options;
+ }
+
+
+ /**
+ * Print out usage of the tool
+ */
+ static private void usage() {
+ System.err.println("Usage: java [-classpath CLASSPATH] DSML2LDIF infile.dsml -s [-o outfile.ldif]");
+ System.err.println("options");
+ System.err.println(" -s use standard input for input of dsml file" );
+ System.err.println(" -o outfile filename for the output LDIF file" );
+ System.err.println(" -H -? for usage" );
+ // System.err.println(" -v for verbose mode" );
+ }
+
+ static void processEntry( LDAPEntry entry ) {
+
+ long now = 0;
+ long later = 0;
+ long writeTime;
+ if ( m_doProfile ) {
+ now = System.currentTimeMillis();
+ }
+ try {
+ if (entry != null) {
+ m_ldifWriter.printEntry( entry );
+ // e = null;
+ }
+ if ( m_doProfile ) {
+ later = System.currentTimeMillis();
+ writeTime = later - now;
+ m_lapWriteTime += writeTime;
+ now = later;
+ }
+ } catch (Exception e) {
+ ;
+ }
+
+ if ( m_doProfile ) {
+ m_entryCount++;
+ if ( (m_entryCount % LAP_LENGTH) == 0 ) {
+ System.err.println( m_entryCount + " entries" );
+ System.err.println( " " + m_lapWriteTime +
+ " ms to write" );
+ m_lapWriteTime = 0;
+ System.err.println( " " + (now - m_lapTime) +
+ " ms total this lap" );
+ m_lapTime = now;
+ }
+ }
+ }
+
+ /**
+ * Temporary class to subclass from LDIFWriter
+ */
+ static class MyLDIFWriter extends netscape.ldap.util.LDIFWriter {
+ public MyLDIFWriter( PrintWriter pw ) {
+ super( pw );
+ }
+
+ /**
+ * Print prologue to entry
+ *
+ * @param dn the DN of the entry
+ */
+ protected void printEntryStart( String dn ) {
+ if ( dn == null ) {
+ dn = "";
+ } else {
+ byte[] b = null;
+ try {
+ b = dn.getBytes( "UTF8" );
+ } catch ( UnsupportedEncodingException ex ) {
+ }
+ if ( !LDIF.isPrintable(b) ) {
+ dn = getPrintableValue( b );
+ printString( "dn" + "::" + " " + dn );
+ return;
+ }
+ }
+ printString( "dn" + ":" + " " + dn );
+ }
+ }
+
+ /**
+ * Main routine for the tool.
+ */
+ public static void main(String[] args) {
+
+ m_verify = Boolean.getBoolean("verify");
+ parseParameters( args );
+
+ DSMLReader reader = null;
+
+ try {
+ if ( m_infile == null ) {
+ reader = new DSMLReader();
+ }
+ else {
+ reader = new DSMLReader( m_infile );
+ }
+ } catch (Exception e) {
+ System.err.println("Error encountered in input");
+ System.err.println(e.toString());
+ System.exit(1);
+ }
+
+ m_ldifWriter = new MyLDIFWriter( m_pw );
+
+ if (m_verify) {
+ if (m_pw != null) {
+ m_pw.close();
+ }
+ System.exit( 0 );
+ }
+
+ try {
+ if ( m_doProfile ) {
+ m_startTime = System.currentTimeMillis();
+ m_lapTime = m_startTime;
+ }
+ reader.parseDocument();
+ } catch( SAXException e ) {
+ System.err.println("Error encountered in parsing the DSML document");
+ System.err.println(e.getMessage());
+ e.printStackTrace();
+ System.exit(1);
+ } catch( Exception e ) {
+ e.printStackTrace();
+ } finally {
+ if (m_pw != null) {
+ m_pw.flush();
+ m_pw.close();
+ }
+ }
+
+ if ( m_doProfile ) {
+ System.err.println(
+ (System.currentTimeMillis() - m_startTime) / 1000 +
+ " seconds total for " + m_entryCount + " entries" );
+ }
+
+ System.exit( 0 );
+ }
+
+ static private PrintWriter m_pw = new PrintWriter(System.out, true);;
+ static private boolean m_verbose = false;
+ static private String m_outfile = null;
+ static private String m_infile = null;
+ static private LDIFWriter m_ldifWriter = null;
+ static private boolean m_verify = false;
+ static boolean m_doProfile = Boolean.getBoolean("com.netscape.xmltools.doProfile");
+ static long m_startTime;
+ static long m_toEntryTime = 0;
+ static long m_writeTime = 0;
+ static long m_lapTime;
+ static long m_lapToEntryTime = 0;
+ static long m_lapWriteTime = 0;
+ static long m_entryCount;
+ static final int LAP_LENGTH = 1000;
+}
diff --git a/ldap/admin/src/java/com/netscape/xmltools/DSMLReader.java b/ldap/admin/src/java/com/netscape/xmltools/DSMLReader.java
new file mode 100644
index 00000000..f6080433
--- /dev/null
+++ b/ldap/admin/src/java/com/netscape/xmltools/DSMLReader.java
@@ -0,0 +1,47 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+
+package com.netscape.xmltools;
+
+import java.io.*;
+import java.util.*;
+import org.xml.sax.*;
+import netscape.ldap.*;
+import netscape.ldap.util.*;
+
+/**
+ * Class for reading a DSML document according to the DSML 1.0 spec.
+ */
+public class DSMLReader {
+
+ /**
+ * Default no argument constructor
+ */
+ public DSMLReader() throws IOException {
+ m_ds = new DataInputStream( System.in );
+ }
+
+ /**
+ * Constructor for a dsml reader based on a file
+ *
+ * @param filename system-dependent filename
+ */
+ public DSMLReader( String filename ) throws IOException {
+ m_ds = new DataInputStream( new FileInputStream( filename ) );
+ }
+
+ /**
+ * Parses the input stream as a DSML document
+ *
+ * @throws SAXException on parsing errors
+ */
+ public void parseDocument() throws SAXException {
+ DSMLSAXBuilder builder = new DSMLSAXBuilder();
+ builder.parse( new InputSource( m_ds ) );
+ }
+
+ private DataInputStream m_ds = null;
+}
diff --git a/ldap/admin/src/java/com/netscape/xmltools/DSMLSAXBuilder.java b/ldap/admin/src/java/com/netscape/xmltools/DSMLSAXBuilder.java
new file mode 100644
index 00000000..4f85d2db
--- /dev/null
+++ b/ldap/admin/src/java/com/netscape/xmltools/DSMLSAXBuilder.java
@@ -0,0 +1,86 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+package com.netscape.xmltools;
+
+import javax.xml.parsers.*;
+import org.xml.sax.*;
+import org.xml.sax.helpers.*;
+
+/**
+ * A skeletal SAX driver, which doesn't create a document. Its content handler
+ * is a DSMLSAXHandler which creates and dispatches LDAP entries from a
+ * DSML document on the fly.
+ */
+public class DSMLSAXBuilder {
+
+ /**
+ * <p>
+ * Creates a new DSMLSAXBuilder with parser that will not validate.
+ * </p>
+ */
+ public DSMLSAXBuilder() {
+ }
+
+ /**
+ * <p>
+ * Creates a new DSMLSAXBuilder which will validate
+ * according to the given parameter.
+ * </p>
+ *
+ * @param validate <code>boolean</code> indicating if
+ * validation should occur.
+ */
+ public DSMLSAXBuilder(boolean validate) {
+ m_validate = validate;
+ }
+
+ /**
+ * Processes the supplied input source
+ *
+ * @param in <code>InputSource</code> to read from
+ * @throws SAXException when errors occur in parsing
+ */
+ public void parse(InputSource in) throws SAXException {
+ DSMLSAXHandler contentHandler = null;
+
+ try {
+ // Create the parser
+ SAXParserFactory fac = SAXParserFactory.newInstance();
+ fac.setValidating( m_validate );
+
+ XMLReader parser = fac.newSAXParser().getXMLReader();
+ parser.setFeature( "http://xml.org/sax/features/namespaces",
+ true );
+ parser.setFeature( "http://xml.org/sax/features/namespace-prefixes",
+ true );
+
+ // Create and configure the content handler
+ parser.setContentHandler( new DSMLSAXHandler() );
+
+ // Parse the document
+ parser.parse( in );
+ } catch (Exception e) {
+ if (e instanceof SAXParseException) {
+ SAXParseException p = (SAXParseException)e;
+ String systemId = p.getSystemId();
+ if (systemId != null) {
+ throw new SAXException("Error on line " +
+ p.getLineNumber() + " of document "
+ + systemId, e);
+ } else {
+ throw new SAXException("Error on line " +
+ p.getLineNumber(), e);
+ }
+ } else if (e instanceof SAXException) {
+ throw (SAXException)e;
+ } else {
+ throw new SAXException("Error in parsing", e);
+ }
+ }
+ }
+
+ private boolean m_validate = false;
+}
diff --git a/ldap/admin/src/java/com/netscape/xmltools/DSMLSAXHandler.java b/ldap/admin/src/java/com/netscape/xmltools/DSMLSAXHandler.java
new file mode 100644
index 00000000..73b067d7
--- /dev/null
+++ b/ldap/admin/src/java/com/netscape/xmltools/DSMLSAXHandler.java
@@ -0,0 +1,299 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+package com.netscape.xmltools;
+
+import java.util.*;
+
+import org.xml.sax.*;
+import org.xml.sax.helpers.*;
+
+import netscape.ldap.*;
+import netscape.ldap.util.*;
+
+/**
+ * Content handler which dispatches each LDAP entry composed from a dsml:entry
+ * element and its children. No document is built.
+ */
+public class DSMLSAXHandler extends DefaultHandler {
+ /** The DSML namespace */
+ private static final String DSML_NS = "http://www.dsml.org/DSML";
+
+ /** Element stack */
+ private Stack stack = new Stack();
+
+ /** Whether to ignore ignorable whitespace */
+ private boolean ignoringWhite = true;
+
+ /** Keeps track of name spaces */
+ private NamespaceSupport namespaces = new NamespaceSupport();
+
+ /**
+ * Creates a new <code>SAXHandler</code> that listens to SAX
+ * events and dispatches LDAP entries as they are found
+ */
+ public DSMLSAXHandler() {
+ }
+
+ /**
+ * Returns the value of a particular attribute from an array of
+ * attributes
+ *
+ * @param atts Array of attributes to process
+ * @param name The name of the attribute to return
+ * @return The value of the matching attribute, or null if not there
+ */
+ private String findAttribute( Attributes atts, String name ) {
+ for (int i = 0, len = atts.getLength(); i < len; i++) {
+ String attLocalName = atts.getLocalName(i);
+ String attQName = atts.getQName(i);
+ // Bypass any xmlns attributes which might appear, as we got
+ // them already in startPrefixMapping().
+
+ if (attQName.startsWith("xmlns:") || attQName.equals("xmlns")) {
+ continue;
+ }
+
+ if ( name.equalsIgnoreCase( attLocalName ) ) {
+ return atts.getValue(i);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Creates and returns an object corresponding to the element type
+ *
+ * @param prefix Namespace
+ * @param localName Element name without namespace
+ * @param atts Any attributes of the element
+ * @return An object corresponding to the element type
+ */
+ private Object getObjectForElement( String prefix,
+ String localName,
+ Attributes atts ) {
+ // Should not assume the "dsml" prefix. Any prefix can
+ // be mapped to the DSML namespace URI.
+ String uri = namespaces.getURI( prefix );
+ if ( (uri != null) && uri.equalsIgnoreCase( DSML_NS ) ) {
+ if ( "entry".equalsIgnoreCase( localName ) ) {
+ String dn = findAttribute( atts, "dn" );
+ if ( dn != null ) {
+ LDAPEntry entry = new LDAPEntry( dn );
+ return entry;
+ } else {
+ System.err.println( "No DN for entry" );
+ }
+ } else if ( "attr".equalsIgnoreCase( localName ) ) {
+ String name = findAttribute( atts, "name" );
+ if ( name != null ) {
+ LDAPAttribute attr = new LDAPAttribute( name );
+ return attr;
+ } else {
+ System.err.println( "No name for attribute" );
+ }
+ } else if ( "objectclass".equalsIgnoreCase( localName ) ) {
+ LDAPAttribute attr = new LDAPAttribute( "objectclass" );
+ return attr;
+ } else if ( "oc-value".equalsIgnoreCase( localName ) ) {
+ return new StringAttrValue();
+ } else if ( "value".equalsIgnoreCase( localName ) ) {
+ String enc = findAttribute( atts, "encoding" );
+ if ( "Base64".equalsIgnoreCase( enc ) ) {
+ return new BinaryAttrValue();
+ } else {
+ return new StringAttrValue();
+ }
+ }
+ }
+ return null;
+ }
+
+
+ /**
+ * This reports the occurrence of an actual element. It will include
+ * the element's attributes, with the exception of XML vocabulary
+ * specific attributes, such as
+ * <code>xmlns:[namespace prefix]</code> and
+ * <code>xsi:schemaLocation</code>.
+ *
+ * @param namespaceURI <code>String</code> namespace URI this element
+ * is associated with, or an empty
+ * <code>String</code>
+ * @param localName <code>String</code> name of element (with no
+ * namespace prefix, if one is present)
+ * @param qName <code>String</code> XML 1.0 version of element name:
+ * [namespace prefix]:[localName]
+ * @param atts <code>Attributes</code> list for this element
+ * @throws SAXException when things go wrong
+ */
+ public void startElement(String namespaceURI, String localName,
+ String qName, Attributes atts)
+ throws SAXException {
+ Object obj = null;
+
+ int split = qName.indexOf(":");
+ String prefix = (split > 0) ? qName.substring(0, split) : null;
+ if ( prefix != null ) {
+ // Save the prefix to URI mapping
+ if ((namespaceURI != null) && (!namespaceURI.equals(""))) {
+ namespaces.pushContext();
+ if ( namespaces.getPrefix( namespaceURI ) == null ) {
+ namespaces.declarePrefix( prefix, namespaceURI );
+ }
+ }
+ obj = getObjectForElement( prefix, localName, atts );
+ if ( obj instanceof LDAPEntry ) {
+ m_entry = (LDAPEntry)obj;
+ } else if ( obj instanceof LDAPAttribute ) {
+ m_attr = (LDAPAttribute)obj;
+ }
+ } else {
+ // This should never happen
+ System.err.println( "No namespace for [" + qName + "]" );
+ m_entry = null;
+ m_attr = null;
+ }
+
+ if ( obj != null ) {
+ // Put the DSML object on the stack
+ stack.push(obj);
+ }
+ }
+
+ /**
+ * This will report character data (within an element)
+ *
+ * @param ch <code>char[]</code> character array with character data
+ * @param start <code>int</code> index in array where data starts.
+ * @param length <code>int</code> length of data.
+ * @throws SAXException when things go wrong
+ */
+ public void characters(char[] ch, int start, int length)
+ throws SAXException {
+
+ // Ignore whitespace
+ boolean empty = true;
+ int maxOffset = start+length;
+ for( int i = start; i < maxOffset; i++ ) {
+ if ( (ch[i] != ' ') && (ch[i] != '\n') ) {
+ empty = false;
+ break;
+ }
+ }
+ if ( empty ) {
+ return;
+ }
+
+ m_sb.append( ch, start, length );
+ }
+
+ /**
+ * Captures ignorable whitespace as text. If
+ * setIgnoringElementContentWhitespace(true) has been called then this
+ * method does nothing.
+ *
+ * @param ch <code>[]</code> - char array of ignorable whitespace
+ * @param start <code>int</code> - starting position within array
+ * @param length <code>int</code> - length of whitespace after start
+ * @throws SAXException when things go wrong
+ */
+ public void ignorableWhitespace(char[] ch, int start, int length)
+ throws SAXException {
+ if (ignoringWhite) return;
+
+ characters(ch, start, length);
+ }
+
+ /**
+ * Takes any action appropriate for a particular object when it has
+ * been composed from an element and any children
+ *
+ * @param obj A DSML object
+ * @return The updated object
+ */
+ private Object processElementByObject( Object obj ) {
+ if ( obj instanceof LDAPEntry ) {
+ // An entry is ready to be processed
+ LDAPEntry entry = (LDAPEntry)obj;
+ // Rather than a static method, this should be an object that
+ // implements an interface and is provided with a setEntryProcessor
+ // method
+ DSML2LDIF.processEntry( entry );
+ } else if ( obj instanceof StringAttrValue ) {
+ if ( m_attr == null ) {
+ // This should never happen
+ System.err.println( "dsml:value or dsml:oc-value element " +
+ "not inside dsml:attr or " +
+ "dsml:objectclass" );
+ } else {
+ String val = new String( m_sb );
+ m_attr.addValue( val );
+ }
+ m_sb.setLength( 0 );
+ } else if ( obj instanceof BinaryAttrValue ) {
+ if ( m_attr == null ) {
+ System.err.println( "dsml:value element not inside dsml:attr" );
+ } else {
+ ByteBuf inBuf = new ByteBuf( new String( m_sb ) );
+ ByteBuf decodedBuf = new ByteBuf();
+ // Decode base 64 into binary
+ m_decoder.translate( inBuf, decodedBuf );
+ int nBytes = decodedBuf.length();
+ if ( nBytes > 0 ) {
+ String decodedValue = new String(decodedBuf.toBytes(), 0,
+ nBytes);
+ m_attr.addValue( decodedValue);
+ }
+ }
+ m_sb.setLength( 0 );
+ } else if ( obj instanceof LDAPAttribute ) {
+ if ( m_entry == null ) {
+ // This should never happen
+ System.err.println( "dsml:attr element not inside dsml:entry" );
+ } else {
+ m_entry.getAttributeSet().add( (LDAPAttribute)obj );
+ }
+ m_attr = null;
+ }
+ return obj;
+ }
+
+ /**
+ * Indicates the end of an element
+ * (<code>&lt;/[element name]&gt;</code>) is reached. Note that
+ * the parser does not distinguish between empty
+ * elements and non-empty elements, so this will occur uniformly.
+ *
+ * @param namespaceURI <code>String</code> URI of namespace this
+ * element is associated with
+ * @param localName <code>String</code> name of element without prefix
+ * @param qName <code>String</code> name of element in XML 1.0 form
+ * @throws SAXException when things go wrong
+ */
+ public void endElement(String namespaceURI, String localName,
+ String qName) throws SAXException {
+ if ( !stack.empty() ) {
+ Object obj = stack.pop();
+
+ processElementByObject( obj );
+ }
+
+ if ((namespaceURI != null) &&
+ (!namespaceURI.equals(""))) {
+ namespaces.popContext();
+ }
+ }
+
+ private LDAPEntry m_entry = null;
+ private LDAPAttribute m_attr = null;
+ private StringBuffer m_sb = new StringBuffer(1024);
+ static private MimeBase64Decoder m_decoder = new MimeBase64Decoder();
+
+ class StringAttrValue {
+ }
+ class BinaryAttrValue {
+ }
+}
diff --git a/ldap/admin/src/java/com/netscape/xmltools/DSMLWriter.java b/ldap/admin/src/java/com/netscape/xmltools/DSMLWriter.java
new file mode 100644
index 00000000..82ebc3d0
--- /dev/null
+++ b/ldap/admin/src/java/com/netscape/xmltools/DSMLWriter.java
@@ -0,0 +1,315 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+
+package com.netscape.xmltools;
+
+import java.util.*;
+import netscape.ldap.*;
+import java.io.*;
+import netscape.ldap.util.*;
+
+/**
+ * Class for outputting LDAP entries to a stream as DSML.
+ *
+ * @version 1.0
+ */
+public class DSMLWriter extends LDAPWriter {
+
+// static final long serialVersionUID = -2710382547996750924L;
+
+ /**
+ * Constructs a <CODE>DSMLWriter</CODE> object to output entries
+ * to a stream as DSML.
+ *
+ * @param pw output stream
+ */
+ public DSMLWriter( PrintWriter pw ) {
+ super( pw );
+ }
+
+ /**
+ * Prints the schema from an entry containing subschema
+ *
+ * entry entry containing schema definitions
+ */
+ public void printSchema( LDAPEntry entry ) {
+ LDAPSchema schema = new LDAPSchema( entry );
+ printString( " <dsml:directory-schema>" );
+ printObjectClassSchema( schema );
+ printAttributeSchema( schema );
+ printString( " </dsml:directory-schema>" );
+ }
+
+
+ /**
+ * Prints the object class schema from a schema object
+ *
+ * schema schema elements
+ */
+ protected void printObjectClassSchema( LDAPSchema schema ) {
+ Enumeration en = schema.getObjectClasses();
+ while( en.hasMoreElements() ) {
+ LDAPObjectClassSchema s = (LDAPObjectClassSchema)en.nextElement();
+ printString( " <dsml:class" );
+ printString( " id=\"" + s.getName() + "\"" );
+ printString( " oid=\"" + s.getID() + "\"" );
+ String[] superiors = s.getSuperiors();
+ if ( superiors != null ) {
+ for( int i = 0; i < superiors.length; i++ ) {
+ printString( " superior=\"#" + superiors[i] + "\"" );
+ }
+ }
+ String classType = "structural";
+ switch( s.getType() ) {
+ case LDAPObjectClassSchema.ABSTRACT: classType = "abstract";
+ break;
+ case LDAPObjectClassSchema.AUXILIARY: classType = "auxiliary";
+ break;
+ }
+ printString( " type=\"" + classType + "\">" );
+ if ( s.isObsolete() ) {
+ printString( " obsolete=true" );
+ }
+ printString( " <dsml:name>" + s.getName() + "</dsml:name>" );
+ printString( " <dsml:description>" + s.getDescription() +
+ "</dsml:description>" );
+ Enumeration attrs = s.getRequiredAttributes();
+ while( attrs.hasMoreElements() ) {
+ printString( " <dsml:attribute ref=\"#" +
+ (String)attrs.nextElement() +
+ "\" required=\"true\"/>" );
+ }
+ attrs = s.getOptionalAttributes();
+ while( attrs.hasMoreElements() ) {
+ printString( " <dsml:attribute ref=\"#" +
+ (String)attrs.nextElement() +
+ "\" required=\"false\"/>" );
+ }
+ printString( " </dsml:class>" );
+ }
+ }
+
+
+ /**
+ * Prints the attribute schema from a schema object
+ *
+ * schema schema elements
+ */
+ protected void printAttributeSchema( LDAPSchema schema ) {
+ Enumeration en = schema.getAttributes();
+ while( en.hasMoreElements() ) {
+ LDAPAttributeSchema s = (LDAPAttributeSchema)en.nextElement();
+ printString( " <dsml:attribute-type" );
+ printString( " id=\"" + s.getName() + "\"" );
+ printString( " oid=\"" + s.getID() + "\"" );
+ String superior = s.getSuperior();
+ if ( superior != null ) {
+ printString( " superior=\"#" + superior + "\"" );
+ }
+ if ( s.isSingleValued() ) {
+ printString( " single-value=true" );
+ }
+ if ( s.isObsolete() ) {
+ printString( " obsolete=true" );
+ }
+ if ( s.getQualifier( s.NO_USER_MODIFICATION ) != null ) {
+ printString( " user-modification=false" );
+ }
+ String[] vals = s.getQualifier( s.EQUALITY );
+ if ( (vals != null) && (vals.length > 0) ) {
+ printString( " equality=" + vals[0] );
+ }
+ vals = s.getQualifier( s.ORDERING );
+ if ( (vals != null) && (vals.length > 0) ) {
+ printString( " ordering=" + vals[0] );
+ }
+ vals = s.getQualifier( s.SUBSTR );
+ if ( (vals != null) && (vals.length > 0) ) {
+ printString( " substring=" + vals[0] );
+ }
+ printString( " <dsml:name>" + s.getName() + "</dsml:name>" );
+ printString( " <dsml:description>" + s.getDescription() +
+ "</dsml:description>" );
+ printString( " <dsml:syntax>" + s.getSyntaxString() +
+ "</dsml:syntax>" );
+ printString( " </dsml:attribute-type>" );
+ }
+ }
+
+
+ /**
+ * Print an attribute of an entry
+ *
+ * @param attr the attribute to format to the output stream
+ */
+ protected void printAttribute( LDAPAttribute attr ) {
+ String attrName = attr.getName();
+
+ // Object classes are treated differently in DSML. Also, they
+ // are always String-valued
+ if ( attrName.equalsIgnoreCase( "objectclass" ) ) {
+ Enumeration enumVals = attr.getStringValues();
+ if ( enumVals != null ) {
+ printString( " <dsml:objectclass>" );
+ while ( enumVals.hasMoreElements() ) {
+ String s = (String)enumVals.nextElement();
+ printString( " <dsml:oc-value>" + s +
+ "</dsml:oc-value>" );
+ }
+ printString( " </dsml:objectclass>" );
+ }
+ return;
+ }
+
+ printString( " <dsml:attr name=\"" + attrName + "\">" );
+
+ /* Loop on values for this attribute */
+ Enumeration enumVals = attr.getByteValues();
+
+ if ( enumVals != null ) {
+ while ( enumVals.hasMoreElements() ) {
+ byte[] b = (byte[])enumVals.nextElement();
+ String s;
+ if ( LDIF.isPrintable(b) ) {
+ try {
+ s = new String( b, "UTF8" );
+ } catch ( UnsupportedEncodingException e ) {
+ s = "";
+ }
+ printEscapedValue( " <dsml:value>", s,
+ "</dsml:value>" );
+ } else {
+ s = getPrintableValue( b );
+ if ( s.length() > 0 ) {
+ printString( " " +
+ "<dsml:value encoding=\"base64\">" );
+ printString( " " + s );
+ printString( " </dsml:value>" );
+ }
+ }
+ }
+ }
+ printString( " </dsml:attr>" );
+ }
+
+ /**
+ * Print prologue to entry
+ *
+ * @param dn the DN of the entry
+ */
+ protected void printEntryStart( String dn ) {
+
+/*
+ if ( dn == null ) {
+ dn = "";
+ } else {
+ byte[] b = null;
+ try {
+ b = dn.getBytes( "UTF8" );
+ } catch ( UnsupportedEncodingException ex ) {
+ }
+
+ if ( !LDIF.isPrintable(b) ) {
+ dn = getPrintableValue( b );
+ printString( " <dsml:entry dn=\"" + dn + "\" encoding=\"base64\">" );
+ return;
+ }
+
+ }
+ printString( " <dsml:entry dn=\"" + dn + "\">" );
+*/
+
+
+ if ( dn == null ) {
+ dn = "";
+ }
+ m_pw.print( " <dsml:entry dn=\"" );
+ printEscapedAttribute( dn );
+ m_pw.println( "\">" );
+ }
+
+ /**
+ * Print epilogue to entry
+ *
+ * @param dn the DN of the entry
+ */
+ protected void printEntryEnd( String dn ) {
+ printString( " </dsml:entry>" );
+ }
+
+ /**
+ * Print the element start, the value with escaping of special
+ * characters, and the element end
+ *
+ * @param prolog element start
+ * @param value value to be escaped
+ * @param epilog element end
+ */
+ protected void printEscapedValue( String prolog, String value,
+ String epilog ) {
+ m_pw.print( prolog );
+ int l = value.length();
+ char[] text = new char[l];
+ value.getChars( 0, l, text, 0 );
+ for ( int i = 0; i < l; i++ ) {
+ char c = text[i];
+ switch (c) {
+ case '<' :
+ m_pw.print( "&lt;" );
+ break;
+ case '&' :
+ m_pw.print( "&amp;" );
+ break;
+ default :
+ m_pw.print( c );
+ }
+ }
+ // m_pw.print( epilog);
+ // m_pw.print( '\n' );
+ m_pw.println( epilog );
+ }
+
+ /**
+ * Print the element attribute escaping of special
+ * characters
+ *
+ * @param attribute Attribute value to be escaped
+ */
+ protected void printEscapedAttribute( String attribute ) {
+
+ int l = attribute.length();
+ char[] text = new char[l];
+ attribute.getChars( 0, l, text, 0 );
+ for ( int i = 0; i < l; i++ ) {
+ char c = text[i];
+ switch (c) {
+ case '<' :
+ m_pw.print( "&lt;" );
+ break;
+ case '>':
+ m_pw.print( "&gt;" );
+ break;
+ case '&' :
+ m_pw.print( "&amp;" );
+ break;
+ case '"':
+ m_pw.print( "&quot;" );
+ break;
+ case '\'':
+ m_pw.print( "&apos;" );
+ break;
+ default :
+ m_pw.print( c );
+ }
+ }
+ }
+
+ protected void printString( String value ) {
+ // m_pw.print( value );
+ // m_pw.print( '\n' );
+ m_pw.println( value );
+ }
+}
diff --git a/ldap/admin/src/java/com/netscape/xmltools/GetOpt.java b/ldap/admin/src/java/com/netscape/xmltools/GetOpt.java
new file mode 100644
index 00000000..91d17e18
--- /dev/null
+++ b/ldap/admin/src/java/com/netscape/xmltools/GetOpt.java
@@ -0,0 +1,222 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+package com.netscape.xmltools;
+import java.util.*;
+
+/**
+ * This class is similar to the <CODE>getopt()</CODE> function in
+ * UNIX System V. You can use this class to parse command-line
+ * arguments.
+ * <P>
+ *
+ * When you create an object of this class, you specify a string
+ * containing the command-line options that you want to check for.
+ * The string should contain the letters of these options. If an
+ * option requires an argument (for example, "-h <hostname>"),
+ * you should add a colon after the letter in this string.
+ * <P>
+ *
+ * For example, in the following string, the <CODE>-h</CODE>,
+ * <CODE>-p</CODE>, <CODE>-D,</CODE>, and <CODE>-w</CODE> options
+ * all require arguments. The <CODE>-H</CODE> option does not
+ * require any arguments.
+ * <PRE>
+ * "h:p:D:w:H"
+ * </PRE>
+ *
+ * You can use the <CODE>hasOption</CODE> method to determine if
+ * an option has been specified and the <CODE>getOptionParam</CODE>
+ * method to get the argument specified after a particular option.
+ * <P>
+ *
+ * If an option not specified in the string is passed in as an
+ * argument, the <CODE>GetOpt</CODE> object prints out an error
+ * message. Note that the object does not throw an exception or
+ * exit the application if an invalid option is specified.
+ * <P>
+ *
+ * Note that you are still responsible for verifying that any
+ * required arguments have been specified.
+ * <P>
+ *
+ * The following example parses the command-line arguments for
+ * the hostname, port number, DN, and password to use when
+ * connecting and authenticating to an LDAP server.
+ * <PRE>
+ * import netscape.ldap.*;
+ * import netscape.ldap.controls.*;
+ * import netscape.ldap.util.*;
+ * import java.util.*;
+ *
+ * public class SearchDirectory {
+ *
+ * public static void main( String[] args )
+ * {
+ *
+ * String usage = "Usage: java SearchDirectory -h <host> -p <port> "
+ * + "[-D <bind dn>] [-w <password>]"
+ *
+ * int portnumber = LDAPv2.DEFAULT_PORT;
+ *
+ * // Check for these options. -H means to print out a usage message.
+ * GetOpt options = new GetOpt( "h:p:D:w:H", args );
+ *
+ * // Get the arguments specified for each option.
+ * String hostname = options.getOptionParam( 'h' );
+ * String port = options.getOptionParam( 'p' );
+ * String bindDN = options.getOptionParam( 'D' );
+ * String bindPW = options.getOptionParam( 'w' );
+ *
+ * // Check to see if the hostname (which is mandatory)
+ * // is not specified or if the user simply wants to
+ * // see the usage message (-H).
+ * if ( hostname == null || options.hasOption( 'H' ) ) {
+ * System.out.println( usage );
+ * System.exit( 1 );
+ * }
+ *
+ * // If a port number was specified, convert the port value
+ * // to an integer.
+ * if ( port != null ) {
+ * try {
+ * portnumber = java.lang.Integer.parseInt( port );
+ * } catch ( java.lang.Exception e ) {
+ * System.out.println( "Invalid port number: " + port );
+ * System.out.println( usage );
+ * System.exit( 1 );
+ * }
+ * }
+ *
+ * // Create a new connection.
+ * LDAPConnection ld = new LDAPConnection();
+ *
+ * try {
+ * // Connect and authenticate to server.
+ * ld.connect( 3, hostname, portnumber, bindDN, bindPW );
+ * ...
+ * } catch ( LDAPException e ) {
+ * System.out.println( "Error: " + e.toString() );
+ * }
+ * ...
+ * }
+ * }
+ * </PRE>
+ *
+ * @version 1.0
+ */
+public class GetOpt implements java.io.Serializable {
+ /**
+ * Internal variables
+ */
+ private int m_pos;
+ private String optarg;
+ private String m_control;
+ private Vector m_option;
+ private Vector m_ParameterList;
+ private Hashtable m_optionHashTable;
+ private Hashtable m_optionParamHashTable;
+ static final long serialVersionUID = -2570196909939660248L;
+
+ /**
+ * Constructs a <CODE>GetOpt</CODE> object.
+ * @param strControl a string specifying the letters of
+ * all available options. If an option requires an argument
+ * (for example, "-h <hostname>"), use a colon after the
+ * letter for that option (for example, "h:p:D:w:H").
+ * @param args an array of strings representing the list
+ * of arguments to parse (for example, the
+ * array passed into Main).
+ */
+ public GetOpt(String strControl, String args[]) {
+ m_option = new Vector();
+ m_control = strControl;
+ m_optionHashTable = new Hashtable();
+ m_optionParamHashTable = new Hashtable();
+ m_ParameterList = new Vector();
+
+ for (int i=0;i<args.length ;i++ ) {
+ String sOpt = args[i];
+ if (sOpt.length()>0) {
+ if (sOpt.charAt(0)=='-') {
+ if (sOpt.length()>1) {
+ int nIndex = m_control.indexOf(sOpt.charAt(1));
+ if (nIndex == (-1)) {
+ System.err.println("Invalid usage. No option -" +
+ sOpt.charAt(1));
+ } else {
+ char cOpt[]= new char[1];
+ cOpt[0]= sOpt.charAt(1);
+ String sName = new String(cOpt);
+ m_optionHashTable.put(sName,"1");
+ if ((m_control != null) && (m_control.length() > (nIndex+1))) {
+ if (m_control.charAt(nIndex+1)==':') {
+ i++;
+ if (i < args.length)
+ m_optionParamHashTable.put(sName,args[i]);
+ else
+ System.err.println("Missing argument for option "+
+ sOpt);
+ }
+ }
+ }
+ } else {
+ System.err.println("Invalid usage.");
+ }
+ } else {
+ // probably parameters
+ m_ParameterList.addElement(args[i]);
+ }
+ }
+ }
+ }
+
+ /**
+ * Determines if an option was specified. For example,
+ * <CODE>hasOption( 'H' )</CODE> checks if the -H option
+ * was specified.
+ * <P>
+ *
+ * @param c letter of the option to check
+ * @return <code>true</code> if the option was specified.
+ */
+ public boolean hasOption(char c) {
+ boolean fReturn = false;
+ char cOption[]=new char[1];
+ cOption[0]=c;
+ String s = new String(cOption);
+ if (m_optionHashTable.get(s)=="1") {
+ fReturn = true;
+ }
+ return(fReturn);
+ }
+
+ /**
+ * Gets the argument specified with an option.
+ * For example, <CODE>getOptionParameter( 'h' )</CODE>
+ * gets the value of the argument specified with
+ * the -h option (such as "localhost" in "-h localhost").
+ * <P>
+ *
+ * @param c the letter of the option to check
+ * @return the argument specified for this option.
+ */
+ public String getOptionParam(char c) {
+ char cOption[] = new char[1];
+ cOption[0]=c;
+ String s = new String(cOption);
+ String sReturn=(String)m_optionParamHashTable.get(s);
+ return(sReturn);
+ }
+
+ /**
+ * Gets a list of any additional parameters specified
+ * (not including the arguments for any options).
+ * @return a list of the additional parameters.
+ */
+ public Vector getParameters() {
+ return(m_ParameterList);
+ }
+}
diff --git a/ldap/admin/src/java/com/netscape/xmltools/LDIF2DSML.java b/ldap/admin/src/java/com/netscape/xmltools/LDIF2DSML.java
new file mode 100644
index 00000000..ae4ada4f
--- /dev/null
+++ b/ldap/admin/src/java/com/netscape/xmltools/LDIF2DSML.java
@@ -0,0 +1,214 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+
+package com.netscape.xmltools;
+
+import java.io.*;
+import java.util.*;
+import netscape.ldap.util.GetOpt;
+import netscape.ldap.util.*;
+import netscape.ldap.*;
+
+/**
+ * Tool for converting LDIF document to DSML document
+ */
+public class LDIF2DSML {
+
+ /**
+ * Default no argument constructor.
+ */
+ public LDIF2DSML() {
+ }
+
+ /**
+ * Converter taking a filename argument for the input LDIF file
+ *
+ * @param filename system-dependent file name for the input LDIF file
+ */
+ public LDIF2DSML( String filename ) throws IOException {
+
+ DataInputStream ds = null;
+
+ if( filename == null || filename.length() == 0 ) {
+ ds = new DataInputStream( System.in );
+ }
+ else {
+ ds = new DataInputStream( new FileInputStream( filename) );
+ }
+
+ // set up the ldif parser with the input stream
+ //
+ m_ldifReader = new LDIF( ds );
+ }
+
+ /**
+ * Converts an LDIF record to an LDAPEntry. Only convert if the content
+ * of the LDIF record is of the type LDIFContent.ATTRIBUTE_CONTENT.
+ *
+ * @param rec An LDIFRecord to be converted
+ * @returns The converted LDAPEntry. null is returned for any ldif record not
+ * being recognized with attribute content
+ */
+ public LDAPEntry toLDAPEntry( LDIFRecord rec ) {
+
+ String dn = rec.getDN();
+ LDIFContent content = rec.getContent();
+
+ if (content.getType() == LDIFContent.ATTRIBUTE_CONTENT) {
+ LDIFAttributeContent entry = (LDIFAttributeContent)content;
+ /* LDAPAttribute attrs[] = entry.getAttributes();
+ for( int i = 0; i < attrs.length; i++ ) {
+ System.err.println( attrs[i].toString() );
+ }*/
+ return new LDAPEntry( dn, new LDAPAttributeSet( entry.getAttributes()) );
+ }
+ return null;
+ }
+
+ /**
+ * Conversion from ldif to dsml document.
+ */
+ public void convert() {
+ DSMLWriter writer = new DSMLWriter( m_pw );
+ int recCount = 0;
+ int rejectCount = 0;
+
+ try {
+
+ m_pw.println( "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>");
+ m_pw.println( "<dsml:dsml xmlns:dsml=\"http://www.dsml.org/DSML\">");
+ m_pw.println( " <dsml:directory-entries>" );
+
+ for( LDIFRecord rec = m_ldifReader.nextRecord();
+ rec != null; rec = m_ldifReader.nextRecord(), recCount++ ) {
+ LDAPEntry entry = toLDAPEntry( rec );
+ if (entry != null) {
+ writer.printEntry( entry );
+ entry = null;
+ }
+ }
+
+ m_pw.println( " </dsml:directory-entries>" );
+ m_pw.println( "</dsml:dsml>" );
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ m_pw.flush();
+ m_pw.close();
+ }
+ }
+
+ /**
+ * Parse the command line parameters and setup the options parameters
+ */
+ static private GetOpt parseParameters( String[] args ) {
+
+ GetOpt options = new GetOpt("H?so:", args);
+
+ if (options.hasOption('H') || options.hasOption('?')) {
+ usage();
+ System.exit(0);
+ }
+
+ if (options.hasOption('v')) {
+ m_verbose = true;
+ }
+
+ if (options.hasOption('o')) {
+ m_outfile = options.getOptionParam('o');
+ if (m_outfile == null) {
+ System.err.println( "Missing argument for output filename" );
+ usage();
+ System.exit(0);
+ }
+
+ try {
+ /*
+ m_pw = null;
+ m_pw = new PrintWriter( new FileOutputStream(m_outfile), true );
+ */
+
+ m_pw = null;
+ // always write DSML document out in UTF8 encoding
+ //
+ OutputStreamWriter os = new OutputStreamWriter( new FileOutputStream(m_outfile), "UTF8" );
+ m_pw = new PrintWriter( os, true );
+ } catch (IOException e) {
+ System.err.println( "Can't open " + m_outfile );
+ System.err.println( e.toString() );
+ System.exit(1);
+ }
+ }
+
+ Vector extras = options.getParameters();
+ if (extras.size() == 1 ) {
+ m_infile = new String( (String)extras.get(0) );
+ } else {
+ if ( options.hasOption('s') ) {
+ // System.err.println( "Use standard input for input of ldif file" );
+ m_infile = null;
+ } else {
+ usage();
+ System.exit(0);
+ }
+ }
+ return options;
+ }
+
+ /**
+ * Print out usage of the tool
+ */
+ static private void usage() {
+ System.err.println("Usage: java [-classpath $CLASSPATH] LDIF2DSML infile.ldif [-s] [-o outfile.dsml]");
+ System.err.println("options");
+ System.err.println(" -s use standard input for input of ldif file" );
+ System.err.println(" -o outfile filename for the output DSML file" );
+ System.err.println(" -H -? for usage" );
+ // System.err.println(" -v for verbose mode" );
+
+ }
+
+ /**
+ * Main routine for the tool.
+ */
+ static public void main(String[] args){
+
+ m_verify = Boolean.getBoolean("verify");
+
+ parseParameters( args);
+
+ LDIF2DSML converter = null;
+
+ try {
+ if (m_infile== null) {
+ converter = new LDIF2DSML( null );
+ }
+ else {
+ converter = new LDIF2DSML( m_infile );
+ }
+ } catch( IOException e ) {
+ System.err.println( "Error encountered in input" );
+ System.err.println( e.toString() );
+ System.exit( 1 );
+ }
+
+ if (m_verify) {
+ System.exit( 0 );
+ }
+
+ converter.convert();
+ System.exit( 0 );
+
+ }
+
+ static private PrintWriter m_pw = new PrintWriter(System.out, true);
+ static private boolean m_verbose = false;
+ static private String m_outfile = null;
+ static private String m_infile = null;
+ static private LDIF m_ldifReader = null;
+ static private boolean m_verify = false;
+}
diff --git a/ldap/admin/src/java/com/netscape/xmltools/Makefile b/ldap/admin/src/java/com/netscape/xmltools/Makefile
new file mode 100644
index 00000000..61b4b535
--- /dev/null
+++ b/ldap/admin/src/java/com/netscape/xmltools/Makefile
@@ -0,0 +1,67 @@
+#
+# BEGIN COPYRIGHT BLOCK
+# Copyright 2001 Sun Microsystems, Inc.
+# Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+# All rights reserved.
+# END COPYRIGHT BLOCK
+#
+# Name:
+# Platform: gmake
+# --------------------------------------------------------------------------
+override BUILD_MODULE=HTTP_ADMIN
+
+NOSTDCLEAN=true
+NO_BUILD_NUM=true
+COMPONENT_DEPS=true
+
+MCOM_ROOT=../../../../../../../..
+
+include ../../../../../../../nsconfig.mk
+include ../../../../../../../ldap/javarules.mk
+CLASS_DIR=$(JAVA_DEST_DIR)/xmltools
+PACKAGE_DIR=$(ABS_ROOT)/dist/$(BUILD_DEBUG)
+_PACKAGE_DIR=$(MCOM_ROOT)/dist/$(BUILD_DEBUG)
+DEST_DIR=$(CLASS_DIR)/com/netscape/xmltools
+JARS_DIR=lib
+TOOLS_JARS=$(JARS_DIR)/crimson.jar$(PATH_SEP)$(JARS_DIR)/ldapjdk.jar
+TOOLS_JAR_FILE=xmltools.jar
+#
+# programs list
+#
+source = \
+ $(DEST_DIR)/DSML2LDIF.class \
+ $(DEST_DIR)/LDIF2DSML.class \
+ $(DEST_DIR)/DSMLReader.class \
+ $(DEST_DIR)/DSMLWriter.class \
+ $(DEST_DIR)/GetOpt.class \
+ $(DEST_DIR)/DSMLSAXBuilder.class \
+ $(DEST_DIR)/DSMLSAXHandler.class
+
+
+package: all $(_PACKAGE_DIR)
+# when zip finds nothing to do, it exits with code 12 which is not an error
+# so we turn that 12 into a 0 which means success so make will continue
+ cd $(CLASS_DIR); zip -r -u $(PACKAGE_DIR)/$(TOOLS_JAR_FILE) com || if [ $$? -eq 12 ]; then exit 0 ; else exit $$? ; fi
+
+all: $(DEST_DIR) $(CRIMSONJAR_DEP) $(LDAPJDK_DEP) $(source)
+
+clean:
+ rm -f $(DEST_DIR)/*.class; rm -f $(PACKAGE_DIR)/$(TOOLS_JAR_FILE)
+
+fresh: $(clean) $(all)
+
+
+jdoc: ./doc
+ $(JAVADOC) -classpath "$(CLASSPATH)$(PATH_SEP)$(CLASS_DIR)$(PATH_SEP)$(CRIMSONJAR_FILE)" -d ./doc com.netscape.xmltools
+
+jdoc.clean :
+ rm -rf ./doc
+
+$(_PACKAGE_DIR):
+ mkdir -p $(_PACKAGE_DIR)
+
+$(DEST_DIR)/%.class : %.java
+ $(JAVAC) -deprecation -classpath "$(CLASSPATH)$(PATH_SEP)$(CLASS_DIR)$(PATH_SEP)$(CRIMSONJAR_FILE)" -d $(CLASS_DIR) $<
+
+$(DEST_DIR) ./doc:
+ mkdir -p $@
diff --git a/ldap/admin/src/java/install b/ldap/admin/src/java/install
new file mode 100755
index 00000000..e307f782
--- /dev/null
+++ b/ldap/admin/src/java/install
@@ -0,0 +1,17 @@
+#!/bin/sh
+#
+# BEGIN COPYRIGHT BLOCK
+# Copyright 2001 Sun Microsystems, Inc.
+# Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+# All rights reserved.
+# END COPYRIGHT BLOCK
+#
+if [ $# -lt 1 ]
+then
+ echo >&2 "Usage: $0 targetDirectory"
+ exit 2
+fi
+mkdir -p $1
+mkdir -p $1/jars
+cp -p `dirname $0`/mcc $1
+cp -p -r `dirname $0`/jars/* $1/jars
diff --git a/ldap/admin/src/java/mcc b/ldap/admin/src/java/mcc
new file mode 100755
index 00000000..080ffb98
--- /dev/null
+++ b/ldap/admin/src/java/mcc
@@ -0,0 +1,38 @@
+#!/bin/sh
+#
+# BEGIN COPYRIGHT BLOCK
+# Copyright 2001 Sun Microsystems, Inc.
+# Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+# All rights reserved.
+# END COPYRIGHT BLOCK
+#
+if [ $# -lt 2 ]
+then
+ echo >&2 "Usage: $0 host port [[user] [password]"
+ exit 2
+fi
+MCC_HOST=$1
+MCC_PORT=$2
+# Has to be in the jars subdirectory
+JARDIR=./jars
+#
+DS=${JARDIR}/ds40.jar
+ADMIN=${JARDIR}/admserv.jar
+KINGPIN=${JARDIR}/kingpin.jar
+SWING=${JARDIR}/swingall.jar
+LF=${JARDIR}/nmclf.jar
+LAYOUT=${JARDIR}/layout.jar
+LDAP=${JARDIR}/ldapjdk.jar
+BASE=o=netscaperoot
+CLASSPATH=${DS}:${KINGPIN}:${ADMIN}:${SWING}:${LAYOUT}:${LF}:${LDAP};export CLASSPATH
+cd `dirname $0`
+if [ $# -gt 3 ]
+then
+ java com.netscape.management.client.console.Console -d ${MCC_HOST} -p ${MCC_PORT} -u "$3" -w "$4" -b ${BASE}
+elif [ $# -gt 2 ]
+then
+ java com.netscape.management.client.console.Console -d ${MCC_HOST} -p ${MCC_PORT} -u "$3" -b ${BASE}
+else
+ java com.netscape.management.client.console.Console -d ${MCC_HOST} -p ${MCC_PORT} -b ${BASE}
+fi
+
diff --git a/ldap/admin/src/java/mcc.bat b/ldap/admin/src/java/mcc.bat
new file mode 100644
index 00000000..4caccf18
--- /dev/null
+++ b/ldap/admin/src/java/mcc.bat
@@ -0,0 +1,45 @@
+@rem //
+@rem // BEGIN COPYRIGHT BLOCK
+@rem // Copyright 2001 Sun Microsystems, Inc.
+@rem // Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+@rem // All rights reserved.
+@rem // END COPYRIGHT BLOCK
+@rem //
+@echo off
+setlocal
+set MCC_HOST=%1
+set MCC_PORT=%2
+if "%MCC_HOST%x"=="x" goto usage
+if "%MCC_PORT%x"=="x" goto usage
+rem
+set MCC_USER=
+if %3x==x goto nouser
+set MCC_USER=-u %3
+echo MCC_USER = %MCC_USER%
+:nouser
+set MCC_PASSWORD=
+if %4x==x goto nopass
+set MCC_PASSWORD=-w %4
+:nopass
+rem
+set JARDIR=./jars
+set JDK=%JARDIR%/classes.zip
+set DS=%JARDIR%/ds40.jar
+set ADMIN=%JARDIR%/admserv.jar
+set KINGPIN=%JARDIR%/kingpin.jar
+set SWING=%JARDIR%/swingall.jar
+set LF=%JARDIR%/nmclf.jar
+set LAYOUT=%JARDIR%/layout.jar
+set LDAP=%JARDIR%/ldapjdk.jar
+set BASE=o=netscaperoot
+set CLASSPATH=%DS%;%KINGPIN%;%ADMIN%;%SWING%;%LAYOUT%;%LF%;%LDAP%
+rem echo java com.netscape.management.client.console.Console -d %MCC_HOST% -p %MCC_PORT% %MCC_USER% %MCC_PASSWORD% -b %BASE%
+java com.netscape.management.client.console.Console -d %MCC_HOST% -p %MCC_PORT% %MCC_USER% %MCC_PASSWORD% -b %BASE%
+goto end
+
+:usage
+echo Usage: mcc HOST PORT [[user] [password]]
+
+:end
+endlocal
+