Source code: jsdsi/Name.java
1 /*
2 * Copyright 2002 Massachusetts Institute of Technology
3 *
4 * Permission to use, copy, modify, and distribute this program for any
5 * purpose and without fee is hereby granted, provided that this
6 * copyright and permission notice appear on all copies and supporting
7 * documentation, the name of M.I.T. not be used in advertising or
8 * publicity pertaining to distribution of the program without specific
9 * prior permission, and notice be given in supporting documentation that
10 * copying and distribution is by permission of M.I.T. M.I.T. makes no
11 * representations about the suitability of this software for any
12 * purpose. It is provided "as is" without express or implied warranty.
13 */
14 package jsdsi;
15
16 import java.util.ArrayList;
17 import java.util.Iterator;
18 import java.util.List;
19
20 import jsdsi.sexp.*;
21
22 /**
23 * A SDSI name: a principal and a sequence of strings. If the sequence
24 * contains just one string, this is a local name; otherwise this is an
25 * extended name.
26 *
27 * @author Sameer Ajmani
28 * @version $Revision: 1.2 $ $Date: 2003/04/22 21:37:44 $
29 */
30 public class Name extends Obj implements Subject {
31 /**
32 * Principal of this Name.
33 */
34 private final Principal issuer;
35
36 /**
37 * The name string(s) for this name (more than one string for an extended
38 * name).
39 */
40 private final String[] names;
41
42 /**
43 * Creates a new <code>Name</code> for a given principal and an array
44 * of name-strings.
45 *
46 * @param i principal to create the <code>Name</code> for.
47 * @param n array of string-names for this <code>Name</code> (if the
48 * length of <code>n</code> is greater than 1, an extended name
49 * will be created).
50 */
51 public Name(Principal i, String[] n) {
52 assert(i != null) : "null issuer";
53 assert(n != null) : "null names";
54 assert(n.length > 0) : "empty names";
55 issuer = i;
56 names = n;
57 }
58
59 /**
60 * Creates a new local name from a given principal and name-string.
61 *
62 * @param i principal to create the <code>Name</code> for.
63 * @param n name-string to create the <code>Name</code> for.
64 */
65 public Name(Principal i, String n) {
66 this(i, new String[] { n }); // XXX assert n != null
67 }
68
69 /**
70 * Returns the principal of the <code>Name</code>.
71 *
72 * @return the principal of this <code>Name</code>.
73 */
74 public Principal getIssuer() {
75 return issuer;
76 }
77
78 /**
79 * Returns an array of name-strings of this <code>Name</code> (the array
80 * has a length of one in the case of a local name, and greater then 1 for
81 * extended names).
82 *
83 * @return an array of strings containing the name-string(s) of this name
84 * (more than one string for an extended string).
85 */
86 public String[] getNames() {
87 return names;
88 }
89
90 /**
91 * Checks if a given <code>Name</code> has the same issuer (principal) as
92 * this <code>Name</code> and if the name-strings are equal to this name's
93 * name-strings (a smaller number of name-strings are okay).
94 *
95 * @param n <code>Name</code> to compare with this <code>Name</code>.
96 * @return <code>false</code> if <code>n</code> has another issuer, a
97 * greater number of name-strings or if one name-string is not
98 * equal if a name-string from this <code>Name</code>, returns
99 * <code>true</code> otherwise.
100 */
101 public boolean prefixOf(Name n) {
102 if (!issuer.equals(n.issuer)) {
103 return false;
104 }
105 if (names.length > n.names.length) {
106 return false;
107 }
108 for (int i = 0; i < names.length; i++) {
109 if (!names[i].equals(n.names[i])) {
110 return false;
111 }
112 }
113 return true;
114 }
115
116 /**
117 * Creates a new <code>Name</code> from this <code>Name</code> using only
118 * the first <code>i</code> name-strings.
119 *
120 * @param i number of name-strings of this <code>Name</code> to use for
121 * creating a new <code>Name</code>.
122 * @return the new <code>Name</code> for the same principal as this
123 * <code>Name</code> using only the first <code>i</code>
124 * name-strings.
125 */
126 public Name prefix(int i) {
127 assert(i <= names.length) : "prefix too long";
128 String[] ns = new String[i];
129 System.arraycopy(names, 0, ns, 0, i);
130 return new Name(issuer, ns);
131 }
132
133 /**
134 * Returns the local name of this name, that is a <code>Name</code> for
135 * this <code>Name</code>s issuer with the first name-string of the list
136 * of names.
137 *
138 * @return the new local name for this <code>Name</code>.
139 */
140 public Name prefix() {
141 return prefix(1);
142 }
143
144 /**
145 * @see java.lang.Object#equals(Object)
146 */
147 public boolean equals(Object o) {
148 if (o instanceof Name) {
149 Name n = (Name) o;
150 return issuer.equals(n.issuer) && Util.equals(names, n.names);
151 }
152 return false;
153 }
154
155 /**
156 * @see java.lang.Object#hashCode()
157 */
158 public int hashCode() {
159 return issuer.hashCode() ^ Util.hashCode(names);
160 }
161
162 public SexpList toSexp() {
163 // TODO: implement this method
164 return toSexp((Principal) null);
165 }
166
167 /**
168 * Returns an <code>SexpList</code>-representation of the given
169 * <code>Principal</code>.
170 *
171 * @param iss the <code>Principal</code> to create an
172 * <code>SexpList</code> from.
173 * @return an <code>SexpList</code>-representation of <code>iss</code>.
174 */
175 public SexpList toSexp(Principal iss) {
176 List l = new ArrayList();
177 if (!getIssuer().samePrincipalAs(iss)) {
178 // make fully-qualified name
179 l.add(getIssuer().toSexp());
180 }
181 for (int i = 0; i < names.length; i++) {
182 l.add(SexpUtil.toSexp(names[i]));
183 }
184 return SexpUtil.toSexp("name", l);
185 }
186
187 /**
188 * Parses an <code>SexpList</code> to create a <code>Name</code>
189 * from it.
190 *
191 * @param l the <code>SexpList</code> that holds a <code>Name</code>.
192 * @return a <code>Name</code> created from the values in <code>l</code>
193 * @throws SexpParseException
194 */
195 static Name parseName(SexpList l) throws SexpParseException {
196 return parseName(l, null);
197 }
198
199 /**
200 * Parses a name from a given <code>SexpList</code> and
201 * <code>Principal</code>.
202 *
203 * @param l the <code>SexpList</code> to parse.
204 * @param issuerParam the <code>Principal</code> that is the issuer
205 * of the <code>Name</code>.
206 * @return the <code>Name</code> created from <code>l</code> and
207 * <code>issuerParm</code>.
208 * @throws SexpParseException
209 */
210 static Name parseName(SexpList l, Principal issuerParam)
211 throws SexpParseException {
212 Iterator nbody = SexpUtil.getBody(l);
213 Sexp s = SexpUtil.getNext(nbody, "first name component");
214 Principal issuer = null;
215 String[] names = null;
216 if (s instanceof SexpList) {
217 // name is fully-qualified
218 issuer = Principal.parsePrincipal(SexpUtil.getList(s));
219 names = new String[l.size() - 2];
220 for (int i = 0; i < names.length; i++) {
221 names[i] = SexpUtil.getNextString(nbody, "name string #" + i);
222 }
223 } else if (issuerParam != null) {
224 // name is relative; issuer provided as a parameter
225 issuer = issuerParam;
226 names = new String[l.size() - 1];
227 names[0] = SexpUtil.getString(s);
228 for (int i = 1; i < names.length; i++) {
229 names[i] = SexpUtil.getNextString(nbody, "name string #" + i);
230 }
231 } else {
232 throw new SexpParseException("relative name used without issuer");
233 }
234 SexpUtil.checkDone(nbody, "name"); // sanity check
235 return new Name(issuer, names);
236 }
237
238 // TODO: boolean sameNameAs(Name n)
239 // TODO: boolean sameNameAs(Principal i, String n)
240 }