1/*
2 * Copyright (c) 2003, 2011, Oracle and/or its affiliates. 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.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package java.security;
27
28import java.io.*;
29import java.security.cert.Certificate;
30import java.security.cert.CertPath;
31import java.security.cert.X509Extension;
32import java.util.Date;
33import java.util.List;
34
35/**
36 * This class encapsulates information about a signed timestamp.
37 * It is immutable.
38 * It includes the timestamp's date and time as well as information about the
39 * Timestamping Authority (TSA) which generated and signed the timestamp.
40 *
41 * @since 1.5
42 * @author Vincent Ryan
43 */
44
45public final class Timestamp implements Serializable {
46
47    private static final long serialVersionUID = -5502683707821851294L;
48
49    /**
50     * The timestamp's date and time
51     *
52     * @serial
53     */
54    private Date timestamp;
55
56    /**
57     * The TSA's certificate path.
58     *
59     * @serial
60     */
61    private CertPath signerCertPath;
62
63    /*
64     * Hash code for this timestamp.
65     */
66    private transient int myhash = -1;
67
68    /**
69     * Constructs a Timestamp.
70     *
71     * @param timestamp is the timestamp's date and time. It must not be null.
72     * @param signerCertPath is the TSA's certificate path. It must not be null.
73     * @throws NullPointerException if timestamp or signerCertPath is null.
74     */
75    public Timestamp(Date timestamp, CertPath signerCertPath) {
76        if (timestamp == null || signerCertPath == null) {
77            throw new NullPointerException();
78        }
79        this.timestamp = new Date(timestamp.getTime()); // clone
80        this.signerCertPath = signerCertPath;
81    }
82
83    /**
84     * Returns the date and time when the timestamp was generated.
85     *
86     * @return The timestamp's date and time.
87     */
88    public Date getTimestamp() {
89        return new Date(timestamp.getTime()); // clone
90    }
91
92    /**
93     * Returns the certificate path for the Timestamping Authority.
94     *
95     * @return The TSA's certificate path.
96     */
97    public CertPath getSignerCertPath() {
98        return signerCertPath;
99    }
100
101    /**
102     * Returns the hash code value for this timestamp.
103     * The hash code is generated using the date and time of the timestamp
104     * and the TSA's certificate path.
105     *
106     * @return a hash code value for this timestamp.
107     */
108    public int hashCode() {
109        if (myhash == -1) {
110            myhash = timestamp.hashCode() + signerCertPath.hashCode();
111        }
112        return myhash;
113    }
114
115    /**
116     * Tests for equality between the specified object and this
117     * timestamp. Two timestamps are considered equal if the date and time of
118     * their timestamp's and their signer's certificate paths are equal.
119     *
120     * @param obj the object to test for equality with this timestamp.
121     *
122     * @return true if the timestamp are considered equal, false otherwise.
123     */
124    public boolean equals(Object obj) {
125        if (obj == null || (!(obj instanceof Timestamp))) {
126            return false;
127        }
128        Timestamp that = (Timestamp)obj;
129
130        if (this == that) {
131            return true;
132        }
133        return (timestamp.equals(that.getTimestamp()) &&
134            signerCertPath.equals(that.getSignerCertPath()));
135    }
136
137    /**
138     * Returns a string describing this timestamp.
139     *
140     * @return A string comprising the date and time of the timestamp and
141     *         its signer's certificate.
142     */
143    public String toString() {
144        StringBuffer sb = new StringBuffer();
145        sb.append("(");
146        sb.append("timestamp: " + timestamp);
147        List<? extends Certificate> certs = signerCertPath.getCertificates();
148        if (!certs.isEmpty()) {
149            sb.append("TSA: " + certs.get(0));
150        } else {
151            sb.append("TSA: <empty>");
152        }
153        sb.append(")");
154        return sb.toString();
155    }
156
157    // Explicitly reset hash code value to -1
158    private void readObject(ObjectInputStream ois)
159        throws IOException, ClassNotFoundException {
160        ois.defaultReadObject();
161        myhash = -1;
162        timestamp = new Date(timestamp.getTime());
163    }
164}
165