1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/*
2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Licensed to the Apache Software Foundation (ASF) under one or more
3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  contributor license agreements.  See the NOTICE file distributed with
4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  this work for additional information regarding copyright ownership.
5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  The ASF licenses this file to You under the Apache License, Version 2.0
6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  (the "License"); you may not use this file except in compliance with
7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  the License.  You may obtain a copy of the License at
8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *     http://www.apache.org/licenses/LICENSE-2.0
10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Unless required by applicable law or agreed to in writing, software
12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  distributed under the License is distributed on an "AS IS" BASIS,
13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  See the License for the specific language governing permissions and
15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  limitations under the License.
16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage java.security;
19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.Serializable;
21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.cert.CertPath;
22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code CodeSigner} represents a signer of code. Instances are immutable.
25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic final class CodeSigner implements Serializable {
27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final long serialVersionUID = 6819288105193937581L;
29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private CertPath signerCertPath;
31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private Timestamp timestamp;
33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // Cached hash code value
35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private transient int hash;
36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constructs a new instance of {@code CodeSigner}.
392f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes     *
40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param signerCertPath
41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the certificate path associated with this code signer.
42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param timestamp
43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the time stamp associated with this code signer, maybe {@code
44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            null}.
45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws NullPointerException
46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if {@code signerCertPath} is {@code null}.
47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public CodeSigner(CertPath signerCertPath, Timestamp timestamp) {
49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (signerCertPath == null) {
50897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes            throw new NullPointerException("signerCertPath == null");
51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.signerCertPath = signerCertPath;
53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.timestamp = timestamp;
54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Compares the specified object with this {@code CodeSigner} for equality.
58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns {@code true} if the specified object is also an instance of
59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code CodeSigner}, the two {@code CodeSigner} encapsulate the same
60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * certificate path and the same time stamp, if present in both.
612f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes     *
62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param obj
63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            object to be compared for equality with this {@code
64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            CodeSigner}.
65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if the specified object is equal to this {@code
66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         CodeSigner}, otherwise {@code false}.
67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
682f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes    @Override
69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean equals(Object obj) {
70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (obj == this) {
71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return true;
72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (obj instanceof CodeSigner) {
74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            CodeSigner that = (CodeSigner) obj;
75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (!signerCertPath.equals(that.signerCertPath)) {
76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return false;
77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return timestamp == null ? that.timestamp == null : timestamp
79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    .equals(that.timestamp);
80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return false;
82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the certificate path associated with this {@code CodeSigner}.
862f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes     *
87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the certificate path associated with this {@code CodeSigner}.
88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public CertPath getSignerCertPath() {
90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return signerCertPath;
91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the time stamp associated with this {@code CodeSigner}.
952f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes     *
96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the time stamp associated with this {@code CodeSigner}, maybe
97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         {@code null}.
98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public Timestamp getTimestamp() {
100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return timestamp;
101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the hash code value for this {@code CodeSigner}. Returns the same
105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * hash code for {@code CodeSigner}s that are equal to each other as
106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * required by the general contract of {@link Object#hashCode}.
1072f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes     *
108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the hash code value for this {@code CodeSigner}.
109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see Object#equals(Object)
110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see CodeSigner#equals(Object)
111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1122f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes    @Override
113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int hashCode() {
114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (hash == 0) {
115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            hash = signerCertPath.hashCode()
116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    ^ (timestamp == null ? 0 : timestamp.hashCode());
117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return hash;
119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns a string containing a concise, human-readable description of the
123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * this {@code CodeSigner} including its first certificate and its time
124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * stamp, if present.
1252f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes     *
126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return a printable representation for this {@code CodeSigner}.
127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1282f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes    @Override
129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public String toString() {
130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // There is no any special reason for '256' here, it's taken abruptly
1312f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes        StringBuilder buf = new StringBuilder(256);
132f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        // The javadoc says nothing, and the others implementations behavior seems as
133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // dumping only the first certificate. Well, let's do the same.
134f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        buf.append("CodeSigner [").append(signerCertPath.getCertificates().get(0));
135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if( timestamp != null ) {
136f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            buf.append("; ").append(timestamp);
137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
138f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        buf.append("]");
139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return buf.toString();
140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1412f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes}
142