Index: java/net/deterlab/abac/Credential.java
===================================================================
--- java/net/deterlab/abac/Credential.java	(revision e9360e21c22cb2a8f081d3680b10d5693d77bfc1)
+++ java/net/deterlab/abac/Credential.java	(revision 84f0e7a4da6df1ae9c533c9c8958bce33f2144ca)
@@ -49,13 +49,22 @@
      * Do the credential initialization from a filename.
      */
-    protected void init(InputStream stream) throws Exception {
+    protected void read_certificate(InputStream stream) 
+	    throws Exception {
         X509AttrCertParser parser = new X509AttrCertParser();
         parser.engineInit(stream);
         m_ac = (X509V2AttributeCertificate)parser.engineRead();
-	m_id = null;
-
-	if ( m_ac == null ) throw new IOException("Invalid Credential Format");
-
-	for (Identity id: s_ids) {
+    }
+
+
+    protected void init(InputStream stream, Collection<Identity> ids) 
+	    throws Exception {
+	read_certificate(stream);
+	if (m_ac == null) throw new IOException("Unknown Format");
+	init(ids);
+    }
+
+    protected void init(Collection<Identity> ids) 
+	    throws CertificateException, InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException,SignatureException {
+	for (Identity id: ids) {
 	    try {
 		m_ac.verify(id.getCertificate().getPublicKey(), "BC");
@@ -72,12 +81,10 @@
 	    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.
      */
-    public Credential(String filename) throws Exception {
-	init(new FileInputStream(filename));
-    }
+    public Credential(String filename, Collection<Identity> ids) 
+	throws Exception { init(new FileInputStream(filename), ids); }
 
     /**
@@ -85,14 +92,19 @@
      * cert file can't be opened or if there's a format problem with the cert.
      */
-    public Credential(File file) throws Exception {
-	init(new FileInputStream(file));
-    }
+    public Credential(File file, Collection<Identity> ids) 
+	throws Exception { init(new FileInputStream(file), ids); }
 
     /**
      * Create a credential from an InputStream.
      */
-    public Credential(InputStream s) throws Exception { 
-	init(s);
-    }
+    public Credential(InputStream s, Collection<Identity> ids) 
+	throws Exception { init(s, ids); }
+
+    public Credential(X509V2AttributeCertificate c, Collection<Identity> ids) 
+	throws Exception {
+	m_ac = c;
+	init(ids);
+    }
+
 
     /**
@@ -213,6 +225,6 @@
     }
 
-    public String simpleString() {
-	return m_head.simpleString() + " <- " + m_tail.simpleString();
+    public String simpleString(Context c) {
+	return m_head.simpleString(c) + " <- " + m_tail.simpleString(c);
     }
 
@@ -230,243 +242,4 @@
     public Identity getID() { return m_id; }
 
-    /**
-     * Import a zip file.  First import all the identities
-     * (pem), then the credentials (der) into the credential graph then any
-     * alias files into the two maps.  If keys is not null, any key pairs in
-     * PEM files are put in there.  If errors is not null, errors reading files
-     * are added indexed by filename.
-     */
-    static public Collection<Credential> readZipFile(File zf, 
-	    Collection<KeyPair> keys, Map<String, Exception> errors) 
-		throws IOException {
-	Vector<Credential> creds = new Vector<Credential>();
-	Vector<ZipEntry> derEntries = new Vector<ZipEntry>();
-	Map<String, Identity> ids = new TreeMap<String, Identity>();
-	Map<String, KeyPair> kps = new TreeMap<String, KeyPair>();
-
-	ZipFile z = new ZipFile(zf);
-
-	for (Enumeration<? extends ZipEntry> ze = z.entries(); 
-		ze.hasMoreElements();) {
-	    ZipEntry  f = ze.nextElement();
-	    try {
-		PEMReader r = new PEMReader(
-			new InputStreamReader(z.getInputStream(f)));
-		Object o = readPEM(r);
-
-		if ( o != null ) {
-		    if (o instanceof Identity) {
-			Identity i = (Identity) o;
-			String kid = i.getKeyID();
-
-			if (kps.containsKey(kid) ) {
-			    i.setKeyPair(kps.get(kid));
-			    kps.remove(kid);
-			}
-			else if (i.getKeyPair() == null ) 
-			    ids.put(i.getKeyID(), i);
-
-			Credential.addIdentity(i);
-		    }
-		    else if (o instanceof KeyPair ) {
-			KeyPair kp = (KeyPair) o;
-			String kid = Identity.extractKeyID(kp.getPublic());
-
-			if (ids.containsKey(kid)) {
-			    Identity i = ids.get(kid);
-
-			    i.setKeyPair(kp);
-			    ids.remove(kid);
-			}
-			else {
-			    kps.put(kid, kp);
-			}
-		    }
-		}
-		else {
-		    // Not a PEM file
-		    derEntries.add(f);
-		    continue;
-		}
-	    }
-	    catch (Exception e ) {
-		if (errors != null ) errors.put(f.getName(), e);
-	    }
-	}
-
-	for ( ZipEntry f : derEntries ) {
-	    try {
-		creds.add(new Credential(z.getInputStream(f)));
-	    }
-	    catch (Exception e ) {
-		if (errors != null ) errors.put(f.getName(), e);
-	    }
-	}
-	return creds;
-    }
-
-    static public Collection<Credential> readZipFile(File d) 
-	    throws IOException {
-	return readZipFile(d, null, null);
-    }
-    static public Collection<Credential> readZipFile(File d, 
-	    Map<String, Exception> errors) throws IOException {
-	return readZipFile(d, null, errors);
-    }
-    static public Collection<Credential> readZipFile(File d, 
-	    Collection<KeyPair> keys) throws IOException {
-	return readZipFile(d, keys, null);
-    }
-
-    protected static Object readPEM(PEMReader r) throws IOException {
-	Identity i = null;
-	KeyPair keys = null;
-	Object o = null;
-
-	while ( (o = r.readObject()) != null ) {
-	    if (o instanceof X509CertificateObject) {
-		if ( i == null ) {
-		    try {
-			i = new Identity((X509CertificateObject)o);
-		    }
-		    catch (Exception e) {
-			// Translate Idenitiy exceptions to IOException
-			throw new IOException(e);
-		    }
-		    if (keys != null ) {
-			i.setKeyPair(keys);
-			keys = null;
-		    }
-		}
-		else throw new IOException("Two certificates");
-	    }
-	    else if (o instanceof KeyPair ) {
-		if ( i != null ) i.setKeyPair((KeyPair) o);
-		else keys = (KeyPair) o;
-	    }
-	    else {
-		throw new IOException("Unexpected PEM object: " + 
-			o.getClass().getName());
-	    }
-	}
-
-	if ( i != null ) return i;
-	else if ( keys != null) return keys;
-	else return null;
-    }
-
-    /**
-     * Import a directory full of files.  First import all the identities
-     * (pem), then the credentials (der) into the credential graph then any
-     * alias files into the two maps.  If keys is not null, any key pairs in
-     * PEM files are put in there.  If errors is not null, errors reading files
-     * are added indexed by filename.
-     */
-    static public Collection<Credential> readDirectory(File d, 
-	    Collection<KeyPair> keys, Map<String, Exception> errors) {
-	Vector<Credential> creds = new Vector<Credential>();
-	Vector<File> derFiles = new Vector<File>();
-	Collection<File> files = new Vector<File>();
-	Map<String, Identity> ids = new TreeMap<String, Identity>();
-	Map<String, KeyPair> kps = new TreeMap<String, KeyPair>();
-
-	if (d.isDirectory() ) 
-	    for (File f : d.listFiles()) 
-		files.add(f);
-	else files.add(d);
-
-	for (File f: files ) {
-	    try {
-		PEMReader r = new PEMReader(new FileReader(f));
-		Object o = readPEM(r);
-
-		if ( o != null ) {
-		    if (o instanceof Identity) {
-			Identity i = (Identity) o;
-			String kid = i.getKeyID();
-
-			if (kps.containsKey(kid) ) {
-			    i.setKeyPair(kps.get(kid));
-			    kps.remove(kid);
-			}
-			else if (i.getKeyPair() == null ) 
-			    ids.put(i.getKeyID(), i);
-
-			Credential.addIdentity(i);
-		    }
-		    else if (o instanceof KeyPair ) {
-			KeyPair kp = (KeyPair) o;
-			String kid = Identity.extractKeyID(kp.getPublic());
-
-			if (ids.containsKey(kid)) {
-			    Identity i = ids.get(kid);
-
-			    i.setKeyPair(kp);
-			    ids.remove(kid);
-			}
-			else {
-			    kps.put(kid, kp);
-			}
-		    }
-		}
-		else {
-		    // Not a PEM file
-		    derFiles.add(f);
-		    continue;
-		}
-	    }
-	    catch (Exception e ) {
-		if (errors != null ) errors.put(f.getName(), e);
-	    }
-	}
-
-	for ( File f : derFiles ) {
-	    try {
-		creds.add(new Credential(f));
-	    }
-	    catch (Exception e ) {
-		if (errors != null ) errors.put(f.getName(), e);
-	    }
-	}
-	return creds;
-    }
-
-    static public Collection<Credential> readDirectory(File d) {
-	return readDirectory(d, null, null);
-    }
-    static public Collection<Credential> readDirectory(File d, 
-	    Map<String, Exception> errors) {
-	return readDirectory(d, null, errors);
-    }
-    static public Collection<Credential> readDirectory(File d, 
-	    Collection<KeyPair> keys) {
-	return readDirectory(d, keys, null);
-    }
-
-    static public void writeZipFile(Collection<Credential> creds, File f,
-	    boolean allIDs, boolean withPrivateKeys) 
-	    throws IOException {
-	ZipOutputStream z = new ZipOutputStream(new FileOutputStream(f));
-	Set<Identity> ids = allIDs ? 
-	    new TreeSet<Identity>(s_ids) : new TreeSet<Identity>();
-
-	int n = 0;
-	for (Credential c: creds) {
-	    z.putNextEntry(new ZipEntry("attr" + n++  + ".der"));
-	    c.write(z);
-	    z.closeEntry();
-	    if ( c.getID() != null && !allIDs) ids.add(c.getID());
-	}
-	for (Identity i: ids) {
-	    z.putNextEntry(new ZipEntry(i.getName() + ".pem"));
-	    i.write(z);
-	    if (withPrivateKeys)
-		i.writePrivateKey(z);
-	    z.closeEntry();
-	}
-	z.close();
-    }
-
-
 private Role m_head, m_tail;
 
@@ -474,28 +247,3 @@
 private Identity m_id;
 
-    /**
-     * Put the Identity into the set of ids used to validate certificates.
-     * Also put the keyID and name into the translation mappings used by Roles
-     * to pretty print.  In the role mapping, if multiple ids use the same
-     * common name they are disambiguated.  Only one entry for keyid is
-     * allowed.
-     */
-    public static void addIdentity(Identity id) { 
-	s_ids.add(id);
-	if (id.getName() != null && id.getKeyID() != null) {
-	    if ( !Role.key_in_mapping(id.getKeyID()) ) {
-		String name = id.getName();
-		int n= 1;
-
-		while (Role.name_in_mapping(name)) {
-		    name = id.getName() + n++;
-		}
-		Role.add_mapping(name, id.getKeyID());
-	    }
-	}
-    }
-    public static Collection<Identity> identities() { return s_ids; }
-    public static void clearIdentities() {
-	s_ids.clear(); Role.clear_mapping();
-    }
 }
Index: java/net/deterlab/abac/Identity.java
===================================================================
--- java/net/deterlab/abac/Identity.java	(revision e9360e21c22cb2a8f081d3680b10d5693d77bfc1)
+++ java/net/deterlab/abac/Identity.java	(revision 84f0e7a4da6df1ae9c533c9c8958bce33f2144ca)
@@ -15,10 +15,10 @@
 import org.bouncycastle.x509.*;
 import org.bouncycastle.jce.provider.X509AttrCertParser;
-import org.bouncycastle.jce.provider.X509CertificateObject;
+// import org.bouncycastle.jce.provider.X509CertificateObject;
 import org.bouncycastle.openssl.PEMReader;
 import org.bouncycastle.openssl.PEMWriter;
 
 public class Identity implements Comparable {
-    private X509CertificateObject m_cert;
+    private X509Certificate m_cert;
     private String m_keyid;
     private String m_cn;
@@ -37,7 +37,7 @@
 	while ( ( c= pr.readObject()) != null ){
 
-	    if (c instanceof X509CertificateObject) {
+	    if (c instanceof X509Certificate) {
 		if ( m_cn == null ) 
-		    init((X509CertificateObject)c);
+		    init((X509Certificate)c);
 		else
 		    throw new CertificateException("Two certs in one file");
@@ -56,8 +56,8 @@
      *  data.  Looks more complex than it is.
      */
-    protected void init(X509CertificateObject c) throws
+    protected void init(X509Certificate c) throws
 	CertificateException, NoSuchAlgorithmException,InvalidKeyException,
 	NoSuchProviderException, SignatureException, IOException {
-	    m_cert = (X509CertificateObject) c;
+	    m_cert = (X509Certificate) c;
 	    m_cert.verify(m_cert.getPublicKey());
 	    // Cert is valid, fill in the CN and keyid
@@ -85,6 +85,5 @@
 	gen.setPublicKey(kp.getPublic());
 	gen.setSignatureAlgorithm("SHA256WithRSAEncryption");
-	X509CertificateObject a = 
-	    (X509CertificateObject) gen.generate(kp.getPrivate());
+	X509Certificate a = (X509Certificate) gen.generate(kp.getPrivate());
 	init(a);
     }
@@ -124,8 +123,8 @@
 
     /**
-     * Construct from an X509CertificateObject, if you parsed one somewhere
+     * Construct from an X509Certificate, if you parsed one somewhere
      * else.
      */
-    public Identity(X509CertificateObject cert) throws 
+    public Identity(X509Certificate cert) throws 
 	CertificateException, NoSuchAlgorithmException,InvalidKeyException,
 	NoSuchProviderException, SignatureException, FileNotFoundException,
@@ -276,5 +275,5 @@
 	else return getKeyID().compareTo(((Identity)o).getKeyID());
     }
-    public X509CertificateObject getCertificate() { return m_cert; }
+    public X509Certificate getCertificate() { return m_cert; }
 
 };
Index: java/net/deterlab/abac/Query.java
===================================================================
--- java/net/deterlab/abac/Query.java	(revision e9360e21c22cb2a8f081d3680b10d5693d77bfc1)
+++ java/net/deterlab/abac/Query.java	(revision 84f0e7a4da6df1ae9c533c9c8958bce33f2144ca)
@@ -36,5 +36,6 @@
                     new DirectedSparseGraph<Role,Credential>());
 
-        /* empty attribute, non-empty principal: find everywhere the principal can go */
+	/* empty attribute, non-empty principal: find everywhere the principal
+	 * can go */
         if (attr.isEmpty() && !prin.isEmpty()) {
             if (g.containsVertex(principal)) {
@@ -52,5 +53,6 @@
             else {
                 if ( g.containsVertex(principal)) {
-                    CollectQueryPath  collect = new CollectQueryPath(ret, principal);
+                    CollectQueryPath  collect = new CollectQueryPath(ret,
+			    principal);
                     reverse_dfs(attribute, collect);
                 }
Index: java/net/deterlab/abac/Role.java
===================================================================
--- java/net/deterlab/abac/Role.java	(revision e9360e21c22cb2a8f081d3680b10d5693d77bfc1)
+++ java/net/deterlab/abac/Role.java	(revision 84f0e7a4da6df1ae9c533c9c8958bce33f2144ca)
@@ -51,6 +51,6 @@
     }
 
-    public Role(String s, boolean translate) {
-	this(translate ? replace(s, nicknames) : s);
+    public Role(String s, Context c) {
+	this(c.expandKeyID(s));
     }
 
@@ -157,6 +157,6 @@
     }
 
-    public String simpleString() {
-	return replace(m_string, keys);
+    public String simpleString(Context c) {
+	return c.expandNickname(m_string);
     }
 
@@ -177,40 +177,3 @@
     }
 
-
-    /**
-     * Translate either keys to nicknames or vice versa.  Break the string into
-     * space separated tokens and then each of them into period separated
-     * strings.  If any of the smallest strings is in the map, replace it with
-     * the value.
-     */
-    protected static String replace(String is, Map<String, String> m) {
-	String rv = "";
-	for (String tok: is.split(" ")) {
-	    String term = "";
-	    for (String s: tok.split("\\.")) {
-		String next = m.containsKey(s) ? m.get(s) : s;
-
-		if (term.isEmpty()) term = next;
-		else term += "." + next;
-	    }
-	    if (rv.isEmpty()) rv = term;
-	    else rv += " " + term;
-	}
-	return rv;
-    }
-    public static void add_mapping(String name, String key) {
-	nicknames.put(name, key);
-	keys.put(key,name);
-    }
-
-    public static boolean key_in_mapping(String key) {
-	return keys.containsKey(key);
-    }
-
-    public static boolean name_in_mapping(String name) {
-	return nicknames.containsKey(name);
-    }
-
-    public static void clear_mapping() { nicknames.clear(); keys.clear(); }
-
 }
