Index: java/net/deterlab/abac/Context.java
===================================================================
--- java/net/deterlab/abac/Context.java	(revision 44896b58622fc4afa61c046f2ff5da0de5722006)
+++ java/net/deterlab/abac/Context.java	(revision 3612811a572b962ff2efd7a1b55e778c7bae3b33)
@@ -239,5 +239,5 @@
 		creds = CredentialFactory.newInstance((File) c, m_identities);
 	    } else if ( c instanceof X509V2AttributeCertificate)  {
-		add_credential(new Credential((X509V2AttributeCertificate)c,
+		add_credential(new X509Credential((X509V2AttributeCertificate)c,
 			    m_identities));
 		return ABAC_CERT_SUCCESS;
@@ -251,11 +251,14 @@
 		add_credential(cc);
 	}
-	catch (InvalidKeyException sig) {
+	catch (MissingIssuerException sig) {
 	    return ABAC_CERT_MISSING_ISSUER ;
 	}
-	catch (SignatureException sig) {
+	catch (BadSignatureException sig) {
 	    return ABAC_CERT_BAD_SIG;
 	}
-	catch (Exception e) {
+	catch (CertInvalidException e) {
+	    return ABAC_CERT_INVALID;
+	}
+	catch (ABACException ae) {
 	    return ABAC_CERT_INVALID;
 	}
@@ -475,5 +478,5 @@
 
         // add the new edge
-        Credential derived_edge = new Credential(head, tail);
+        Credential derived_edge = new InternalCredential(head, tail);
         derived_edges.add(derived_edge);
         g.addEdge(derived_edge, tail, head);
@@ -649,7 +652,9 @@
 	for ( String k: derEntries.keySet() ) {
 	    try {
-		add_credential(new Credential(
+		Credential[] creds = CredentialFactory.newInstance(
 			    new ByteArrayInputStream(derEntries.get(k)),
-			    m_identities));
+			    m_identities);
+		for (Credential c: creds) 
+		    add_credential(c);
 	    }
 	    catch (Exception e ) {
@@ -858,5 +863,8 @@
 	for ( File f : derFiles ) {
 	    try {
-		add_credential(new Credential(f, m_identities));
+		Credential[] creds = CredentialFactory.newInstance(f, 
+			m_identities);
+		for (Credential c: creds) 
+		    add_credential(c);
 	    }
 	    catch (Exception e ) {
@@ -921,5 +929,5 @@
 	    if (cm.find()) continue;
 	    if (rm.find()) 
-		add_credential(new Credential(new Role(rm.group(1)), 
+		add_credential(new InternalCredential(new Role(rm.group(1)), 
 			    new Role(rm.group(2))));
 	    else 
Index: java/net/deterlab/abac/CredentialFactory.java
===================================================================
--- java/net/deterlab/abac/CredentialFactory.java	(revision 44896b58622fc4afa61c046f2ff5da0de5722006)
+++ java/net/deterlab/abac/CredentialFactory.java	(revision 3612811a572b962ff2efd7a1b55e778c7bae3b33)
@@ -2,39 +2,109 @@
 
 import java.io.*;
-
 import java.util.*;
+import java.lang.reflect.*;
 
 
 /**
- * XXX:
- * An ABAC credential, with or without an underlying certificate that
- * represents it.  These are edges in proof graphs and can be constructed from
- * their constituent Roles.
  * @author <a href="http://abac.deterlab.net">ISI ABAC team</a>
  * @version 1.3
  */
 public class CredentialFactory {
-    // XXX register and extend
-    static Credential[] newInstance(File fn, Set<Identity> ids) {
+    static List<Constructor<? extends Credential> > defCons = 
+	new ArrayList<Constructor<? extends Credential> >();
+    static List<Constructor<? extends Credential> > cons = 
+	new ArrayList<Constructor<? extends Credential> >();
+    static String defName = "net.deterlab.abac.GENICredential";
+    public static final int maxSize = 50 * 1024;
+
+    static void initDefaultConstructors() 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);
+	}
+	catch (Exception e) {
+	    throw new ABACException("Could not initialize default " +
+		    "credential parser.  Something is very wrong", e);
+	}
+    }
+
+    static Credential[] newInstance(InputStream is, Set<Identity> ids) 
+	    throws ABACException {
 	Credential rv = null;
-	try {
-	    rv = new X509Credential(fn, ids);
+	ABACException err = null;
+	List<Constructor<? extends Credential> > useCons = 
+	    (cons.size()> 0 ) ? cons : defCons;
+
+	if ( defCons.size() < 1 )  initDefaultConstructors();
+
+	if (!is.markSupported() && useCons.size() > 1) 
+	    is = new BufferedInputStream(is, maxSize);
+	is.mark(maxSize);
+
+	for (Constructor<? extends Credential> c : useCons ) {
+	    try {
+		rv = c.newInstance(is, ids);
+	    }
+	    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);
+		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(); 
+	    }
+	    catch (IOException ie) { 
+		break;
+	    }
 	}
-	catch (Exception e ) {
-	    rv = null;
-	}
-	try {
-	    rv = new GENICredential(fn, ids);
-	}
-	catch (Exception e ) {
-	    rv = null;
-	}
+
 	if ( rv != null ) 
 	    return new Credential[] { rv };
 	else 
-	    return null;
+	    throw (err != null) ? err :
+		new ABACException("null exception and failed construction??");
     }
-    static Credential[] newInstance(String fn, Set<Identity> ids) {
+
+
+    static Credential[] newInstance(File f, Set<Identity> ids) 
+	throws ABACException {
+	try {
+	    return newInstance(new FileInputStream(f), ids);
+	}
+	catch (FileNotFoundException e) {
+	    throw new CertInvalidException(e.getMessage(), e);
+	}
+    }
+    static Credential[] newInstance(String fn, Set<Identity> ids) 
+	throws ABACException {
 	return newInstance(new File(fn), ids);
     }
+
+    static public void registerClass(String name)
+	throws ClassNotFoundException, NoSuchMethodException, 
+			  SecurityException {
+
+	Class c = Class.forName(name);
+	Constructor<?  extends Credential> con = c.getConstructor(
+		Class.forName("java.io.InputStream"),
+		Class.forName("java.util.Collection"));
+
+	cons.add(con);
+    }
 }
Index: java/net/deterlab/abac/GENICredential.java
===================================================================
--- java/net/deterlab/abac/GENICredential.java	(revision 44896b58622fc4afa61c046f2ff5da0de5722006)
+++ java/net/deterlab/abac/GENICredential.java	(revision 3612811a572b962ff2efd7a1b55e778c7bae3b33)
@@ -141,10 +141,13 @@
 	}
 	catch (IllegalArgumentException ie) {
+	    ie.printStackTrace();
 	    throw new IOException("null stream", ie);
 	}
 	catch (SAXException se) {
+	    se.printStackTrace();
 	    throw new IOException(se.getMessage(), se);
 	}
 	catch (Exception e) {
+	    e.printStackTrace();
 	    throw new IOException(e.getMessage(), e);
 	}
Index: java/net/deterlab/abac/InternalCredential.java
===================================================================
--- java/net/deterlab/abac/InternalCredential.java	(revision 3612811a572b962ff2efd7a1b55e778c7bae3b33)
+++ java/net/deterlab/abac/InternalCredential.java	(revision 3612811a572b962ff2efd7a1b55e778c7bae3b33)
@@ -0,0 +1,125 @@
+package net.deterlab.abac;
+
+import java.io.*;
+import java.math.*;
+
+import java.util.*;
+import java.security.*;
+import java.security.cert.*;
+
+import javax.security.auth.x500.*;
+
+import org.bouncycastle.asn1.*;
+import org.bouncycastle.asn1.x509.*;
+import org.bouncycastle.x509.*;
+import org.bouncycastle.x509.util.*;
+import org.bouncycastle.openssl.*;
+
+/**
+ * An Internal Credential, used to represent extra arcs in the proof graph.  It
+ * should never be converted to a cert or output.
+ * @author <a href="http://abac.deterlab.net">ISI ABAC team</a>
+ * @version 1.3
+ */
+public class InternalCredential extends Credential {
+
+    /**
+     * Create an empty InternalCredential.
+     */
+    public InternalCredential() { super(); }
+    /**
+     * Create a credential from a head and tail role.  This credential has no
+     * underlying certificate, and cannot be exported or used in real proofs.
+     * @param head the Role at the head of the credential
+     * @param tail the Role at the tail of the credential
+     */
+    public InternalCredential(Role head, Role tail) {super(head, tail); }
+
+    /**
+     * Create a credential from an attribute cert in a file.  This will always
+     * fail for in InternalCredential.
+     * @param filename a String containing the filename to read
+     * @param ids a Collection of Identities to use in validating the cert
+     * @throws CertInvalidException if the stream is unparsable
+     * @throws MissingIssuerException if none of the Identities can validate the
+     *				    certificate
+     * @throws BadSignatureException if the signature check fails
+     */
+    public InternalCredential(String filename, Collection<Identity> ids) 
+	throws ABACException { this(); }
+
+    /**
+     * Create a credential from an attribute cert in a file.   This will always
+     * * fail for in InternalCredential.
+     * @param file the File to read
+     * @param ids a Collection of Identities to use in validating the cert
+     * @throws CertInvalidException if the stream is unparsable
+     * @throws MissingIssuerException if none of the Identities can validate the
+     *				    certificate
+     * @throws BadSignatureException if the signature check fails
+     */
+    public InternalCredential(File file, Collection<Identity> ids) 
+	    throws ABACException {
+	 this();
+    }
+
+    /**
+     * Create a credential from an InputStream.  This will always
+     * fail for in InternalCredential.
+     * @param ids a Collection of Identities to use in validating the cert
+     * @throws CertInvalidException if the stream is unparsable
+     * @throws MissingIssuerException if none of the Identities can validate the
+     *				    certificate
+     * @throws BadSignatureException if the signature check fails
+     */
+    public InternalCredential(InputStream s, Collection<Identity> ids) 
+	    throws ABACException {
+	 this();
+    }
+
+
+    /**
+     * Create a certificate from this credential issued by the given identity.
+     * This will always fail for an InternalCredential.
+     * @param i the Identity that will issue the certificate
+     * @throws ABACException for Credential-specific errors
+     * @throws MissingIssuerException the identity is invalid
+     * @throws BadSignatureException if the signature creation fails
+     */
+    public void make_cert(Identity i) throws ABACException {
+	throw new ABACException("Cannot create certificate for " +
+		"an InternalCredential");
+    }
+
+    /**
+     * Output the DER formatted attribute certificate associated with this
+     * Credential to the OutputStream.  This will always fail for an
+     * InternalCredential.
+     * @param s the OutputStream on which to write
+     * @throws IOException if there is an error writing.
+     */
+    public void write(OutputStream s) throws IOException {
+	throw new IOException("Cannot write certificate for " +
+		"an InternalCredential");
+    }
+
+    /**
+     * Output the DER formatted attribute certificate associated with this
+     * Credential to the filename given.  This will always fail for an
+     * InternalCredential.
+     * @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((OutputStream) null);
+    }
+
+    /**
+     * Return true if this Credential has a certificate associated.  A jabac
+     * extension.  Always false for an InternalCredential.
+     * @return true if this Credential has a certificate associated.
+     */
+    public boolean hasCertificate() { return false; }
+
+}
Index: java/net/deterlab/abac/X509Credential.java
===================================================================
--- java/net/deterlab/abac/X509Credential.java	(revision 44896b58622fc4afa61c046f2ff5da0de5722006)
+++ java/net/deterlab/abac/X509Credential.java	(revision 3612811a572b962ff2efd7a1b55e778c7bae3b33)
@@ -66,5 +66,10 @@
     protected void read_certificate(InputStream stream) 
 	    throws IOException {
-	ac = new X509V2AttributeCertificate(stream);
+	try { 
+	    ac = new X509V2AttributeCertificate(stream);
+	}
+	catch (Exception e) {
+	    throw new IOException(e.getMessage(), e);
+	}
     }
 
