Index: java/build.xml
===================================================================
--- java/build.xml	(revision 56ec930e01e71105b85ee15e8f8d3314a562a616)
+++ java/build.xml	(revision e36ea1d2124f37b1cb324dbc84671ca0f5efa7e5)
@@ -5,4 +5,5 @@
   <property name="classes.dir" value="${build.dir}/classes"/>
   <property name="jar.dir" value="${build.dir}/jar"/>
+  <property name="doc.dir" value="./doc"/>
   <property name="main.class" value="GraphTest"/>
   <property name="dump.class" value="Dumper"/>
@@ -10,4 +11,5 @@
   <target name="clean">
     <delete dir="${build.dir}"/>
+    <delete dir="${doc.dir}"/>
     <delete>
       <fileset dir="${basedir}" includes="**/*.der"/>
@@ -38,4 +40,11 @@
   </target>
 
+  <target name="doc" description="Generate API documentation">
+    <mkdir dir="${doc.dir}"/>
+    <javadoc sourcepath="${src.dir}" destdir="${doc.dir}"
+      classpathref="compile.classpath" access="public"
+      noqualifier="java.lang:java.io:java.util:java.security:java.security.cert"/>
+  </target>
+
   <target name="run" depends="compile" description="run visualizer">
     <java classname="${main.class}" fork="true" >
Index: java/net/deterlab/abac/Context.java
===================================================================
--- java/net/deterlab/abac/Context.java	(revision 56ec930e01e71105b85ee15e8f8d3314a562a616)
+++ java/net/deterlab/abac/Context.java	(revision e36ea1d2124f37b1cb324dbc84671ca0f5efa7e5)
@@ -1,12 +1,7 @@
 package net.deterlab.abac;
 
-import org.apache.commons.collections15.*;
-import org.apache.commons.collections15.functors.*;
-
 import edu.uci.ics.jung.graph.*;
-import edu.uci.ics.jung.graph.event.*;
 import edu.uci.ics.jung.graph.util.*;
 
-import java.awt.geom.Point2D;
 import java.io.*;
 import java.util.*;
@@ -18,35 +13,65 @@
 import org.bouncycastle.asn1.x509.*;
 import org.bouncycastle.x509.*;
