001    /* CertPath.java -- a sequence of certificates
002       Copyright (C) 2002, 2005  Free Software Foundation, Inc.
003    
004    This file is part of GNU Classpath.
005    
006    GNU Classpath is free software; you can redistribute it and/or modify
007    it under the terms of the GNU General Public License as published by
008    the Free Software Foundation; either version 2, or (at your option)
009    any later version.
010    
011    GNU Classpath is distributed in the hope that it will be useful, but
012    WITHOUT ANY WARRANTY; without even the implied warranty of
013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014    General Public License for more details.
015    
016    You should have received a copy of the GNU General Public License
017    along with GNU Classpath; see the file COPYING.  If not, write to the
018    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019    02110-1301 USA.
020    
021    Linking this library statically or dynamically with other modules is
022    making a combined work based on this library.  Thus, the terms and
023    conditions of the GNU General Public License cover the whole
024    combination.
025    
026    As a special exception, the copyright holders of this library give you
027    permission to link this library with independent modules to produce an
028    executable, regardless of the license terms of these independent
029    modules, and to copy and distribute the resulting executable under
030    terms of your choice, provided that you also meet, for each linked
031    independent module, the terms and conditions of the license of that
032    module.  An independent module is a module which is not derived from
033    or based on this library.  If you modify this library, you may extend
034    this exception to your version of the library, but you are not
035    obligated to do so.  If you do not wish to do so, delete this
036    exception statement from your version. */
037    
038    package java.security.cert;
039    
040    import java.io.ByteArrayInputStream;
041    import java.io.NotSerializableException;
042    import java.io.ObjectStreamException;
043    import java.io.Serializable;
044    import java.util.Iterator;
045    import java.util.List;
046    
047    /**
048     * This class represents an immutable sequence, or path, of security
049     * certificates. The path type must match the type of each certificate in the
050     * path, or in other words, for all instances of cert in a certpath object,
051     * <code>cert.getType().equals(certpath.getType())</code> will return true.
052     *
053     * <p>Since this class is immutable, it is thread-safe. During serialization,
054     * the path is consolidated into a {@link CertPathRep}, which preserves the
055     * data regardless of the underlying implementation of the path.
056     *
057     * @author Eric Blake (ebb9@email.byu.edu)
058     * @since 1.4
059     * @status updated to 1.4
060     */
061    public abstract class CertPath implements Serializable
062    {
063      /**
064       * The serialized representation of a path.
065       *
066       * @author Eric Blake (ebb9@email.byu.edu)
067       */
068      protected static class CertPathRep implements Serializable
069      {
070        /**
071         * Compatible with JDK 1.4+.
072         */
073        private static final long serialVersionUID = 3015633072427920915L;
074    
075        /**
076         * The certificate type.
077         *
078         * @serial the type of the certificate path
079         */
080        private final String type;
081    
082        /**
083         * The encoded form of the path.
084         *
085         * @serial the encoded form
086         */
087        private final byte[] data;
088    
089        /**
090         * Create the new serial representation.
091         *
092         * @param type the path type
093         * @param data the encoded path data
094         */
095        protected CertPathRep(String type, byte[] data)
096        {
097          this.type = type;
098          this.data = data;
099        }
100    
101        /**
102         * Decode the data into an actual {@link CertPath} upon deserialization.
103         *
104         * @return the replacement object
105         * @throws ObjectStreamException if replacement fails
106         */
107        protected Object readResolve() throws ObjectStreamException
108        {
109          try
110            {
111              return CertificateFactory.getInstance(type)
112                .generateCertPath(new ByteArrayInputStream(data));
113            }
114          catch (CertificateException e)
115            {
116              throw (ObjectStreamException)
117                new NotSerializableException("java.security.cert.CertPath: "
118                                             + type).initCause(e);
119            }
120        }
121      } // class CertPathRep
122    
123      /**
124       * Compatible with JDK 1.4+.
125       */
126      private static final long serialVersionUID = 6068470306649138683L;
127    
128      /**
129       * The path type.
130       *
131       * @serial the type of all certificates in this path
132       */
133      private final String type;
134    
135      /**
136       * Create a certificate path with the given type. Most code should use
137       * {@link CertificateFactory} to create CertPaths.
138       *
139       * @param type the type of the path
140       */
141      protected CertPath(String type)
142      {
143        this.type = type;
144      }
145    
146      /**
147       * Get the (non-null) type of all certificates in the path.
148       *
149       * @return the path certificate type
150       */
151      public String getType()
152      {
153        return type;
154      }
155    
156      /**
157       * Get an immutable iterator over the path encodings (all String names),
158       * starting with the default encoding. The iterator will throw an
159       * <code>UnsupportedOperationException</code> if an attempt is made to
160       * remove items from the list.
161       *
162       * @return the iterator of supported encodings in the path
163       */
164      public abstract Iterator<String> getEncodings();
165    
166      /**
167       * Compares this path to another for semantic equality. To be equal, both
168       * must be instances of CertPath, with the same type, and identical
169       * certificate lists. Overriding classes must not change this behavior.
170       *
171       * @param o the object to compare to
172       * @return true if the two are equal
173       */
174      public boolean equals(Object o)
175      {
176        if (! (o instanceof CertPath))
177          return false;
178        CertPath cp = (CertPath) o;
179        return type.equals(cp.type)
180          && getCertificates().equals(cp.getCertificates());
181      }
182    
183      /**
184       * Returns the hashcode of this certificate path. This is defined as:<br>
185       * <code>31 * getType().hashCode() + getCertificates().hashCode()</code>.
186       *
187       * @return the hashcode
188       */
189      public int hashCode()
190      {
191        return 31 * type.hashCode() + getCertificates().hashCode();
192      }
193    
194      public String toString()
195      {
196        List l = getCertificates();
197        int size = l.size();
198        int i = 0;
199        StringBuffer result = new StringBuffer(type);
200        result.append(" Cert Path: length = ").append(size).append(".\n[\n");
201        while (--size >= 0)
202          result.append(l.get(i++)).append('\n');
203        return result.append("\n]").toString();
204      }
205    
206      /**
207       * Returns the encoded form of this path, via the default encoding.
208       *
209       * @return the encoded form
210       * @throws CertificateEncodingException if encoding fails
211       */
212      public abstract byte[] getEncoded() throws CertificateEncodingException;
213    
214      /**
215       * Returns the encoded form of this path, via the specified encoding.
216       *
217       * @param encoding the encoding to use
218       * @return the encoded form
219       * @throws CertificateEncodingException if encoding fails or does not exist
220       */
221      public abstract byte[] getEncoded(String encoding)
222        throws CertificateEncodingException;
223    
224      /**
225       * Returns the immutable, thread-safe list of certificates in this path.
226       *
227       * @return the list of certificates, non-null but possibly empty
228       */
229      public abstract List<? extends Certificate> getCertificates();
230    
231      /**
232       * Serializes the path in its encoded form, to ensure reserialization with
233       * the appropriate factory object without worrying about list implementation.
234       * The result will always be an instance of {@link CertPathRep}.
235       *
236       * @return the replacement object
237       * @throws ObjectStreamException if the replacement creation fails
238       */
239      protected Object writeReplace() throws ObjectStreamException
240      {
241        try
242          {
243            return new CertPathRep(type, getEncoded());
244          }
245        catch (CertificateEncodingException e)
246          {
247            throw (ObjectStreamException)
248              new NotSerializableException("java.security.cert.CertPath: "
249                                           + type).initCause(e);
250          }
251      }
252    } // class CertPath