Index: java/net/deterlab/abac/GENICredential.java
===================================================================
--- java/net/deterlab/abac/GENICredential.java	(revision 5a16edff185fb88403082b8fd6d8cd22feef2f61)
+++ java/net/deterlab/abac/GENICredential.java	(revision c1736fe3113c21b39b3ffa81901a4118bcfdaa01)
@@ -25,9 +25,9 @@
 
 /**
- * An ABAC credential formatted as an abac-type GENI credential.
+ * Abstract Base class from which GENI credentials are derived.
  * @author <a href="http://abac.deterlab.net">ISI ABAC team</a>
  * @version 1.4
  */
-public class GENICredential extends Credential implements Comparable {
+public abstract class GENICredential extends Credential implements Comparable {
     /** The signed XML representing this credential */
     protected Document doc;
@@ -401,6 +401,6 @@
 
     /**
-     * Encode the abac credential's XML and set the validity.  This is straight
-     * line code that directly builds the credential.
+     * Encode the abac credential's XML and set the validity. Overload this to
+     * build a real credential.
      * @param validity a long holding the number of seconds that the credential
      * is valid for.
@@ -408,69 +408,6 @@
      * @throws ABACException if any of the XML construction fails
      */
-    protected Node make_rt0_content(long validity) throws ABACException {
-	DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
-	DocumentBuilder db = null;
-	SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
-	StringBuffer expBuf = new StringBuffer();
-
-	/* This is a weirdness to cope with the GENI format.  They have a naked
-	 * xml:id specifier without any namespace declarations in the
-	 * credential.  Notice that this is the opposite of the setting used in
-	 * init to read a credential. */
-	dbf.setNamespaceAware(false);
-
-	if ( dbf == null ) 
-	    throw new ABACException("Cannot get DocumentBuilderFactory!?");
-
-	try {
-	    db = dbf.newDocumentBuilder();
-	}
-	catch (ParserConfigurationException pe) {
-	    throw new ABACException("Cannot get DocumentBuilder!?" + 
-		    pe.getMessage(), pe);
-	}
-
-	doc = db.newDocument();
-	if ( doc == null ) 
-	    throw new ABACException("No Document");
-
-	Element root = doc.createElement("signed-credential"); 
-	Element cred = doc.createElement("credential");
-	Element sig = doc.createElement("signatures");
-	Element e = doc.createElement("type");
-	Node text = doc.createTextNode("abac");
-
-	doc.appendChild(root);
-
-	cred.setAttribute("xml:id", "ref0");
-	/* So that the signing code can find the section to sign */
-	cred.setIdAttribute("xml:id", true);
-
-	root.appendChild(cred);
-	e.appendChild(text);
-	cred.appendChild(e);
-
-	m_expiration = new Date(System.currentTimeMillis() + 
-		(1000L * validity ));
-	df.setTimeZone(new SimpleTimeZone(0, "Z"));
-	df.format(m_expiration, expBuf, new FieldPosition(0));
-	e = doc.createElement("expires");
-	text = doc.createTextNode(expBuf.toString());
-	e.appendChild(text);
-	cred.appendChild(e);
-
-	e = doc.createElement("version");
-	text = doc.createTextNode("1.0");
-	e.appendChild(text);
-	cred.appendChild(e);
-
-	e = doc.createElement("rt0");
-	text = doc.createTextNode(m_head + "<-" + m_tail);
-	e.appendChild(text);
-	cred.appendChild(e);
-
-	root.appendChild(sig);
-	return sig;
-    }
+    abstract protected Node make_rt0_content(long validity) 
+	throws ABACException;
 
     /**
@@ -569,45 +506,9 @@
 
     /**
-     * Load the roles off the attribute cert.
+     * Load the roles off the attribute cert. Overload it to make a real
+     * credential.
      * @throws CertInvalidException if the certificate is badly formatted
      */
-    protected void load_roles() throws CertInvalidException {
-	if ( doc == null ) 
-            throw new CertInvalidException("No credential");
-
-	NodeList nodes = doc.getElementsByTagName("type");
-	Node node = null;
-        String roles = null;
-
-	if (nodes == null || nodes.getLength() != 1) 
-            throw new CertInvalidException("More than one type element?");
-
-	node = nodes.item(0);
-	if ( node == null ) 
-            throw new CertInvalidException("bad rt0 element?");
-
-	if ( !"abac".equals(node.getTextContent()) ) 
-            throw new CertInvalidException("Not an abac type credential");
-
-	nodes = doc.getElementsByTagName("rt0");
-	if (nodes == null || nodes.getLength() != 1) 
-            throw new CertInvalidException("More than one rt0 element?");
-
-	node = nodes.item(0);
-
-	if ( node == null ) 
-            throw new CertInvalidException("bad rt0 element?");
-
-	if ( (roles = node.getTextContent()) == null ) 
-            throw new CertInvalidException("bad rt0 element (no text)?");
-
-        String[] parts = roles.split("\\s*<--?\\s*");
-        if (parts.length != 2)
-            throw new CertInvalidException("Invalid attribute: " + roles);
-
-        m_head = new Role(parts[0]);
-        m_tail = new Role(parts[1]);
-    }
-
+    abstract protected void load_roles() throws CertInvalidException;
     /**
      * Output the signed GENI ABAC certificate associated with this
@@ -650,21 +551,3 @@
     public boolean hasCertificate() { return doc != null; }
 
-    /**
-     * Return a CredentialCredentialFactorySpecialization for GENICredentials.
-     * Used by the CredentialFactory to parse and generate these kind of
-     * credentials.  It basically wraps constuctor calls.
-     * @return a CredentialFactorySpecialization for this kind of credential.
-     */
-    static public CredentialFactorySpecialization 
-	    getCredentialFactorySpecialization() {
-	return new CredentialFactorySpecialization() {
-	    public Credential[] parseCredential(InputStream is, 
-		    Collection<Identity> ids) throws ABACException {
-		return new Credential[] { new GENICredential(is, ids) }; 
-	    }
-	    public Credential generateCredential(Role head, Role tail) {
-		return new GENICredential(head, tail);
-	    }
-	};
-    }
 }