-import org.bouncycastle.x509.util.*;
 import org.bouncycastle.openssl.*;
 
 /**
  * Represents a global graph of credentials in the form of principals and
- * attributes.
+ * attributes.  Contains the identities and credentials that can be used in a
+ * proof.
+ * @author <a href="http://abac.deterlab.net">ISI ABAC team</a>
+ * @version 1.3
  */
 public class Context {
-    static final int ABAC_CERT_SUCCESS = 0;
-    static final int ABAC_CERT_INVALID = -1;
-    static final int ABAC_CERT_BAD_SIG = -2;
-    static final int ABAC_CERT_MISSING_ISSUER = -3;
-
+    /** Certificate imported successfully */
+    public static final int ABAC_CERT_SUCCESS = 0;
+    /** Certificate import failed, invalid certificate */
+    public static final int ABAC_CERT_INVALID = -1;
+    /** Certificate import failed, signature filed */
+    public static final int ABAC_CERT_BAD_SIG = -2;
+    /** Certificate import failed, unknown issuer */
+    public static final int ABAC_CERT_MISSING_ISSUER = -3;
+
+    /** Internal graph representation */
     protected Graph<Role,Credential> g;
+    /** Set of edges in the graph that were added by the logic.  */
     protected Set<Credential> derived_edges;
+    /** Internal persistent query object */
     protected Query pq;
+    /** True when the graph has been changed since the last set of implied
+     * edges were calculated. */
     protected boolean dirty;
+    /** Set of identities known to this Context. */
     protected Set<Identity> identities;
 
+    /** Translation from issuer CN to issuer pubkey identifier */
     protected Map<String, String> nicknames;
+    /** Translation from issuer pubkey identifier to issuer CN */
     protected Map<String, String> keys;
 
+    /**
+     * The result of a query on this context.  The credentials form a partial
+     * or total proof, and success indicates whether the proof succeeded.
+     * @author <a href="http://abac.deterlab.net">ISI ABAC team</a>
+     * @version 1.3
+     */
     public class QueryResult {
+	/** Credentials returned */
 	protected Collection<Credential> creds;
+	/** True if the proof succeeded. */
 	protected boolean success;
 
-	public QueryResult(Collection<Credential> c, boolean s) {
+	/**
+	 * Construct a result from components.
+	 * @param c the collection of credentials in the proof
+	 * @param s a boolean, true if the query succeeded.
+	 */
+	QueryResult(Collection<Credential> c, boolean s) {
 	    creds = c;
 	    success = s;
 	}
 
+	/**
+	 * Empty constructor
+	 */
 	public QueryResult() { 
 	    creds = new TreeSet<Credential>();
@@ -54,9 +79,20 @@
 	}
 
+	/**
+	 * Return the credentials in the proof.
+	 * @return the collection of credentials
+	 */
 	public Collection<Credential> getCredentials() { return creds; }
+	/**
+	 * Return the success in the proof.
+	 * @return the boolean, true on success
+	 */
 	public boolean getSuccess() { return success; }
     }
 
 
+    /**
+     * Create an empty Context.
+     */
     public Context() {
         /* create the graph */
@@ -71,4 +107,8 @@
     }
 
+    /**
+     * Create a context from another context.
+     * @param c the Context to copy
+     */
     public Context(Context c) {
 	this();
@@ -80,6 +120,24 @@
     }
 
+    /**
+     * Load an Identity from a file.
+     * @param fn a String containing the file name.
+     * @return one of the static int return codes.
+     */
     public int loadIDFile(String fn) { return loadIDChunk(new File(fn)); }
+    /**
+     * Load an Identity from a file.
+     * @param fn a File containing the file name.
+     * @return one of the static int return codes.
+     */
     public int loadIDFile(File fn) { return loadIDChunk(fn); }
+    /**
+     * Load an Identity from an object.  Supported objects are an Identity, a
+     * String, a File, or a java.security.cert.X509Certificate.  A string
+     * creates an new identity, and the others are derived from the contents of
+     * the data or file.
+     * @param c an object convertable to an identity as above.
+     * @return one of the static int return codes.
+     */
     public int loadIDChunk(Object c) {
 	try {
@@ -104,10 +162,28 @@
     }
 
+    /**
+     * Load an attribute certificate from a file.
+     * @param fn a String containing the file name.
+     * @return one of the static int return codes.
+     */
     public int loadAttributeFile(String fn) { 
 	return loadAttributeChunk(new File(fn));
     }
 
+    /**
+     * Load an attribute certificate from a file.
+     * @param fn a File containing the file name.
+     * @return one of the static int return codes.
+     */
     public int loadAttributeFile(File fn) { return loadAttributeChunk(fn); }
 
+    /**
+     * Load an Identity from an object.  Supported objects are a Credential, a
+     * String, a File, or an org.bouncycastle.x509.X509V2AttributeCertificate.
+     * A string creates an new Credential, and the others are derived from the
+     * contents of the data or file.
+     * @param c an object convertable to a Credential as above.
+     * @return one of the static int return codes.
+     */
     public int loadAttributeChunk(Object c) {
 	try {
@@ -133,4 +209,11 @@
     }
 
+    /**
+     * Determine if prinicpal possesses role in the current context.  If so,
+     * return a proof of that, otherwise return a partial proof of it.
+     * @param role a String encoding the role to check for.
+     * @param principal a String with the principal ID in it.
+     * @return a Context.QueryResult containing the result.
+     */
     public QueryResult query(String role, String principal) {
 	derive_implied_edges();
@@ -143,5 +226,6 @@
 
     /**
-     * Returns a collection of the credentials in the graph.
+     * Return a collection of the credentials in the graph.s
+     * @return a collection of the credentials in the graph.
      */
     public Collection<Credential> credentials() {
@@ -156,5 +240,17 @@
     }
 
+    /**
+     * Returns true if the given Identity is known in this Context.  A jabac
+     * extension.
+     * @param i the Identity to look for
+     * @return a boolean, true if the Identity is known.
+     */
     public boolean knowsIdentity(Identity i) { return identities.contains(i); }
+    /**
+     * Returns true if an Identity with the given string representation is
+     * known in this Context.  A jabac extension.
+     * @param k the string representing the Identity to look for 
+     * @return a boolean, true if the Identity is known.
+     */
     public boolean knowsKeyID(String k) {
 	boolean known = false;
@@ -167,4 +263,5 @@
     /**
      * Add a credential to the graph.
+     * @param cred the Credential to add
      */
     protected void add_credential(Credential cred) {
@@ -191,4 +288,5 @@
     /**
      * Remove a credential from the graph.
+     * @param cred the Credential to remove
      */
     protected void remove_credential(Credential cred) {
@@ -200,4 +298,5 @@
     /**
      * Add a role w/o an edge
+     * @param v the Role to add
      */
     protected void add_vertex(Role v) {
@@ -208,4 +307,8 @@
     }
 
+    /**
+     * Remove a role and connected edges.
+     * @param v the Role to remove
+     */
     protected void remove_vertex(Role v) {
 	if (g.containsVertex(v)) {
@@ -239,4 +342,5 @@
      * Single iteration of deriving implied edges. Returns the number of new
      * links added.
+     * @return the number of new links added.
      */
     protected int derive_links_iter() {
@@ -301,4 +405,5 @@
      * Add a derived edge in the graph. Returns true only if the edge does not
      * exist.
+     * @return a boolean, true if an edge has been added
      */
     protected boolean add_derived_edge(Role head, Role tail) {
@@ -331,4 +436,5 @@
      * common name they are disambiguated.  Only one entry for keyid is
      * allowed.
+     * @param i the Identity to add
      */
     protected void addIdentity(Identity id) { 
@@ -352,4 +458,7 @@
      * strings.  If any of the smallest strings is in the map, replace it with
      * the value.
+     * @param is the string to manipulate
+     * @param m the Map containing translations
+     * @return the string after modification
      */
     protected String replace(String is, Map<String, String> m) {
@@ -369,6 +478,19 @@
     }
 
-    public String expandKeyID(String s) { return replace(s, nicknames); }
-    public String expandNickname(String s) { return replace(s, keys); }
+    /**
+     * Expand menmonic names in a Role string, e.g. the CN of the issuer
+     * certificate, into the full key ID.  Used internally by Roles to provide
+     * transparent use of mnemonics
+     * @param s the string to expand
+     * @return the String after expansion.
+     */
+    String expandKeyID(String s) { return replace(s, nicknames); }
+    /**
+     * Convert key IDs to  menmonic names in a Role string.  The inverse of
+     * expandKeyID.
+     * @param s the string to expand
+     * @return the String after expansion.
+     */
+    String expandNickname(String s) { return replace(s, keys); }
 
     /**
@@ -378,4 +500,9 @@
      * PEM files are put in there.  If errors is not null, errors reading files
      * are added indexed by filename.
+     * @param zf the File to read
+     * @param keys a Collection into which to insert unmatched keys
+     * @param errors a Map from entry name to generated exception
+     * @throws IOException if the file is unreadable.  Per entry exceptions are
+     *			   returned in the errors parameter.
      */
     public void readZipFile(File zf, Collection<KeyPair> keys, 
@@ -444,13 +571,32 @@
 	}
     }
-
+    /**
+     * Equivalent to readZipFile(d, null, null).
+     * @param d the File to read
+     * @throws IOException if the file is unreadable. To see per-entry
+     *			    exceptions use a signature with the errors parameter
+     */
     public void readZipFile(File d) 
 	    throws IOException {
 	readZipFile(d, null, null);
     }
+    /**
+     * Equivalent to readZipFile(d, null, errors).
+     * @param d the File to read
+     * @param errors a Map from entry name to generated exception
+     * @throws IOException if the file is unreadable.  Per entry exceptions are
+     *			   returned in the errors parameter.
+     */
     public void readZipFile(File d, 
 	    Map<String, Exception> errors) throws IOException {
 	readZipFile(d, null, errors);
     }
+    /**
+     * Equivalent to readZipFile(d, keys, null).
+     * @param d the File to read
+     * @param keys a Collection into which to insert unmatched keys
+     * @throws IOException if the file is unreadable. To see per-entry
+     *			    exceptions use a signature with the errors parameter
+     */
     public void readZipFile(File d, 
 	    Collection<KeyPair> keys) throws IOException {
@@ -458,4 +604,13 @@
     }
 
+    /**
+     * Read a PEM file that contains an X509 Certificate, a key pair, or both.
+     * If a cert is present it is converted into an Identity.  A key pair is
+     * returned as a java.security.KeyPair and both are returned as an Identity
+     * with an associated key pair.
+     * @param r a PEMReader from which to read
+     * @return an object encoding the contents (as above)
+     * @throws IOException for an unreadable or badly formated input
+     */
     protected Object readPEM(PEMReader r) throws IOException {
 	Identity i = null;
@@ -501,4 +656,9 @@
      * PEM files are put in there.  If errors is not null, errors reading files
      * are added indexed by filename.
+     * @param d the File to read.  If it is a directory its contents are read
+     * @param keys a Collection into which to insert unmatched keys
+     * @param errors a Map from entry name to generated exception
+     * @throws IOException if the file is unreadable.  Per file exceptions are
+     *			   returned in the errors parameter.
      */
     public void readDirectory(File d, Collection<KeyPair> keys, 
@@ -568,15 +728,44 @@
 	}
     }
-
+    /**
+     * Equivalent to readDirectory(d, null, null).
+     * @param d the File to read.  If it is a directory its contents are read
+     * @throws IOException if the file is unreadable.  To see per-file 
+     *                     exceptions use a signature with the errors parameter.
+     */
     public void readDirectory(File d) {
 	readDirectory(d, null, null);
     }
+    /**
+     * Equivalent to readDirectory(d, null, null).
+     * @param d the File to read.  If it is a directory its contents are read
+     * @param errors a Map from entry name to generated exception
+     * @throws IOException if the file is unreadable.  Per file exceptions are
+     *			   returned in the errors parameter.
+     */
     public void readDirectory(File d, Map<String, Exception> errors) {
 	readDirectory(d, null, errors);
     }
+    /**
+     * Equivalent to readDirectory(d, null, null).
+     * @param d the File to read.  If it is a directory its contents are read
+     * @param keys a Collection into which to insert unmatched keys
+     * @throws IOException if the file is unreadable.  To see per-file 
+     *                     exceptions use a signature with the errors parameter.
+     */
     public void readDirectory(File d, Collection<KeyPair> keys) {
 	readDirectory(d, keys, null);
     }
 
+    /**
+     * Write the certificates that make up the context as a zip file, with an
+     * entry for each credential or identity.
+     * @param f the File to write
+     * @param allIDs a boolean, if true write certificates for all Identities,
+     * whether used in signing a credential or not.
+     * @param withPrivateKeys a boolean, if true write the Identities as PEM
+     * file containing both the certificate and the private keys.
+     * @throws IOException if there is a problem writhing the file.
+     */
     public void writeZipFile(File f, boolean allIDs, boolean withPrivateKeys) 
 	    throws IOException {
@@ -602,7 +791,10 @@
 
     /**
-     * Get to the SHA1 hash of the key.
-     */
-    public static String extractKeyID(PublicKey k) {
+     * Get to the SHA1 hash of the key.  Used by Roles and Identities to get a
+     * key ID.
+     * @param k the PublicKey to get the ID from.
+     * @return a String with the key identifier
+     */
+    static String extractKeyID(PublicKey k) {
 	SubjectPublicKeyInfo ki = extractSubjectPublicKeyInfo(k);
 	SubjectKeyIdentifier id = 
@@ -619,6 +811,8 @@
      * Extratct the SubjectPublicKeyInfo.  Useful for some other encryptions,
      * notably Certificate.make_cert().
-     */
-    public static SubjectPublicKeyInfo extractSubjectPublicKeyInfo(
+     * @param k the PublicKey to get the ID from.
+     * @return a String with the key identifier
+     */
+    static SubjectPublicKeyInfo extractSubjectPublicKeyInfo(
 	    PublicKey k) {
 	ASN1Sequence seq = null;
Index: java/net/deterlab/abac/Credential.java
===================================================================
--- java/net/deterlab/abac/Credential.java	(revision 56ec930e01e71105b85ee15e8f8d3314a562a616)
+++ java/net/deterlab/abac/Credential.java	(revision e36ea1d2124f37b1cb324dbc84671ca0f5efa7e5)
@@ -5,32 +5,39 @@
 
 import java.util.*;
-import java.util.zip.*;
 import java.security.*;
 import java.security.cert.*;
 
-import net.deterlab.abac.Identity;
+import javax.security.auth.x500.*;
 
 import org.bouncycastle.asn1.*;
 import org.bouncycastle.asn1.x509.*;
 import org.bouncycastle.x509.*;
-import org.bouncycastle.jce.X509Principal;
-import org.bouncycastle.jce.provider.X509AttrCertParser;
-import org.bouncycastle.jce.provider.X509CertificateObject;
-import org.bouncycastle.openssl.PEMReader;
-
-import java.security.PrivateKey;
-
+import org.bouncycastle.x509.util.*;
+import org.bouncycastle.openssl.*;
+
+/**
+ * An ABAC credential, with or without an underlying certificate that
+ * represents it.  These are edges in proof garphs and can be constructed from
+ * their constituent Roles.
+ * @author <a href="http://abac.deterlab.net">ISI ABAC team</a>
+ * @version 1.3
+ */
 public class Credential implements Comparable {
-    protected static Vector<Identity> s_ids = new Vector<Identity>();
+    /** The ASN1 OID for an IETF attribute. */
     protected static String attrOID = "1.3.6.1.5.5.7.10.4";
+    /** The ASN1 OID for AuthorityKeyIdentifier. */
     protected static String authKeyOID = "2.5.29.35";
 
-    protected Role m_head;
+    /** The role at the head */
+    protected Role m_head
+    /** The role at the tail */;
     protected Role m_tail;
+    /** The certificate representing this credential */
     protected X509V2AttributeCertificate ac;
+    /** The identity that issued the certificate */
     protected Identity id;
 
     /**
-     * A dummy credential.
+     * Create an empty Credential.
      */
     public Credential() {
@@ -40,7 +47,10 @@
     }
     /**
-     * Create a credential from a head and tail role. This is only for testing.
-     * In a real implementation the Credential must be loaded from an X.509
-     * attribute cert.
+     * Create a credential from a head and tail role.  This credential has no
+     * underlying certificate, and cannot be exported or used in real proofs.
+     * make_cert can create a certificate for a credential initialized this
+     * way.
+     * @param head the Role at the head of the credential
+     * @param tail the Role at the tail of the credential
      */
     public Credential(Role head, Role tail) {
@@ -52,21 +62,30 @@
 
     /**
-     * Do the credential initialization from a filename.
+     * Do the credential extraction from an input stream.  This parses the
+     * certificate from the input stream and saves it. The contents must be
+     * validated and parsed later.
+     * @param stream the InputStream to read the certificate from.
+     * @throws IOException if the stream is unparsable
      */
     protected void read_certificate(InputStream stream) 
-	    throws Exception {
-        X509AttrCertParser parser = new X509AttrCertParser();
-        parser.engineInit(stream);
-        ac = (X509V2AttributeCertificate)parser.engineRead();
-    }
-
-
-    protected void init(InputStream stream, Collection<Identity> ids) 
-	    throws Exception {
-	read_certificate(stream);
-	if (ac == null) throw new IOException("Unknown Format");
-	init(ids);
-    }
-
+	    throws IOException {
+	ac = new X509V2AttributeCertificate(stream);
+    }
+
+    /**
+     * Initialize a credential from parsed certificate.  Validiate it against
+     * the given identities and parse out the roles.  Note that catching
+     * java.security.GeneralSecurityException catches most of the exceptions
+     * this throws.
+     * @param ids a Collection of Identities to use in validating the cert
+     * @throws CertificateException if the certificate is badly formatted
+     * @throws InvalidKeyException if none of the Identities can validate the
+     *				    certificate
+     * @throws NoSuchAlgorithmException if the credential uses an unknown
+     *				    signature algorithm
+     * @throws NoSuchProviderException if the provider of the signature
+     *				    algorithm is unavailable
+     * @throws SignatureException if the signature check fails
+     */
     protected void init(Collection<Identity> ids) 
 	    throws CertificateException, InvalidKeyException, 
@@ -88,7 +107,49 @@
 	    throw new InvalidKeyException("Unknown identity");
     }
-    /**
-     * Create a credential from an attribute cert. Throws an exception if the
-     * cert file can't be opened or if there's a format problem with the cert.
+
+    /**
+     * Parse a credential from an InputStream and initialize the role from it.
+     * Combine read_credential(stream) and init(ids).  Note that catching
+     * java.security.GeneralSecurityException catches most of the exceptions
+     * this throws.
+     * @param stream the InputStream to read the certificate from.
+     * @param ids a Collection of Identities to use in validating the cert
+     * @throws CertificateException if the certificate is badly formatted
+     * @throws InvalidKeyException if none of the Identities can validate the
+     *				    certificate
+     * @throws NoSuchAlgorithmException if the credential uses an unknown
+     *				    signature algorithm
+     * @throws NoSuchProviderException if the provider of the signature
+     *				    algorithm is unavailable
+     * @throws SignatureException if the signature check fails
+     * @throws IOException if the certificate is unparsable.
+     */
+    protected void init(InputStream stream, Collection<Identity> ids) 
+	    throws CertificateException, InvalidKeyException, 
+		NoSuchAlgorithmException, NoSuchProviderException,
+		SignatureException, IOException {
+	read_certificate(stream);
+	if (ac == null) throw new IOException("Unknown Format");
+	init(ids);
+    }
+
+    /**
+     * Create a credential from an attribute cert in a file. Throws an
+     * exception if the cert file can't be opened or if there's a format
+     * problem with the cert.  Note that catching
+     * java.security.GeneralSecurityException catches most of the exceptions
+     * this throws.
+     * @param filename a String containing the filename to read
+     * @param ids a Collection of Identities to use in validating the cert
+     * @throws StreamParsingException if the stream is unparsable
+     * @throws CertificateException if the certificate is badly formatted
+     * @throws InvalidKeyException if none of the Identities can validate the
+     *				    certificate
+     * @throws NoSuchAlgorithmException if the credential uses an unknown
+     *				    signature algorithm
+     * @throws NoSuchProviderException if the provider of the signature
+     *				    algorithm is unavailable
+     * @throws SignatureException if the signature check fails
+     * @throws IOException if the certificate is unparsable.
      */
     public Credential(String filename, Collection<Identity> ids) 
@@ -96,18 +157,76 @@
 
     /**
-     * Create a credential from an attribute cert. Throws an exception if the
-     * cert file can't be opened or if there's a format problem with the cert.
+     * Create a credential from an attribute cert in a file. Throws an
+     * exception if the cert file can't be opened or if there's a format
+     * problem with the cert.  Note that catching
+     * java.security.GeneralSecurityException catches most of the exceptions
+     * this throws.
+     * @param file the File to read
+     * @param ids a Collection of Identities to use in validating the cert
+     * @throws StreamParsingException if the stream is unparsable
+     * @throws CertificateException if the certificate is badly formatted
+     * @throws InvalidKeyException if none of the Identities can validate the
+     *				    certificate
+     * @throws NoSuchAlgorithmException if the credential uses an unknown
+     *				    signature algorithm
+     * @throws NoSuchProviderException if the provider of the signature
+     *				    algorithm is unavailable
+     * @throws SignatureException if the signature check fails
+     * @throws IOException if the certificate is unparsable.
      */
     public Credential(File file, Collection<Identity> ids) 
-	throws Exception { init(new FileInputStream(file), ids); }
-
-    /**
-     * Create a credential from an InputStream.
+	    throws CertificateException, InvalidKeyException, 
+		NoSuchAlgorithmException, NoSuchProviderException,
+		SignatureException, StreamParsingException, IOException {
+	init(new FileInputStream(file), ids);
+    }
+
+    /**
+     * Create a credential from an InputStream.  Throws an exception if the
+     * stream can't be parsed or if there's a format problem with the cert.
+     * Note that catching java.security.GeneralSecurityException catches most
+     * of the exceptions this throws.
+     * @param s the InputStream to read
+     * @param ids a Collection of Identities to use in validating the cert
+     * @throws StreamParsingException if the stream is unparsable
+     * @throws CertificateException if the certificate is badly formatted
+     * @throws InvalidKeyException if none of the Identities can validate the
+     *				    certificate
+     * @throws NoSuchAlgorithmException if the credential uses an unknown
+     *				    signature algorithm
+     * @throws NoSuchProviderException if the provider of the signature
+     *				    algorithm is unavailable
+     * @throws SignatureException if the signature check fails
+     * @throws IOException if the certificate is unparsable.
      */
     public Credential(InputStream s, Collection<Identity> ids) 
-	throws Exception { init(s, ids); }
-
+	    throws CertificateException, InvalidKeyException, 
+		NoSuchAlgorithmException, NoSuchProviderException,
+		SignatureException, StreamParsingException, IOException {
+	init(s, ids);
+    }
+
+    /**
+     * Create a credential from an X509V2AttributeCertificate object.  Throws
+     * an exception if the certificate doesn't parse into an ABAC credential,
+     * or cannot be validated.  Note that catching
+     * java.security.GeneralSecurityException catches most of the exceptions
+     * this throws.
+     * @param c the X509V2AttributeCertificate to create from
+     * @param ids a Collection of Identities to use in validating the cert
+     * @throws CertificateException if the certificate is badly formatted
+     * @throws InvalidKeyException if none of the Identities can validate the
+     *				    certificate
+     * @throws NoSuchAlgorithmException if the credential uses an unknown
+     *				    signature algorithm
+     * @throws NoSuchProviderException if the provider of the signature
+     *				    algorithm is unavailable
+     * @throws SignatureException if the signature check fails
+     * @throws IOException if the certificate is unparsable.
+     */
     public Credential(X509V2AttributeCertificate c, Collection<Identity> ids) 
-	throws Exception {
+	    throws CertificateException, InvalidKeyException, 
+		NoSuchAlgorithmException, NoSuchProviderException,
+		SignatureException, IOException {
 	ac = c;
 	init(ids);
@@ -117,7 +236,21 @@
     /**
      * Create a certificate from this credential issued by the given identity.
-     * This is just grungy credential generation work.
-     */
-    public void make_cert(Identity i) {
+     * Note that catching java.security.GeneralSecurityException catches most
+     * of the exceptions this throws.
+     * @param i the Identity that will issue the certificate
+     * @throws IOException reading or writing problems
+     * @throws CertificateEncodingException Problem creating certificate
+     * @throws InvalidKeyException if none of the Identities can sign the
+     *				    certificate
+     * @throws NoSuchAlgorithmException if the credential uses an unknown
+     *				    signature algorithm
+     * @throws NoSuchProviderException if the provider of the signature
+     *				    algorithm is unavailable
+     * @throws SignatureException if the signature creation fails
+     */
+    public void make_cert(Identity i) 
+	    throws IOException, CertificateEncodingException,
+	       NoSuchProviderException, NoSuchAlgorithmException,
+	       SignatureException, InvalidKeyException {
 	PrivateKey key = i.getKeyPair().getPrivate();
 	SubjectPublicKeyInfo pki = Context.extractSubjectPublicKeyInfo(
@@ -127,7 +260,7 @@
 
 	gen.setIssuer(new AttributeCertificateIssuer(
-		    new X509Principal("CN="+m_head.principal())));
+		    new X500Principal("CN="+m_head.principal())));
 	gen.setHolder(new AttributeCertificateHolder(
-		    new X509Principal("CN="+m_head.principal())));
+		    new X500Principal("CN="+m_head.principal())));
 	gen.setNotAfter(new Date(System.currentTimeMillis() 
 		    + 3600 * 1000 * 24 * 365));
@@ -140,14 +273,9 @@
 	gen.setSignatureAlgorithm("SHA256WithRSAEncryption");
 
-	try { 
-	    // Creddy expects an authority key identifier.
-	    gen.addExtension(authKeyOID, false, 
-		    new AuthorityKeyIdentifier(pki));
-	    // Create the cert.
-	    ac = (X509V2AttributeCertificate) gen.generate(key, "BC");
-	}
-	catch (Exception e) { 
-	    System.err.println(e);
-	}
+	// Creddy expects an authority key identifier.
+	gen.addExtension(authKeyOID, false, 
+		new AuthorityKeyIdentifier(pki));
+	// Create the cert.
+	ac = (X509V2AttributeCertificate) gen.generate(key, "BC");
     }
 
@@ -156,5 +284,5 @@
      * there's something wrong with the cert.
      */
-    private void load_roles() throws RuntimeException {
+    private void load_roles() {
         String roles = null;
         try {
@@ -181,4 +309,6 @@
     /**
      * Two credentials are the same if their roles are the same.
+     * @param o an Object to compare
+     * @return true if the Credentials have the Roles 
      */
     public boolean equals(Object o) {
@@ -192,4 +322,11 @@
     }
 
+    /**
+     * Allow credentials to be compared.  They are ordered by their Roles, head
+     * then tail.
+     * @param o an Object to compare
+     * @return -1 if this Credential is before, 0 if they are the same, and 1
+     *		    if this Credential is after the given object.
+     */
     public int compareTo(Object o) {
 	if (o instanceof Credential) {
@@ -205,4 +342,5 @@
     /**
      * Get the head role from the credential.
+     * @return the Role in the head
      */
     public Role head() { return m_head; }
@@ -210,4 +348,5 @@
     /**
      * Get the tail role from the credential
+     * @return the Role in the tail
      */
     public Role tail() { return m_tail; }
@@ -215,4 +354,5 @@
     /**
      * Gets the cert associated with this credential (if any).
+     * @return the attribute cert associated with this credential (if any).
      */
     public X509V2AttributeCertificate cert() { return ac; }
@@ -220,5 +360,6 @@
     /**
      * Turn the credential into string form. The format is head &lt;- tail. For
-     * example: A.r1 &lt;- B.r2.r3.
+     * example: A.r1 &lt;- B.r2.r3.  Principal names are key identifiers.
+     * @return the string form
      */
     public String toString() {
@@ -226,21 +367,59 @@
     }
 
+    /**
+     * Turn the credential into string form. The format is head &lt;- tail. For
+     * example: A.r1 &lt;- B.r2.r3.  Principal names are shortened to menmonics
+     * if the Context knows the identity.
+     * @param c the Context to translate names in
+     * @return the string form
+     */
     public String simpleString(Context c) {
 	return m_head.simpleString(c) + " <- " + m_tail.simpleString(c);
     }
 
+    /**
+     * Output the DER formatted attribute certificate associated with this
+     * Credential to the OutputStream.
+     * @param s the OutputStream on which to write
+     * @throws IOException if there is an error writing.
+     */
     public void write(OutputStream s) throws IOException {
-	s.write(ac.getEncoded());
+	if (ac != null ) 
+	    s.write(ac.getEncoded());
 	s.flush();
     }
 
+    /**
+     * Output the DER formatted attribute certificate associated with this
+     * Credential to the filename given.
+     * @param fn a String containing the output filename
+     * @throws IOException if there is an error writing.
+     */
     public void write(String fn) throws IOException, FileNotFoundException {
 	write(new FileOutputStream(fn));
     }
 
+    /**
+     * Return true if this Credential has a certificate associated.  A jabac
+     * extension.
+     * @return true if this Credential has a certificate associated.
+     */
     public boolean hasCertificate() { return ac != null; }
 
+    /**
+     * Return the Identity that issued the underlying certificate.  A jabac
+     * extension.
+     * @return the Identity that issued the underlying certificate.
+     */
     public Identity issuer() { return id; }
+    /**
+     * Return the X509Certificate that issued the underlying certificate.
+     * @return the X509Certificate that issued the underlying certificate.
+     */
     public X509Certificate issuerCert() { return id.getCertificate(); }
+    /**
+     * Return the X509V2AttributeCertificate that underlys the Credential
+     * @return the X509V2AttributeCertificate that underlys the Credential.
+     */
     public X509V2AttributeCertificate attributeCert() { return ac; }
 
Index: java/net/deterlab/abac/Identity.java
===================================================================
--- java/net/deterlab/abac/Identity.java	(revision 56ec930e01e71105b85ee15e8f8d3314a562a616)
+++ java/net/deterlab/abac/Identity.java	(revision e36ea1d2124f37b1cb324dbc84671ca0f5efa7e5)
@@ -19,13 +19,34 @@
 import org.bouncycastle.openssl.PEMWriter;
 
+/**
+ * An ABAC identity.  An X509 Certificate-encoded public key.  The key
+ * identifier is used as the name of the Identity.  This whole class is
+ * something of a jabac extension.
+ * @author <a href="http://abac.deterlab.net">ISI ABAC team</a>
+ * @version 1.3
+ */
 public class Identity implements Comparable {
-    private X509Certificate cert;
-    private String keyid;
-    private String cn;
-    private KeyPair kp;
-
-    /**
-     *  Initialize internals from PEM cert in a reader.  Use a PEMReader to get
-     *  the certificate, and call init(cert) on it.
+    /** The underlying X509 certificate. */
+    protected X509Certificate cert;
+    /** The public key id used as this principal's name */
+    protected String keyid;
+    /** The common name in the certificate, used as a mnemonic */
+    protected String cn;
+    /** The keypair, if any, used to sign for this Identity */
+    protected KeyPair kp;
+
+    /**
+     * Initialize from PEM cert in a reader.  Use a PEMReader to get
+     * the certificate, and call init(cert) on it.
+     * @param r a Reader containing the certificate
+     * @throws CertificateException if the certificate is badly formatted
+     * @throws InvalidKeyException if none of the Identities can validate the
+     *				    certificate
+     * @throws NoSuchAlgorithmException if the credential uses an unknown
+     *				    signature algorithm
+     * @throws NoSuchProviderException if the provider of the signature
+     *				    algorithm is unavailable
+     * @throws SignatureException if the signature check fails
+     * @throws IOException if the certificate is unparsable.
      */
     protected void init(Reader r) throws 
@@ -51,8 +72,18 @@
 
     /**
-     *  Initialize internals from cert.  Confirm it is self signed,  and then
-     *  the keyid and common name.  There's some work to get this stuff, but
-     *  it's all an incantation of getting the right classes to get the right
-     *  data.  Looks more complex than it is.
+     * Initialize internals from cert.  Confirm it is self signed,  and then
+     * the keyid and common name.  There's some work to get this stuff, but
+     * it's all an incantation of getting the right classes to get the right
+     * data.  Looks more complex than it is.
+     * @param c an X509Certificate to init from
+     * @throws CertificateException if the certificate is badly formatted
+     * @throws InvalidKeyException if none of the Identities can validate the
+     *				    certificate
+     * @throws NoSuchAlgorithmException if the credential uses an unknown
+     *				    signature algorithm
+     * @throws NoSuchProviderException if the provider of the signature
+     *				    algorithm is unavailable
+     * @throws SignatureException if the signature check fails
+     * @throws IOException if the certificate is unparsable.
      */
     protected void init(X509Certificate c) throws
@@ -69,5 +100,15 @@
 
     /**
-     * Construct from a string, used as a CN
+     * Construct from a string, used as a CN.  Keys are generated.
+     * @param cn a String containing the menomnic name
+     * @throws IOException reading or writing problems
+     * @throws CertificateEncodingException Problem creating certificate
+     * @throws InvalidKeyException if none of the Identities can sign the
+     *				    certificate
+     * @throws NoSuchAlgorithmException if the credential uses an unknown
+     *				    signature algorithm
+     * @throws NoSuchProviderException if the provider of the signature
+     *				    algorithm is unavailable
+     * @throws SignatureException if the signature creation fails
      */
     public Identity(String cn) throws
@@ -93,4 +134,14 @@
     /**
      * Construct from a file, containing a self-signed PEM certificate.
+     * @param file the File to read
+     * @throws CertificateException if the certificate is badly formatted
+     * @throws InvalidKeyException if none of the Identities can validate the
+     *				    certificate
+     * @throws NoSuchAlgorithmException if the credential uses an unknown
+     *				    signature algorithm
+     * @throws NoSuchProviderException if the provider of the signature
+     *				    algorithm is unavailable
+     * @throws SignatureException if the signature check fails
+     * @throws IOException if the certificate is unparsable.
      */
     public Identity(File file) throws 
@@ -103,5 +154,15 @@
 
     /**
-     * Construct from a reader, containing a self-signed PEM certificate.
+     * Construct from a reader containing a self-signed PEM certificate.
+     * @param r the Reader containing the certificate
+     * @throws CertificateException if the certificate is badly formatted
+     * @throws InvalidKeyException if none of the Identities can validate the
+     *				    certificate
+     * @throws NoSuchAlgorithmException if the credential uses an unknown
+     *				    signature algorithm
+     * @throws NoSuchProviderException if the provider of the signature
+     *				    algorithm is unavailable
+     * @throws SignatureException if the signature check fails
+     * @throws IOException if the certificate is unparsable.
      */
     public Identity(Reader r) throws 
@@ -113,5 +174,15 @@
 
     /**
-     * Construct from an InputStream, containing a self-signed PEM certificate.
+     * Construct from an InputStream containing a self-signed PEM certificate.
+     * @param s the InputStream containing the certificate
+     * @throws CertificateException if the certificate is badly formatted
+     * @throws InvalidKeyException if none of the Identities can validate the
+     *				    certificate
+     * @throws NoSuchAlgorithmException if the credential uses an unknown
+     *				    signature algorithm
+     * @throws NoSuchProviderException if the provider of the signature
+     *				    algorithm is unavailable
+     * @throws SignatureException if the signature check fails
+     * @throws IOException if the certificate is unparsable.
      */
     public Identity(InputStream s) throws 
@@ -123,6 +194,15 @@
 
     /**
-     * Construct from an X509Certificate, if you parsed one somewhere
-     * else.
+     * Construct from an X509Certificate
+     * @param cert an X509Certificate to init from
+     * @throws CertificateException if the certificate is badly formatted
+     * @throws InvalidKeyException if none of the Identities can validate the
+     *				    certificate
+     * @throws NoSuchAlgorithmException if the credential uses an unknown
+     *				    signature algorithm
+     * @throws NoSuchProviderException if the provider of the signature
+     *				    algorithm is unavailable
+     * @throws SignatureException if the signature check fails
+     * @throws IOException if the certificate is unparsable.
      */
     public Identity(X509Certificate cert) throws 
@@ -136,4 +216,7 @@
     /**
      * Write the PEM key to the given writer.
+     * @param w the Writer
+     * @return true if the Identity had a keypair and wrote the key
+     * @throws IOException if writing fails
      */
     public boolean writePrivateKey(Writer w) throws IOException {
@@ -158,4 +241,7 @@
     /**
      * Write the PEM key to the given file.
+     * @param fn a String with the output file name
+     * @return true if the Identity had a keypair and wrote the key
+     * @throws IOException if writing fails
      */
     public boolean writePrivateKey(File fn) 
@@ -166,4 +252,7 @@
     /**
      * Write the PEM key to the given OutputStream.
+     * @param s an OutputStream to write on
+     * @return true if the Identity had a keypair and wrote the key
+     * @throws IOException if writing fails
      */
     public boolean writePrivateKey(OutputStream s) 
@@ -175,4 +264,6 @@
     /**
      * Write the PEM cert to the given writer.
+     * @param w a Writer to write on
+     * @throws IOException if writing fails
      */
     public void write(Writer w) throws IOException {
@@ -192,4 +283,6 @@
     /**
      * Write the PEM cert to the given file.
+     * @param fn a String with the output file name
+     * @throws IOException if writing fails
      */
     public void write(File fn) throws IOException, FileNotFoundException {
@@ -199,4 +292,6 @@
     /**
      * Write the PEM cert to the given OutputStream.
+     * @param s an OutputStream to write on
+     * @throws IOException if writing fails
      */
     public void write(OutputStream s) 
@@ -206,7 +301,23 @@
 
 
-    // Accessors
+    /**
+     * Return the Identity's KeyID
+     * @return the Identity's KeyID
+     */
     public String getKeyID() { return keyid; }
+    /**
+     * Return the Identity's mnemonic name
+     * @return the Identity's mnemonic name
+     */
     public String getName() { return cn; }
+    /**
+     * Return the Identity's X509 Certificate
+     * @return the Identity's X509 Certificate
+     */
+    public X509Certificate getCertificate() { return cert; }
+    /**
+     * Return a simple string rep of the Identity.
+     * @return a simple string rep of the Identity.
+     */
     public String toString() { 
 	String s = keyid + " (" + cn ;
@@ -220,4 +331,7 @@
      * make sure that the keypair matches it.  If not throw an
      * IllegalArgumentException.
+     * @param k the KeyPair to connect
+     * @throws IllegalArgumentException if the keypair does not 
+     *				    match the pubkey in the X509 certificate
      */
     public void setKeyPair(KeyPair k) {
@@ -232,5 +346,15 @@
 	else kp = k;
     }
+
+    /**
+     * Return the keypair associated with this Identity (if any)
+     * @return the keypair associated with this Identity (if any)
+     */
     public KeyPair getKeyPair() { return kp; }
+
+    /**
+     * Equality test.  Two Identities are equal if their key ID's match.
+     * @return true if the two key ID's are equal.
+     */
     public boolean equals(Object o) { 
 	if ( o == null ) return false;
@@ -238,9 +362,14 @@
 	else return getKeyID().equals(((Identity)o).getKeyID());
     }
+    /**
+     * Allow Identities to be compared.  They are ordered by their key ID's.
+     * @param o an Object to compare
+     * @return -1 if this Identity is before, 0 if they are the same, and 1
+     *		    if this Identity is after the given object.
+     */
     public int compareTo(Object o) { 
 	if ( ! (o instanceof Identity) ) return 1;
 	else return getKeyID().compareTo(((Identity)o).getKeyID());
     }
-    public X509Certificate getCertificate() { return cert; }
 
 };
Index: java/net/deterlab/abac/Role.java
===================================================================
--- java/net/deterlab/abac/Role.java	(revision 56ec930e01e71105b85ee15e8f8d3314a562a616)
+++ java/net/deterlab/abac/Role.java	(revision e36ea1d2124f37b1cb324dbc84671ca0f5efa7e5)
@@ -7,11 +7,19 @@
 /**
  * Represents a role, which is a vertex in a Credential graph.
+ * @author <a href="http://abac.deterlab.net">ISI ABAC team</a>
+ * @version 1.3
  */
 public class Role implements Comparable {
+    /** The role represnetation */
     protected String m_string;
+    /** The role broken into parts between dots */
     protected String[] m_parts;
+    /** The linking role from a linking Role */
     protected String m_A_r1;
+    /** The linked role from a linked Role */
     protected String m_r2;
+    /** A prefix of the role */
     protected String m_prefix;
+    /** Prerequisite roles for an intersection role. */
     protected Role[] m_prereqs;
 
@@ -25,6 +33,9 @@
      * If the string does not have this format, the constructor throws a
      * RuntimeException.
-     */
-    public Role(String s) throws RuntimeException {
+     *
+     * @param s a String with the role name
+     * @throws RuntimeException if the string is badly formatted
+     */
+    public Role(String s) {
         m_string = s;
 
@@ -49,8 +60,19 @@
     }
 
+    /**
+     * Create a role from the given string, converted from mnemonic strings to
+     * key IDs that are known from the Context.  This is a jabac extension.
+     * @param s the String containing the rile name.
+     * @param c the Context in which to expand mnemonics
+     * @throws RuntimeException if the string is badly formatted.
+     */
     public Role(String s, Context c) {
 	this(c.expandKeyID(s));
     }
 
+    /**
+     * Copy an existing role.
+     * @param r the Role to copy
+     */
     public Role(Role r) {
 	m_string = r.m_string;
@@ -67,8 +89,9 @@
 
     /**
-     * Initialize a single non-intersection role. See constructor for details of
-     * role format. Will throw RuntimeException if the role is invalid.
-     */
-    private void single_role() throws RuntimeException {
+     * Initialize a single non-intersection role. See constructor for details
+     * of role format. Will throw RuntimeException if the role is invalid.
+     * @throws RuntimeException if a role is invalid.
+     */
+    private void single_role() {
         m_parts = m_string.split("\\.");
         if (m_parts.length > 3)
@@ -93,4 +116,5 @@
     /**
      * Returns true iff the role is a principal.
+     * @returns true iff the role is a principal.
      */
     public boolean is_principal() { return m_parts.length == 1; }
@@ -98,4 +122,5 @@
     /**
      * Returns true iff the role is a role (i.e., A.r1).
+     * @returns true iff the role is a role (i.e., A.r1).
      */
     public boolean is_role() { return m_parts.length == 2; }
@@ -103,4 +128,5 @@
     /**
      * Returns true iff the role is a linking role (i.e., A.r1.r2).
+     * @returns true iff the role is a linking role (i.e., A.r1.r2).
      */
     public boolean is_linking() { return m_parts.length == 3; }
@@ -108,4 +134,5 @@
     /**
      * Returns true iff the role represents an intersection role.
+     * @returns true iff the role represents an intersection role.
      */
     public boolean is_intersection() { return m_prereqs != null; }
@@ -115,4 +142,6 @@
      * refers to another role in the graph. This will throw a runtime
      * exception if the node is not a linking role.
+     * @returns the first two elements of a linking role's name.
+     * @throws RuntimeException if the role is not linking
      */
     String A_r1() throws RuntimeException {
@@ -125,4 +154,6 @@
      * Return the last element of a linking role's name. This will throw a
      * runtime exception if the node is not a linking role.
+     * @return the last element of a linking role's name.
+     * @throws RuntimeException if the node is not a linking role.
      */
     String r2() throws RuntimeException {
@@ -134,12 +165,25 @@
     /**
      * Returns the principal part of a role or principal. This is everything
-     * except the last element of the name.
-     */
-    public String principal_part() {
+     * except the last element of the name.  Used by Query.
+     * @returns the principal part of a role or principal.
+     */
+    String principal_part() {
         return m_prefix;
     }
 
+    /**
+     * Return the principal
+     * @return the principal
+     */
     public String principal() { return m_parts.length > 0 ? m_parts[0] : null; }
+    /**
+     * Return the role name (part after the first dot and before any second)
+     * @return the role name
+     */
     public String role_name() { return m_parts.length > 1 ? m_parts[1] : null; }
+    /**
+     * Return the linked role (first two parts of a linking role)
+     * @return the linked role
+     */
     public String linked_role() { return A_r1(); }
 
@@ -147,4 +191,6 @@
      * Get the roles that form the prerequisites to this intersection. Throws
      * a runtime exception if this is not an intersection role.
+     * @return a Role[] of prerequisites
+     * @throws RuntimeException if this is not an intersection role
      */
     Role[] prereqs() throws RuntimeException {
