1/* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package java.security.cert; 19 20import java.io.ByteArrayInputStream; 21import java.io.NotSerializableException; 22import java.io.ObjectStreamException; 23import java.io.ObjectStreamField; 24import java.io.Serializable; 25import java.util.Iterator; 26import java.util.List; 27 28import org.apache.harmony.security.internal.nls.Messages; 29 30/** 31 * An immutable certificate path that can be validated. All certificates in the 32 * path are of the same type (i.e., X509). 33 * <p> 34 * A {@code CertPath} can be represented as a byte array in at least one 35 * supported encoding scheme (i.e. PkiPath or PKCS7) when serialized. 36 * <p> 37 * When a {@code List} of the certificates is obtained it must be immutable. 38 * <p> 39 * A {@code CertPath} must be thread-safe without requiring coordinated access. 40 * 41 * @see Certificate 42 */ 43public abstract class CertPath implements Serializable { 44 45 private static final long serialVersionUID = 6068470306649138683L; 46 // Standard name of the type of certificates in this path 47 private final String type; 48 49 /** 50 * Creates a new {@code CertPath} instance for the specified certificate 51 * type. 52 * 53 * @param type 54 * the certificate type. 55 */ 56 protected CertPath(String type) { 57 this.type = type; 58 } 59 60 /** 61 * Returns the type of {@code Certificate} in this instance. 62 * 63 * @return the certificate type. 64 */ 65 public String getType() { 66 return type; 67 } 68 69 /** 70 * Returns {@code true} if {@code Certificate}s in the list are the same 71 * type and the lists are equal (and by implication the certificates 72 * contained within are the same). 73 * 74 * @param other 75 * {@code CertPath} to be compared for equality. 76 * @return {@code true} if the object are equal, {@code false} otherwise. 77 */ 78 public boolean equals(Object other) { 79 if (this == other) { 80 return true; 81 } 82 if (other instanceof CertPath) { 83 CertPath o = (CertPath)other; 84 if (getType().equals(o.getType())) { 85 if (getCertificates().equals(o.getCertificates())) { 86 return true; 87 } 88 } 89 } 90 return false; 91 } 92 93 /** 94 * Overrides {@code Object.hashCode()}. The function is defined as follows: 95 * <pre> 96 * {@code hashCode = 31 * path.getType().hashCode() + 97 * path.getCertificates().hashCode();} 98 * </pre> 99 * 100 * @return the hash code for this instance. 101 */ 102 public int hashCode() { 103 int hash = getType().hashCode(); 104 hash = hash*31 + getCertificates().hashCode(); 105 return hash; 106 } 107 108 /** 109 * Returns a {@code String} representation of this {@code CertPath} 110 * instance. It is the result of calling {@code toString} on all {@code 111 * Certificate}s in the {@code List}. 112 * 113 * @return a string representation of this instance. 114 */ 115 public String toString() { 116 StringBuilder sb = new StringBuilder(getType()); 117 sb.append(" Cert Path, len="); //$NON-NLS-1$ 118 sb.append(getCertificates().size()); 119 sb.append(": [\n"); //$NON-NLS-1$ 120 int n=1; 121 // BEGIN android-changed 122 for (Iterator<? extends Certificate> i=getCertificates().iterator(); 123 i.hasNext(); n++) { 124 sb.append("---------------certificate "); //$NON-NLS-1$ 125 sb.append(n); 126 sb.append("---------------\n"); //$NON-NLS-1$ 127 sb.append(((Certificate)i.next()).toString()); 128 } 129 // END android-changed 130 sb.append("\n]"); //$NON-NLS-1$ 131 return sb.toString(); 132 } 133 134 /** 135 * Returns an immutable List of the {@code Certificate}s contained 136 * in the {@code CertPath}. 137 * 138 * @return a list of {@code Certificate}s in the {@code CertPath}. 139 */ 140 public abstract List<? extends Certificate> getCertificates(); 141 142 /** 143 * Returns an encoding of the {@code CertPath} using the default encoding. 144 * 145 * @return default encoding of the {@code CertPath}. 146 * @throws CertificateEncodingException 147 * if the encoding fails. 148 */ 149 public abstract byte[] getEncoded() 150 throws CertificateEncodingException; 151 152 /** 153 * Returns an encoding of the {@code CertPath} using the specified encoding. 154 * 155 * @param encoding 156 * encoding that should be generated. 157 * @return default encoding of the {@code CertPath}. 158 * @throws CertificateEncodingException 159 * if the encoding fails. 160 */ 161 public abstract byte[] getEncoded(String encoding) 162 throws CertificateEncodingException; 163 164 /** 165 * Returns an {@code Iterator} over the supported encodings for a 166 * representation of the certificate path. 167 * 168 * @return {@code Iterator} over supported encodings (as {@code String}s). 169 */ 170 public abstract Iterator<String> getEncodings(); 171 172 /** 173 * Returns an alternate object to be serialized. 174 * 175 * @return an alternate object to be serialized. 176 * @throws ObjectStreamException 177 * if the creation of the alternate object fails. 178 */ 179 protected Object writeReplace() throws ObjectStreamException { 180 try { 181 return new CertPathRep(getType(), getEncoded()); 182 } catch (CertificateEncodingException e) { 183 throw new NotSerializableException ( 184 Messages.getString("security.66", e)); //$NON-NLS-1$ 185 } 186 } 187 188 /** 189 * The alternate {@code Serializable} class to be used for serialization and 190 * deserialization on {@code CertPath} objects. 191 */ 192 protected static class CertPathRep implements Serializable { 193 194 private static final long serialVersionUID = 3015633072427920915L; 195 // Standard name of the type of certificates in this path 196 private final String type; 197 // cert path data 198 private final byte[] data; 199 200 // Force default serialization to use writeUnshared/readUnshared 201 // for cert path data 202 private static final ObjectStreamField[] serialPersistentFields = { 203 new ObjectStreamField("type", String.class), //$NON-NLS-1$ 204 new ObjectStreamField("data", byte[].class, true) //$NON-NLS-1$ 205 }; 206 207 /** 208 * Creates a new {@code CertPathRep} instance with the specified type 209 * and encoded data. 210 * 211 * @param type 212 * the certificate type. 213 * @param data 214 * the encoded data. 215 */ 216 protected CertPathRep(String type, byte[] data) { 217 this.type = type; 218 this.data = data; 219 } 220 221 /** 222 * Deserializes a {@code CertPath} from a serialized {@code CertPathRep} 223 * object. 224 * 225 * @return the deserialized {@code CertPath}. 226 * @throws ObjectStreamException 227 * if deserialization fails. 228 */ 229 protected Object readResolve() throws ObjectStreamException { 230 try { 231 CertificateFactory cf = CertificateFactory.getInstance(type); 232 return cf.generateCertPath(new ByteArrayInputStream(data)); 233 } catch (Throwable t) { 234 throw new NotSerializableException( 235 Messages.getString("security.67", t)); //$NON-NLS-1$ 236 } 237 } 238 } 239} 240