| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package java.security.cert; |
| |
| import java.io.ByteArrayInputStream; |
| import java.io.NotSerializableException; |
| import java.io.ObjectStreamException; |
| import java.io.ObjectStreamField; |
| import java.io.Serializable; |
| import java.util.Iterator; |
| import java.util.List; |
| |
| /** |
| * An immutable certificate path that can be validated. All certificates in the |
| * path are of the same type (i.e., X509). |
| * <p> |
| * A {@code CertPath} can be represented as a byte array in at least one |
| * supported encoding scheme (i.e. PkiPath or PKCS7) when serialized. |
| * <p> |
| * When a {@code List} of the certificates is obtained it must be immutable. |
| * <p> |
| * A {@code CertPath} must be thread-safe without requiring coordinated access. |
| * |
| * @see Certificate |
| */ |
| public abstract class CertPath implements Serializable { |
| |
| private static final long serialVersionUID = 6068470306649138683L; |
| // Standard name of the type of certificates in this path |
| private final String type; |
| |
| /** |
| * Creates a new {@code CertPath} instance for the specified certificate |
| * type. |
| * |
| * @param type |
| * the certificate type. |
| */ |
| protected CertPath(String type) { |
| this.type = type; |
| } |
| |
| /** |
| * Returns the type of {@code Certificate} in this instance. |
| * |
| * @return the certificate type. |
| */ |
| public String getType() { |
| return type; |
| } |
| |
| /** |
| * Returns {@code true} if {@code Certificate}s in the list are the same |
| * type and the lists are equal (and by implication the certificates |
| * contained within are the same). |
| * |
| * @param other |
| * {@code CertPath} to be compared for equality. |
| * @return {@code true} if the object are equal, {@code false} otherwise. |
| */ |
| public boolean equals(Object other) { |
| if (this == other) { |
| return true; |
| } |
| if (other instanceof CertPath) { |
| CertPath o = (CertPath)other; |
| if (getType().equals(o.getType())) { |
| if (getCertificates().equals(o.getCertificates())) { |
| return true; |
| } |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Overrides {@code Object.hashCode()}. The function is defined as follows: |
| * <pre> |
| * {@code hashCode = 31 * path.getType().hashCode() + |
| * path.getCertificates().hashCode();} |
| * </pre> |
| * |
| * @return the hash code for this instance. |
| */ |
| public int hashCode() { |
| int hash = getType().hashCode(); |
| hash = hash*31 + getCertificates().hashCode(); |
| return hash; |
| } |
| |
| /** |
| * Returns a {@code String} representation of this {@code CertPath} |
| * instance. It is the result of calling {@code toString} on all {@code |
| * Certificate}s in the {@code List}. |
| * |
| * @return a string representation of this instance. |
| */ |
| public String toString() { |
| StringBuilder sb = new StringBuilder(getType()); |
| sb.append(" Cert Path, len="); |
| sb.append(getCertificates().size()); |
| sb.append(": [\n"); |
| int n=1; |
| for (Iterator<? extends Certificate> i=getCertificates().iterator(); i.hasNext(); n++) { |
| sb.append("---------------certificate "); |
| sb.append(n); |
| sb.append("---------------\n"); |
| sb.append(((Certificate)i.next()).toString()); |
| } |
| sb.append("\n]"); |
| return sb.toString(); |
| } |
| |
| /** |
| * Returns an immutable List of the {@code Certificate}s contained |
| * in the {@code CertPath}. |
| * |
| * @return a list of {@code Certificate}s in the {@code CertPath}. |
| */ |
| public abstract List<? extends Certificate> getCertificates(); |
| |
| /** |
| * Returns an encoding of the {@code CertPath} using the default encoding. |
| * |
| * @return default encoding of the {@code CertPath}. |
| * @throws CertificateEncodingException |
| * if the encoding fails. |
| */ |
| public abstract byte[] getEncoded() |
| throws CertificateEncodingException; |
| |
| /** |
| * Returns an encoding of the {@code CertPath} using the specified encoding. |
| * |
| * @param encoding |
| * encoding that should be generated. |
| * @return default encoding of the {@code CertPath}. |
| * @throws CertificateEncodingException |
| * if the encoding fails. |
| */ |
| public abstract byte[] getEncoded(String encoding) |
| throws CertificateEncodingException; |
| |
| /** |
| * Returns an {@code Iterator} over the supported encodings for a |
| * representation of the certificate path. |
| * |
| * @return {@code Iterator} over supported encodings (as {@code String}s). |
| */ |
| public abstract Iterator<String> getEncodings(); |
| |
| /** |
| * Returns an alternate object to be serialized. |
| * |
| * @return an alternate object to be serialized. |
| * @throws ObjectStreamException |
| * if the creation of the alternate object fails. |
| */ |
| protected Object writeReplace() throws ObjectStreamException { |
| try { |
| return new CertPathRep(getType(), getEncoded()); |
| } catch (CertificateEncodingException e) { |
| throw new NotSerializableException("Could not create serialization object: " + e); |
| } |
| } |
| |
| /** |
| * The alternate {@code Serializable} class to be used for serialization and |
| * deserialization on {@code CertPath} objects. |
| */ |
| protected static class CertPathRep implements Serializable { |
| |
| private static final long serialVersionUID = 3015633072427920915L; |
| // Standard name of the type of certificates in this path |
| private final String type; |
| // cert path data |
| private final byte[] data; |
| |
| // Force default serialization to use writeUnshared/readUnshared |
| // for cert path data |
| private static final ObjectStreamField[] serialPersistentFields = { |
| new ObjectStreamField("type", String.class), |
| new ObjectStreamField("data", byte[].class, true), |
| }; |
| |
| /** |
| * Creates a new {@code CertPathRep} instance with the specified type |
| * and encoded data. |
| * |
| * @param type |
| * the certificate type. |
| * @param data |
| * the encoded data. |
| */ |
| protected CertPathRep(String type, byte[] data) { |
| this.type = type; |
| this.data = data; |
| } |
| |
| /** |
| * Deserializes a {@code CertPath} from a serialized {@code CertPathRep} |
| * object. |
| * |
| * @return the deserialized {@code CertPath}. |
| * @throws ObjectStreamException |
| * if deserialization fails. |
| */ |
| protected Object readResolve() throws ObjectStreamException { |
| try { |
| CertificateFactory cf = CertificateFactory.getInstance(type); |
| return cf.generateCertPath(new ByteArrayInputStream(data)); |
| } catch (Throwable t) { |
| throw new NotSerializableException("Could not resolve cert path: " + t); |
| } |
| } |
| } |
| } |