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;
19
20import java.io.Serializable;
21import java.security.cert.CertPath;
22import java.util.Date;
23
24/**
25 * {@code Timestamp} represents a signed time stamp. {@code Timestamp} is
26 * immutable.
27 */
28public final class Timestamp implements Serializable {
29
30    private static final long serialVersionUID = -5502683707821851294L;
31
32    private Date timestamp;
33
34    private CertPath signerCertPath;
35
36    // Cached hash
37    private transient int hash;
38
39    /**
40     * Constructs a new instance of {@code Timestamp} with the specified {@code
41     * timestamp} and the given certificate path.
42     *
43     * @param timestamp
44     *            date and time.
45     * @param signerCertPath
46     *            the certificate path.
47     * @throws NullPointerException
48     *             if {@code timestamp} is {@code null} or if {@code
49     *             signerCertPath} is {@code null}.
50     */
51    public Timestamp(Date timestamp, CertPath signerCertPath) {
52        if (timestamp == null) {
53            throw new NullPointerException("timestamp == null");
54        }
55        if (signerCertPath == null) {
56            throw new NullPointerException("signerCertPath == null");
57        }
58        // Clone timestamp to prevent modifications
59        this.timestamp = new Date(timestamp.getTime());
60        this.signerCertPath = signerCertPath;
61    }
62
63    /**
64     * Compares the specified object with this {@code Timestamp} for equality
65     * and returns {@code true} if the specified object is equal, {@code false}
66     * otherwise. The given object is equal to this {@code Timestamp}, if it is
67     * an instance of {@code Timestamp}, the two timestamps have an equal date
68     * and time and their certificate paths are equal.
69     *
70     * @param obj
71     *            object to be compared for equality with this {@code
72     *            Timestamp}.
73     * @return {@code true} if the specified object is equal to this {@code
74     *         Timestamp}, otherwise {@code false}.
75     * @see #hashCode
76     */
77    @Override
78    public boolean equals(Object obj) {
79        if (obj == this) {
80            return true;
81        }
82        if (obj instanceof Timestamp) {
83            Timestamp that = (Timestamp) obj;
84            return timestamp.equals(that.timestamp)
85                    && signerCertPath.equals(that.signerCertPath);
86        }
87        return false;
88    }
89
90    /**
91     * Returns the certificate path of this {@code Timestamp}.
92     *
93     * @return the certificate path of this {@code Timestamp}.
94     */
95    public CertPath getSignerCertPath() {
96        return signerCertPath;
97    }
98
99    /**
100     * Returns the date and time of this {@code Timestamp}.
101     *
102     * @return the date and time of this {@code Timestamp}.
103     */
104    public Date getTimestamp() {
105        return (Date) timestamp.clone();
106    }
107
108    /**
109     * Returns the hash code value for this {@code Timestamp}. Returns the same
110     * hash code for {@code Timestamp}s that are equal to each other as
111     * required by the general contract of {@link Object#hashCode}.
112     *
113     * @return the hash code value for this {@code Timestamp}.
114     * @see Object#equals(Object)
115     * @see Timestamp#equals(Object)
116     */
117    @Override
118    public int hashCode() {
119        if (hash == 0) {
120            hash = timestamp.hashCode() ^ signerCertPath.hashCode();
121        }
122        return hash;
123    }
124
125    /**
126     * Returns a string containing a concise, human-readable description of this
127     * {@code Timestamp}.
128     *
129     * @return a printable representation for this {@code Timestamp}.
130     */
131    @Override
132    public String toString() {
133        StringBuilder buf = new StringBuilder(256);
134        // Dump only the first certificate
135        buf.append("Timestamp [").append(timestamp).append(" certPath=");
136        buf.append(signerCertPath.getCertificates().get(0)).append("]");
137        return buf.toString();
138    }
139}
140