blob: 9534429ff2e6e0d68d2711fc738679ac7a953a79 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package java.security.cert;
27
28import java.io.ByteArrayInputStream;
29import java.io.NotSerializableException;
30import java.io.ObjectStreamException;
31import java.io.Serializable;
32import java.util.Iterator;
33import java.util.List;
34
35/**
36 * An immutable sequence of certificates (a certification path).
37 * <p>
38 * This is an abstract class that defines the methods common to all
39 * <code>CertPath</code>s. Subclasses can handle different kinds of
40 * certificates (X.509, PGP, etc.).
41 * <p>
42 * All <code>CertPath</code> objects have a type, a list of
43 * <code>Certificate</code>s, and one or more supported encodings. Because the
44 * <code>CertPath</code> class is immutable, a <code>CertPath</code> cannot
45 * change in any externally visible way after being constructed. This
46 * stipulation applies to all public fields and methods of this class and any
47 * added or overridden by subclasses.
48 * <p>
49 * The type is a <code>String</code> that identifies the type of
50 * <code>Certificate</code>s in the certification path. For each
51 * certificate <code>cert</code> in a certification path <code>certPath</code>,
52 * <code>cert.getType().equals(certPath.getType())</code> must be
53 * <code>true</code>.
54 * <p>
55 * The list of <code>Certificate</code>s is an ordered <code>List</code> of
56 * zero or more <code>Certificate</code>s. This <code>List</code> and all
57 * of the <code>Certificate</code>s contained in it must be immutable.
58 * <p>
59 * Each <code>CertPath</code> object must support one or more encodings
60 * so that the object can be translated into a byte array for storage or
61 * transmission to other parties. Preferably, these encodings should be
62 * well-documented standards (such as PKCS#7). One of the encodings supported
63 * by a <code>CertPath</code> is considered the default encoding. This
64 * encoding is used if no encoding is explicitly requested (for the
65 * {@link #getEncoded() getEncoded()} method, for instance).
66 * <p>
67 * All <code>CertPath</code> objects are also <code>Serializable</code>.
68 * <code>CertPath</code> objects are resolved into an alternate
69 * {@link CertPathRep CertPathRep} object during serialization. This allows
70 * a <code>CertPath</code> object to be serialized into an equivalent
71 * representation regardless of its underlying implementation.
72 * <p>
73 * <code>CertPath</code> objects can be created with a
74 * <code>CertificateFactory</code> or they can be returned by other classes,
75 * such as a <code>CertPathBuilder</code>.
76 * <p>
77 * By convention, X.509 <code>CertPath</code>s (consisting of
78 * <code>X509Certificate</code>s), are ordered starting with the target
79 * certificate and ending with a certificate issued by the trust anchor. That
80 * is, the issuer of one certificate is the subject of the following one. The
81 * certificate representing the {@link TrustAnchor TrustAnchor} should not be
82 * included in the certification path. Unvalidated X.509 <code>CertPath</code>s
83 * may not follow these conventions. PKIX <code>CertPathValidator</code>s will
84 * detect any departure from these conventions that cause the certification
85 * path to be invalid and throw a <code>CertPathValidatorException</code>.
86 * <p>
87 * <b>Concurrent Access</b>
88 * <p>
89 * All <code>CertPath</code> objects must be thread-safe. That is, multiple
90 * threads may concurrently invoke the methods defined in this class on a
91 * single <code>CertPath</code> object (or more than one) with no
92 * ill effects. This is also true for the <code>List</code> returned by
93 * <code>CertPath.getCertificates</code>.
94 * <p>
95 * Requiring <code>CertPath</code> objects to be immutable and thread-safe
96 * allows them to be passed around to various pieces of code without worrying
97 * about coordinating access. Providing this thread-safety is
98 * generally not difficult, since the <code>CertPath</code> and
99 * <code>List</code> objects in question are immutable.
100 *
101 * @see CertificateFactory
102 * @see CertPathBuilder
103 *
104 * @author Yassir Elley
105 * @since 1.4
106 */
107public abstract class CertPath implements Serializable {
108
109 private static final long serialVersionUID = 6068470306649138683L;
110
111 private String type; // the type of certificates in this chain
112
113 /**
114 * Creates a <code>CertPath</code> of the specified type.
115 * <p>
116 * This constructor is protected because most users should use a
117 * <code>CertificateFactory</code> to create <code>CertPath</code>s.
118 *
119 * @param type the standard name of the type of
120 * <code>Certificate</code>s in this path
121 */
122 protected CertPath(String type) {
123 this.type = type;
124 }
125
126 /**
127 * Returns the type of <code>Certificate</code>s in this certification
128 * path. This is the same string that would be returned by
129 * {@link java.security.cert.Certificate#getType() cert.getType()}
130 * for all <code>Certificate</code>s in the certification path.
131 *
132 * @return the type of <code>Certificate</code>s in this certification
133 * path (never null)
134 */
135 public String getType() {
136 return type;
137 }
138
139 /**
140 * Returns an iteration of the encodings supported by this certification
141 * path, with the default encoding first. Attempts to modify the returned
142 * <code>Iterator</code> via its <code>remove</code> method result in an
143 * <code>UnsupportedOperationException</code>.
144 *
145 * @return an <code>Iterator</code> over the names of the supported
146 * encodings (as Strings)
147 */
148 public abstract Iterator<String> getEncodings();
149
150 /**
151 * Compares this certification path for equality with the specified
152 * object. Two <code>CertPath</code>s are equal if and only if their
153 * types are equal and their certificate <code>List</code>s (and by
154 * implication the <code>Certificate</code>s in those <code>List</code>s)
155 * are equal. A <code>CertPath</code> is never equal to an object that is
156 * not a <code>CertPath</code>.
157 * <p>
158 * This algorithm is implemented by this method. If it is overridden,
159 * the behavior specified here must be maintained.
160 *
161 * @param other the object to test for equality with this certification path
162 * @return true if the specified object is equal to this certification path,
163 * false otherwise
164 */
165 public boolean equals(Object other) {
166 if (this == other)
167 return true;
168
169 if (! (other instanceof CertPath))
170 return false;
171
172 CertPath otherCP = (CertPath) other;
173 if (! otherCP.getType().equals(type))
174 return false;
175
176 List<? extends Certificate> thisCertList = this.getCertificates();
177 List<? extends Certificate> otherCertList = otherCP.getCertificates();
178 return(thisCertList.equals(otherCertList));
179 }
180
181 /**
182 * Returns the hashcode for this certification path. The hash code of
183 * a certification path is defined to be the result of the following
184 * calculation:
185 * <pre><code>
186 * hashCode = path.getType().hashCode();
187 * hashCode = 31*hashCode + path.getCertificates().hashCode();
188 * </code></pre>
189 * This ensures that <code>path1.equals(path2)</code> implies that
190 * <code>path1.hashCode()==path2.hashCode()</code> for any two certification
191 * paths, <code>path1</code> and <code>path2</code>, as required by the
192 * general contract of <code>Object.hashCode</code>.
193 *
194 * @return the hashcode value for this certification path
195 */
196 public int hashCode() {
197 int hashCode = type.hashCode();
198 hashCode = 31*hashCode + getCertificates().hashCode();
199 return hashCode;
200 }
201
202 /**
203 * Returns a string representation of this certification path.
204 * This calls the <code>toString</code> method on each of the
205 * <code>Certificate</code>s in the path.
206 *
207 * @return a string representation of this certification path
208 */
209 public String toString() {
210 StringBuffer sb = new StringBuffer();
211 Iterator<? extends Certificate> stringIterator =
212 getCertificates().iterator();
213
214 sb.append("\n" + type + " Cert Path: length = "
215 + getCertificates().size() + ".\n");
216 sb.append("[\n");
217 int i = 1;
218 while (stringIterator.hasNext()) {
219 sb.append("=========================================="
220 + "===============Certificate " + i + " start.\n");
221 Certificate stringCert = stringIterator.next();
222 sb.append(stringCert.toString());
223 sb.append("\n========================================"
224 + "=================Certificate " + i + " end.\n\n\n");
225 i++;
226 }
227
228 sb.append("\n]");
229 return sb.toString();
230 }
231
232 /**
233 * Returns the encoded form of this certification path, using the default
234 * encoding.
235 *
236 * @return the encoded bytes
237 * @exception CertificateEncodingException if an encoding error occurs
238 */
239 public abstract byte[] getEncoded()
240 throws CertificateEncodingException;
241
242 /**
243 * Returns the encoded form of this certification path, using the
244 * specified encoding.
245 *
246 * @param encoding the name of the encoding to use
247 * @return the encoded bytes
248 * @exception CertificateEncodingException if an encoding error occurs or
249 * the encoding requested is not supported
250 */
251 public abstract byte[] getEncoded(String encoding)
252 throws CertificateEncodingException;
253
254 /**
255 * Returns the list of certificates in this certification path.
256 * The <code>List</code> returned must be immutable and thread-safe.
257 *
258 * @return an immutable <code>List</code> of <code>Certificate</code>s
259 * (may be empty, but not null)
260 */
261 public abstract List<? extends Certificate> getCertificates();
262
263 /**
264 * Replaces the <code>CertPath</code> to be serialized with a
265 * <code>CertPathRep</code> object.
266 *
267 * @return the <code>CertPathRep</code> to be serialized
268 *
269 * @throws ObjectStreamException if a <code>CertPathRep</code> object
270 * representing this certification path could not be created
271 */
272 protected Object writeReplace() throws ObjectStreamException {
273 try {
274 return new CertPathRep(type, getEncoded());
275 } catch (CertificateException ce) {
276 NotSerializableException nse =
277 new NotSerializableException
278 ("java.security.cert.CertPath: " + type);
279 nse.initCause(ce);
280 throw nse;
281 }
282 }
283
284 /**
285 * Alternate <code>CertPath</code> class for serialization.
286 * @since 1.4
287 */
288 protected static class CertPathRep implements Serializable {
289
290 private static final long serialVersionUID = 3015633072427920915L;
291
292 /** The Certificate type */
293 private String type;
294 /** The encoded form of the cert path */
295 private byte[] data;
296
297 /**
298 * Creates a <code>CertPathRep</code> with the specified
299 * type and encoded form of a certification path.
300 *
301 * @param type the standard name of a <code>CertPath</code> type
302 * @param data the encoded form of the certification path
303 */
304 protected CertPathRep(String type, byte[] data) {
305 this.type = type;
306 this.data = data;
307 }
308
309 /**
310 * Returns a <code>CertPath</code> constructed from the type and data.
311 *
312 * @return the resolved <code>CertPath</code> object
313 *
314 * @throws ObjectStreamException if a <code>CertPath</code> could not
315 * be constructed
316 */
317 protected Object readResolve() throws ObjectStreamException {
318 try {
319 CertificateFactory cf = CertificateFactory.getInstance(type);
320 return cf.generateCertPath(new ByteArrayInputStream(data));
321 } catch (CertificateException ce) {
322 NotSerializableException nse =
323 new NotSerializableException
324 ("java.security.cert.CertPath: " + type);
325 nse.initCause(ce);
326 throw nse;
327 }
328 }
329 }
330}