Index: java/net/deterlab/abac/Context.java
===================================================================
--- java/net/deterlab/abac/Context.java	(revision 3612811a572b962ff2efd7a1b55e778c7bae3b33)
+++ java/net/deterlab/abac/Context.java	(revision f84d71ef9228ce05d039c4a0c59f5022ccd18ed3)
@@ -235,7 +235,9 @@
 		return ABAC_CERT_SUCCESS;
 	    } else if (c instanceof String) {
-		creds = CredentialFactory.newInstance((String) c, m_identities);
+		creds = CredentialFactory.parseCredential(
+			(String) c, m_identities);
 	    } else if (c instanceof File) {
-		creds = CredentialFactory.newInstance((File) c, m_identities);
+		creds = CredentialFactory.parseCredential(
+			(File) c, m_identities);
 	    } else if ( c instanceof X509V2AttributeCertificate)  {
 		add_credential(new X509Credential((X509V2AttributeCertificate)c,
@@ -244,5 +246,4 @@
 	    } else return ABAC_CERT_INVALID;
 
-	    //XXX:
 	    if ( creds == null ) 
 		return ABAC_CERT_INVALID;
@@ -652,5 +653,5 @@
 	for ( String k: derEntries.keySet() ) {
 	    try {
-		Credential[] creds = CredentialFactory.newInstance(
+		Credential[] creds = CredentialFactory.parseCredential(
 			    new ByteArrayInputStream(derEntries.get(k)),
 			    m_identities);
@@ -863,5 +864,5 @@
 	for ( File f : derFiles ) {
 	    try {
-		Credential[] creds = CredentialFactory.newInstance(f, 
+		Credential[] creds = CredentialFactory.parseCredential(f, 
 			m_identities);
 		for (Credential c: creds) 
Index: java/net/deterlab/abac/Credential.java
===================================================================
--- java/net/deterlab/abac/Credential.java	(revision 3612811a572b962ff2efd7a1b55e778c7bae3b33)
+++ java/net/deterlab/abac/Credential.java	(revision f84d71ef9228ce05d039c4a0c59f5022ccd18ed3)
@@ -216,3 +216,18 @@
      */
     public X509Certificate issuerCert() { return id.getCertificate(); }
+
+    /**
+     * Return a CredentialParser that never parses a credential.  Credentials
+     * that can be parsed must override this.  Called indirectly by
+     * CredentialFactory.registerClass().
+     * @return a CredentialParser for this kind of credential.
+     */
+    static public CredentialParser getCredentialParser() { 
+	return new CredentialParser() {
+	    public Credential[] parseCredential(InputStream s, 
+		    Collection<Identity> ids) { 
+		return null; 
+	    } 
+	};
+    }
 }
Index: java/net/deterlab/abac/CredentialFactory.java
===================================================================
--- java/net/deterlab/abac/CredentialFactory.java	(revision 3612811a572b962ff2efd7a1b55e778c7bae3b33)
+++ java/net/deterlab/abac/CredentialFactory.java	(revision f84d71ef9228ce05d039c4a0c59f5022ccd18ed3)
@@ -7,22 +7,28 @@
 
 /**
+ * The system demultiplex point for parsing Credentials.  Static class that
+ * keeps an ordered list of CredentialParsers to try and a couple helper
+ * functions to open files, etc in calling the CredentialParsers.  All
+ * credential parsing should use a credential factory.
  * @author <a href="http://abac.deterlab.net">ISI ABAC team</a>
  * @version 1.3
  */
 public class CredentialFactory {
-    static List<Constructor<? extends Credential> > defCons = 
-	new ArrayList<Constructor<? extends Credential> >();
-    static List<Constructor<? extends Credential> > cons = 
-	new ArrayList<Constructor<? extends Credential> >();
+    static List<CredentialParser> defParsers =new ArrayList<CredentialParser>();
+    static List<CredentialParser> parsers = new ArrayList<CredentialParser>();
     static String defName = "net.deterlab.abac.GENICredential";
     public static final int maxSize = 50 * 1024;
 
-    static void initDefaultConstructors() throws ABACException {
+    /**
+     * Initialize the Default parser list.
+     * @throws ABACException in extreme cases.  Should never happen.
+     */
+    static void initDefaultParser() throws ABACException {
 	try {
 	    Class c = Class.forName(defName);
-	    Constructor<?  extends Credential> con = c.getConstructor(
-		    Class.forName("java.io.InputStream"),
-		    Class.forName("java.util.Collection"));
-	    defCons.add(con);
+	    Method m = c.getMethod("getCredentialParser");
+	    CredentialParser cp = (CredentialParser) m.invoke(null);
+
+	    defParsers.add(cp);
 	}
 	catch (Exception e) {
@@ -32,41 +38,41 @@
     }
 
-    static Credential[] newInstance(InputStream is, Set<Identity> ids) 
-	    throws ABACException {
-	Credential rv = null;
+    /**
+     * Parse an input stream using each possible credential format and the
+     * available identities for validation.  Return the credentials found or
+     * throw an ABACException with the problem.  It wraps the input stream in a
+     * BufferedInputStream in order to retry is a parser fails.  Credentials
+     * larger than maxSize will nor be able to be reparsed.
+     * @param is an InputStream to parse
+     * @param ids a Collection of Identities for validation
+     * @return an Array of Credentials parsed
+     * @throws CertInvalidException if the stream is unparsable
+     * @throws MissingIssuerException if none of the Identities can validate the
+     * @throws BadSignatureException if the signature check fails
+     */
+    static public Credential[] parseCredential(InputStream is, 
+	    Collection<Identity> ids) throws ABACException {
+	Credential[] rv = null;
 	ABACException err = null;
-	List<Constructor<? extends Credential> > useCons = 
-	    (cons.size()> 0 ) ? cons : defCons;
+	List<CredentialParser> useParsers = 
+	    (parsers.size()> 0 ) ? parsers : defParsers;
 
-	if ( defCons.size() < 1 )  initDefaultConstructors();
+	if ( defParsers.size() < 1 )  initDefaultParser();
 
-	if (!is.markSupported() && useCons.size() > 1) 
+	if (!is.markSupported() && useParsers.size() > 1) 
 	    is = new BufferedInputStream(is, maxSize);
 	is.mark(maxSize);
 
-	for (Constructor<? extends Credential> c : useCons ) {
+	for (CredentialParser c : useParsers ) {
 	    try {
-		rv = c.newInstance(is, ids);
+		rv = c.parseCredential(is, ids);
+		break;
 	    }
-	    catch (InvocationTargetException ie ) {
-		Throwable th = ie.getCause();
-
-		if ( th != null && th instanceof ABACException ) 
-		    err = (ABACException) th;
-		else
-		    err = new ABACException("Constructor error " + 
-				"(this is weird) " + ie.getMessage(), ie);
+	    catch (ABACException e ) {
+		err = e;
 		rv = null;
 	    }
-	    catch (Exception e ) {
-		err = new ABACException("Constructor error " + 
-			e.getMessage(), e);
-		rv = null;
-	    }
-	    if ( rv != null ) 
-		break;
-
 	    try {
-		if (useCons.size() > 1) is.reset(); 
+		if (useParsers.size() > 1) is.reset(); 
 	    }
 	    catch (IOException ie) { 
@@ -76,5 +82,5 @@
 
 	if ( rv != null ) 
-	    return new Credential[] { rv };
+	    return rv;
 	else 
 	    throw (err != null) ? err :
@@ -83,8 +89,20 @@
 
 
-    static Credential[] newInstance(File f, Set<Identity> ids) 
-	throws ABACException {
+    /**
+     * Parse a File using each possible credential format and the
+     * available identities for validation.  Return the credentials found or
+     * throw an ABACException with the problem.  Calls the InputStream version
+     * internally.
+     * @param f a File to parse
+     * @param ids a Collection of Identities for validation
+     * @return an Array of Credentials parsed
+     * @throws CertInvalidException if the stream is unparsable
+     * @throws MissingIssuerException if none of the Identities can validate the
+     * @throws BadSignatureException if the signature check fails
+     */
+    static public Credential[] parseCredential(File f, 
+	    Collection<Identity> ids) throws ABACException {
 	try {
-	    return newInstance(new FileInputStream(f), ids);
+	    return parseCredential(new FileInputStream(f), ids);
 	}
 	catch (FileNotFoundException e) {
@@ -92,19 +110,45 @@
 	}
     }
-    static Credential[] newInstance(String fn, Set<Identity> ids) 
-	throws ABACException {
-	return newInstance(new File(fn), ids);
+    /**
+     * Parse a file named fn using each possible credential format and the
+     * available identities for validation.  Return the credentials found or
+     * throw an ABACException with the problem.  Calls the InputStream version
+     * internally.
+     * @param fn a String holding the filename to parse
+     * @param ids a Collection of Identities for validation
+     * @return an Array of Credentials parsed
+     * @throws CertInvalidException if the stream is unparsable
+     * @throws MissingIssuerException if none of the Identities can validate the
+     * @throws BadSignatureException if the signature check fails
+     */
+    static public Credential[] parseCredential(String fn, 
+	    Collection<Identity> ids) throws ABACException {
+	return parseCredential(new File(fn), ids);
     }
 
+    /**
+     * Add the named class to the list of usable parsers.  The class passed in
+     * must have a static getCredentialParser() method that returns a
+     * CredentialParser to use.
+     * @param name a String containing the binary name of the class to register
+     * @throws ABACException if there is a problem.  The cause field of this
+     * exception is set to the classloading exception, if any.
+     */
     static public void registerClass(String name)
-	throws ClassNotFoundException, NoSuchMethodException, 
-			  SecurityException {
+	throws ABACException {
+	CredentialParser cp = null;
 
-	Class c = Class.forName(name);
-	Constructor<?  extends Credential> con = c.getConstructor(
-		Class.forName("java.io.InputStream"),
-		Class.forName("java.util.Collection"));
+	try {
+	    Class c = Class.forName(defName);
+	    Method m = c.getMethod("getCredentialParser");
 
-	cons.add(con);
+	    cp = (CredentialParser) m.invoke(null);
+	}
+	catch (Exception e) {
+	    throw new ABACException("Could not register credential type" + 
+		    e.getMessage(), e);
+	}
+
+	parsers.add(cp);
     }
 }
Index: java/net/deterlab/abac/CredentialParser.java
===================================================================
--- java/net/deterlab/abac/CredentialParser.java	(revision f84d71ef9228ce05d039c4a0c59f5022ccd18ed3)
+++ java/net/deterlab/abac/CredentialParser.java	(revision f84d71ef9228ce05d039c4a0c59f5022ccd18ed3)
@@ -0,0 +1,27 @@
+package net.deterlab.abac;
+
+import java.io.*;
+import java.util.*;
+import java.lang.reflect.*;
+
+
+/**
+ * This class parses one or more Credentials.  Each class that wants to be
+ * parsed needs to export a static method that returns one of these.  For
+ * credentials that parse 1 credential to 1 input it will be a wrapper around a
+ * constructor.
+ * @author <a href="http://abac.deterlab.net">ISI ABAC team</a>
+ * @version 1.3
+ */
+public abstract class CredentialParser {
+    /**
+     * Parse one or more Credentials from the given input and IDs.  The
+     * sub-type of Credential returned is up to this class.
+     * @param is an InputStream to be parsed
+     * @param ids a Collection of Identity s to use in validating credentials.
+     * @return an array of Credentials
+     * @throws ABACException on parsing problems
+     */
+    public abstract Credential[] parseCredential(InputStream is, 
+	    Collection<Identity> ids) throws ABACException;
+}
Index: java/net/deterlab/abac/GENICredential.java
===================================================================
--- java/net/deterlab/abac/GENICredential.java	(revision 3612811a572b962ff2efd7a1b55e778c7bae3b33)
+++ java/net/deterlab/abac/GENICredential.java	(revision f84d71ef9228ce05d039c4a0c59f5022ccd18ed3)
@@ -588,3 +588,17 @@
     public boolean hasCertificate() { return doc != null; }
 
+    /**
+     * Return a CredentialParser for GENICredentials.  Used by the
+     * CredentialFactory to parse these kind of credentials.  It is basically a
+     * constuctor call.
+     * @return a CredentialParser for this kind of credential.
+     */
+    static public CredentialParser getCredentialParser() {
+	return new CredentialParser() {
+	    public Credential[] parseCredential(InputStream is, 
+		    Collection<Identity> ids) throws ABACException {
+		return new Credential[] { new GENICredential(is, ids) }; 
+	    }
+	};
+    }
 }
Index: java/net/deterlab/abac/X509Credential.java
===================================================================
--- java/net/deterlab/abac/X509Credential.java	(revision 3612811a572b962ff2efd7a1b55e778c7bae3b33)
+++ java/net/deterlab/abac/X509Credential.java	(revision f84d71ef9228ce05d039c4a0c59f5022ccd18ed3)
@@ -321,4 +321,19 @@
     public X509V2AttributeCertificate attributeCert() { return ac; }
 
+    /**
+     * Return a CredentialParser for X509Credentials.  Used by the
+     * CredentialFactory to parse these kind of credentials.  It is basically a
+     * constuctor call.
+     * @return a CredentialParser for this kind of credential.
+     */
+    static public CredentialParser getCredentialParser() {
+	return new CredentialParser() {
+	    public Credential[] parseCredential(InputStream is, 
+		    Collection<Identity> ids) throws ABACException {
+		return new Credential[] { new X509Credential(is, ids) }; 
+	    }
+	};
+    }
+
 
 }
