source: java/net/deterlab/abac/Role.java @ 88e139a

abac0-leakabac0-meicompt_changesgec13mei-idmei-rt0-nmei_rt0mei_rt2mei_rt2_fix_1meiyap-rt1meiyap1rt2tvf-new-xml
Last change on this file since 88e139a was 88e139a, checked in by Ted Faber <faber@…>, 13 years ago

Add some basic features, comparability.

  • Property mode set to 100644
File size: 6.1 KB
Line 
1package net.deterlab.abac;
2
3import java.util.*;
4
5import org.bouncycastle.asn1.*;
6
7/**
8 * Represents a role, which is a vertex in a Credential graph.
9 */
10public class Role implements Comparable {
11    private String m_string;
12    private String[] m_parts;
13    private String m_A_r1, m_r2;
14    private String m_prefix;
15    private Role[] m_prereqs;
16
17    protected static TreeMap<String, String> nicknames = 
18        new TreeMap<String, String>();
19    protected static TreeMap<String, String> keys = 
20        new TreeMap<String, String>();
21
22    /**
23     * Create a role from a string. A single role must be of the format "A",
24     * "A.r1", or "A.r1.r2", where A is a principal and r1 and r2 are role
25     * names. This constructor also supports intersection roles: a sequence of
26     * two or more roles separated by "&amp;". The whitespace surrounding &amp;
27     * is arbitrary.
28     *
29     * If the string does not have this format, the constructor throws a
30     * RuntimeException.
31     */
32    public Role(String s) throws RuntimeException {
33        m_string = s;
34
35        // intersection roles have at least two roles separated by "&"
36        String[] isect_roles = s.split("&");
37
38        // ordinary role
39        if (isect_roles.length == 1)
40            single_role();
41
42        // intersection role: make a list of prereqs
43        else {
44            m_prereqs = new Role[isect_roles.length];
45            for (int i = 0; i < isect_roles.length; ++i)
46                m_prereqs[i] = new Role(isect_roles[i].trim()); // trim() handles arbitrary whitespace
47
48            // this make is_principal etc. work properly
49            m_parts = new String[0];
50        }
51    }
52
53    public Role(String s, boolean translate) {
54        this(translate ? replace(s, nicknames) : s);
55    }
56
57    /**
58     * Initialize a single non-intersection role. See constructor for details of
59     * role format. Will throw RuntimeException if the role is invalid.
60     */
61    private void single_role() throws RuntimeException {
62        m_parts = m_string.split("\\.");
63        if (m_parts.length > 3)
64            throw new RuntimeException("Not a valid role: " + m_string);
65
66        // linking role: prefix is A.r1 from A.r1.r2
67        if (is_linking()) {
68            m_A_r1 = m_parts[0] + "." + m_parts[1];
69            m_r2 = m_parts[2];
70            m_prefix = m_A_r1;
71        }
72
73        // role: prefix is A from A.r1
74        else if (is_role())
75            m_prefix = m_parts[0];
76
77        // principal: prefix is the whole thing
78        else
79            m_prefix = m_string;
80    }
81
82    /**
83     * Returns true iff the role is a principal.
84     */
85    public boolean is_principal() { return m_parts.length == 1; }
86
87    /**
88     * Returns true iff the role is a role (i.e., A.r1).
89     */
90    public boolean is_role() { return m_parts.length == 2; }
91
92    /**
93     * Returns true iff the role is a linking role (i.e., A.r1.r2).
94     */
95    public boolean is_linking() { return m_parts.length == 3; }
96
97    /**
98     * Returns true iff the role represents an intersection role.
99     */
100    public boolean is_intersection() { return m_prereqs != null; }
101
102    /**
103     * Returns the first two elements of a linking role's name. This typically
104     * refers to another role in the graph. This will throw a runtime
105     * exception if the node is not a linking role.
106     */
107    public String A_r1() throws RuntimeException {
108        if (!is_linking())
109            throw new RuntimeException("Not a linking role");
110        return m_A_r1;
111    }
112
113    /**
114     * Return the last element of a linking role's name. This will throw a
115     * runtime exception if the node is not a linking role.
116     */
117    public String r2() throws RuntimeException {
118        if (!is_linking())
119            throw new RuntimeException("Not a linking role");
120        return m_r2;
121    }
122
123    /**
124     * Returns the principal part of a role or principal. This is everything
125     * except the last element of the name.
126     */
127    public String principal_part() {
128        return m_prefix;
129    }
130
131    /**
132     * Returns an issuer, only the first element.
133     */
134    public String issuer_part() { return m_parts[0]; }
135
136    /**
137     * Returns true if the principal part of the name matches a prefix. This
138     * is used when filtering graphs.
139     */
140    public boolean matches(String prefix) {
141        return prefix.length() == 0 || m_prefix.equals(prefix);
142    }
143
144    /**
145     * Get the roles that form the prerequisites to this intersection. Throws
146     * a runtime exception if this is not an intersection role.
147     */
148    public Role[] prereqs() throws RuntimeException {
149        if (!is_intersection())
150            throw new RuntimeException("Not an intersection role.");
151
152        return m_prereqs;
153    }
154
155    public String toString() {
156        return m_string;
157    }
158
159    public String simpleString() {
160        return replace(m_string, keys);
161    }
162
163    public boolean equals(Object v2) {
164        if (v2 instanceof Role)
165            return m_string.equals(((Role)v2).m_string);
166        return false;
167    }
168
169    public int compareTo(Object o) {
170        if (o instanceof Role) 
171            return m_string.compareTo(((Role)o).m_string);
172        else return 1;
173    }
174
175    public int hashCode() {
176        return m_string.hashCode();
177    }
178
179
180    /**
181     * Translate either keys to nicknames or vice versa.  Break the string into
182     * space separated tokens and then each of them into period separated
183     * strings.  If any of the smallest strings is in the map, replace it with
184     * the value.
185     */
186    protected static String replace(String is, Map<String, String> m) {
187        String rv = "";
188        for (String tok: is.split(" ")) {
189            String term = "";
190            for (String s: tok.split("\\.")) {
191                String next = m.containsKey(s) ? m.get(s) : s;
192
193                if (term.isEmpty()) term = next;
194                else term += "." + next;
195            }
196            if (rv.isEmpty()) rv = term;
197            else rv += " " + term;
198        }
199        return rv;
200    }
201    public static void add_mapping(String name, String key) {
202        nicknames.put(name, key);
203        keys.put(key,name);
204    }
205
206    public static boolean key_in_mapping(String key) {
207        return keys.containsKey(key);
208    }
209
210    public static boolean name_in_mapping(String name) {
211        return nicknames.containsKey(name);
212    }
213
214    public static void clear_mapping() { nicknames.clear(); keys.clear(); }
215
216}
Note: See TracBrowser for help on using the repository browser.