1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  Licensed to the Apache Software Foundation (ASF) under one or more
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  contributor license agreements.  See the NOTICE file distributed with
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  this work for additional information regarding copyright ownership.
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  The ASF licenses this file to You under the Apache License, Version 2.0
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  (the "License"); you may not use this file except in compliance with
7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  the License.  You may obtain a copy of the License at
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *     http://www.apache.org/licenses/LICENSE-2.0
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  Unless required by applicable law or agreed to in writing, software
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  distributed under the License is distributed on an "AS IS" BASIS,
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  See the License for the specific language governing permissions and
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  limitations under the License.
16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage java.security;
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.ByteArrayInputStream;
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.IOException;
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.OptionalDataException;
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.ObjectInputStream;
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.ObjectOutputStream;
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.Serializable;
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.net.SocketPermission;
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.net.URL;
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.cert.CertPath;
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.cert.Certificate;
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.cert.CertificateEncodingException;
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.cert.CertificateException;
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.cert.CertificateFactory;
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.cert.X509Certificate;
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.ArrayList;
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.List;
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport javax.security.auth.x500.X500Principal;
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.apache.harmony.security.fortress.PolicyUtils;
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.apache.harmony.security.internal.nls.Messages;
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/**
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * {@code CodeSource} encapsulates the location from where code is loaded and
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the certificates that were used to verify that code. This information is used
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * by {@code SecureClassLoader} to define protection domains for loaded classes.
46e7637fe9734c4e3bece51db6773505c04e49fabaElliott Hughes *
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @see SecureClassLoader
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @see ProtectionDomain
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic class CodeSource implements Serializable {
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static final long serialVersionUID = 4977541819976013951L;
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // Location of this CodeSource object
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private URL location;
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // Array of certificates assigned to this CodeSource object
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private transient java.security.cert.Certificate[] certs;
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // Array of CodeSigners
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private transient CodeSigner[] signers;
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // SocketPermission() in implies() method takes to many time.
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // Need to cache it for better performance.
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private transient SocketPermission sp;
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // Cached factory used to build CertPath-s in <code>getCodeSigners()</code>.
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private transient CertificateFactory factory;
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Constructs a new instance of {@code CodeSource} with the specified
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * {@code URL} and the {@code Certificate}s.
73e7637fe9734c4e3bece51db6773505c04e49fabaElliott Hughes     *
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param location
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the {@code URL} representing the location from where code is
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            loaded, maybe {@code null}.
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param certs
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the {@code Certificate} used to verify the code, loaded from
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the specified {@code location}, maybe {@code null}.
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public CodeSource(URL location, Certificate[] certs) {
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.location = location;
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (certs != null) {
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.certs = new Certificate[certs.length];
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            System.arraycopy(certs, 0, this.certs, 0, certs.length);
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Constructs a new instance of {@code CodeSource} with the specified
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * {@code URL} and the {@code CodeSigner}s.
92e7637fe9734c4e3bece51db6773505c04e49fabaElliott Hughes     *
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param location
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the {@code URL} representing the location from where code is
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            loaded, maybe {@code null}.
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param signers
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the {@code CodeSigner}s of the code, loaded from the specified
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            {@code location}. Maybe {@code null}.
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public CodeSource(URL location, CodeSigner[] signers) {
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.location = location;
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (signers != null) {
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.signers = new CodeSigner[signers.length];
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            System.arraycopy(signers, 0, this.signers, 0, signers.length);
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Compares the specified object with this {@code CodeSource} for equality.
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns {@code true} if the specified object is also an instance of
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * {@code CodeSource}, points to the same {@code URL} location and the two
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * code sources encapsulate the same {@code Certificate}s. The order of the
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * {@code Certificate}s is ignored by this method.
114e7637fe9734c4e3bece51db6773505c04e49fabaElliott Hughes     *
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param obj
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            object to be compared for equality with this {@code
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            CodeSource}.
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return {@code true} if the specified object is equal to this {@code
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *         CodeSource}, otherwise {@code false}.
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
121e7637fe9734c4e3bece51db6773505c04e49fabaElliott Hughes    @Override
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public boolean equals(Object obj) {
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (obj == this) {
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return true;
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!(obj instanceof CodeSource)) {
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        CodeSource that = (CodeSource) obj;
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (this.location != null) {
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (that.location == null) {
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return false;
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!this.location.equals(that.location)) {
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return false;
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (that.location != null) {
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // do not use this.certs, as we also need to take care about
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // CodeSigners' certificates
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Certificate[] thizCerts = getCertificatesNoClone();
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Certificate[] thatCerts = that.getCertificatesNoClone();
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!PolicyUtils.matchSubset(thizCerts, thatCerts)) {
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!PolicyUtils.matchSubset(thatCerts, thizCerts)) {
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return true;
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns the certificates of this {@code CodeSource}. If the
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * {@link #CodeSource(URL, CodeSigner[])} constructor was used to create
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * this instance, the certificates are obtained from the supplied signers.
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <p>
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * External modifications of the returned {@code Certificate[]} has no
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * impact on this {@code CodeSource}.
164e7637fe9734c4e3bece51db6773505c04e49fabaElliott Hughes     *
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return the certificates of this {@code CodeSource} or {@code null} if
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *         there is none.
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public final Certificate[] getCertificates() {
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        getCertificatesNoClone();
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (certs == null) {
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return null;
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Certificate[] tmp = new Certificate[certs.length];
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        System.arraycopy(certs, 0, tmp, 0, certs.length);
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return tmp;
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // Acts exactly as {@link #getCertificates()} does, but does not clone the
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // array before returning (and returns reference to <code>this.certs</code>
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // if this array is not null).<br>
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // @return a reference to the certificates array, or null if there are no
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // certificates associated.
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private Certificate[] getCertificatesNoClone() {
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (certs != null) {
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return certs;
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (signers == null) {
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return null;
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // Extract Certificates from the CodeSigner-s
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ArrayList<Certificate> v = new ArrayList<Certificate>();
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (int i = 0; i < signers.length; i++) {
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            v.addAll(signers[i].getSignerCertPath().getCertificates());
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        certs = v.toArray(new Certificate[v.size()]);
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return certs;
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns the {@code CodeSigner}s of this {@code CodeSource}. If the
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * {@link #CodeSource(URL, Certificate[])} constructor was used to create
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * this instance, the signers are obtained from the supplied certificates.
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Only X.509 certificates are analyzed.
206e7637fe9734c4e3bece51db6773505c04e49fabaElliott Hughes     *
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return the signers of this {@code CodeSource}, or {@code null} if there
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *         is none.
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public final CodeSigner[] getCodeSigners() {
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (signers != null) {
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            CodeSigner[] tmp = new CodeSigner[signers.length];
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            System.arraycopy(signers, 0, tmp, 0, tmp.length);
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return tmp;
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if(certs == null || factory != null){
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // factory != null means we've done this exercise already.
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return null;
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        X500Principal prevIssuer = null;
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ArrayList<Certificate> list = new ArrayList<Certificate>(certs.length);
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ArrayList<CodeSigner> asigners = new ArrayList<CodeSigner>();
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // The presumption is that the chains of certificates are placed
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // according to the CertPath agreement:
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // the lowest certs first; the CAs are at the last
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // So the following loop scans trough the certs and checks
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // that every next certificate is an Issuer of the previous one.
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // Any certificate that is not an Issuer of the previous one starts a
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // new chain (== a new CertPath)
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (int i = 0; i < certs.length; i++) {
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!(certs[i] instanceof X509Certificate)) {
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // Only X509Certificate-s are taken into account - see API spec.
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                continue;
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            X509Certificate x509 = (X509Certificate) certs[i];
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (prevIssuer == null) {
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // start a very first chain
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                prevIssuer = x509.getIssuerX500Principal();
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                list.add(x509);
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                X500Principal subj = x509.getSubjectX500Principal();
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (!prevIssuer.equals(subj)) {
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    // Ok, this ends the previous chain,
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    // so transform this one into CertPath ...
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    CertPath cpath = makeCertPath(list);
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (cpath != null) {
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        asigners.add(new CodeSigner(cpath, null));
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    // ... and start a new one
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    list.clear();
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }// else { it's still the same chain }
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                prevIssuer = x509.getSubjectX500Principal();
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                list.add(x509);
259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!list.isEmpty()) {
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            CertPath cpath = makeCertPath(list);
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (cpath != null) {
264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                asigners.add(new CodeSigner(cpath, null));
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (asigners.isEmpty()) {
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // 'signers' is 'null' already
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return null;
270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        signers = new CodeSigner[asigners.size()];
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        asigners.toArray(signers);
273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        CodeSigner[] tmp = new CodeSigner[asigners.size()];
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        System.arraycopy(signers, 0, tmp, 0, tmp.length);
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return tmp;
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // Makes an CertPath from a given List of X509Certificate-s.
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // @param list
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // @return CertPath, or null if CertPath cannot be made
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private CertPath makeCertPath(List<? extends Certificate> list) {
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (factory == null) {
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            try {
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                factory = CertificateFactory.getInstance("X.509"); //$NON-NLS-1$
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } catch (CertificateException ex) {
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                //? throw new Error("X.509 is a 'must be'", ex);
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return null;
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        try {
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return factory.generateCertPath(list);
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (CertificateException ex) {
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // ignore(ex)
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return null;
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns the location of this {@code CodeSource}.
300e7637fe9734c4e3bece51db6773505c04e49fabaElliott Hughes     *
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return the location of this {@code CodeSource}, maybe {@code null}.
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public final URL getLocation() {
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return location;
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns the hash code value for this {@code CodeSource}.
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns the same hash code for {@code CodeSource}s that are
310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * equal to each other as required by the general contract of
311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * {@link Object#hashCode}.
312e7637fe9734c4e3bece51db6773505c04e49fabaElliott Hughes     *
313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return the hash code value for this {@code CodeSource}.
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @see Object#equals(Object)
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @see CodeSource#equals(Object)
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
317e7637fe9734c4e3bece51db6773505c04e49fabaElliott Hughes    @Override
318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public int hashCode() {
319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //
320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // hashCode() is undocumented there. Should we also use certs[i] to
321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // compute the hash ?
322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // for now, I don't take certs[] into account
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return location == null ? 0 : location.hashCode();
324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Indicates whether the specified code source is implied by this {@code
328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * CodeSource}. Returns {@code true} if all of the following conditions are
329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * {@code true}, otherwise {@code false}:
330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <p>
331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <ul>
332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <li>{@code cs} is not {@code null}
333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <li>if this {@code CodeSource} has associated certificates, all
334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * certificates are present in {@code cs}. The certificates are extracted
335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * from the signers if signers are present.
336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <li>if this {@code CodeSource}'s location is not {@code null}, the
337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * following conditions are checked
338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <ul>
339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <li>this {@code CodeSource}'s location is not {@code null}
340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <li>this {@code CodeSource}'s location protocol is equal to {@code cs}'s
341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * location protocol
342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <li>if this {@code CodeSource}'s location host is not {@code null}, the
343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * following conditions are checked
344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <ul>
345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <li>{@code cs}'s host is not {@code null}
346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <li>the {@link SocketPermission} of this {@code CodeSource}'s location
347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * host implies the {@code SocketPermission} of {@code cs}'s location host
348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * </ul>
349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <li>if this {@code CodeSource}'s location port != -1 the port of {@code
350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * cs}'s location is equal to this {@code CodeSource}'s location port
351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <li>this {@code CodeSource}'s location file matches {@code cs}'s file
352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * whereas special wildcard matching applies as described below
353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <li>this {@code CodeSource}'s location reference is equal to to {@code
354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * cs}'s location reference
355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * </ul>
356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * </ul>
357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <p>
358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Note: If this {@code CodeSource} has a {@code null} location and not any
359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * certificates, this method returns {@code true}.
360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <p>
361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Matching rules for the {@code CodeSource}'s location file:
362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <ul>
363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <li>if this {@code CodeSource}'s location file ends with {@code "/-"},
364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * then {@code cs}'s file must start with {@code CodeSource}'s location file
365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (exclusive the trailing '-')
366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <li>if this {@code CodeSource}'s location file ends with {@code "/*"},
367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * then {@code cs}'s file must start with {@code CodeSource}'s location file
368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (exclusive the trailing '*') and must not have any further '/'
369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <li>if this {@code CodeSource}'s location file ends with {@code "/"},
370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * then {@code cs}'s file must start with {@code CodeSource}'s location file
371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <li>if this {@code CodeSource}'s location file does not end with {@code
372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * "/"}, then {@code cs}'s file must start with {@code CodeSource}'s
373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * location file with the '/' appended to it.
374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * </ul>
375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Examples for locations that imply the location
376e7637fe9734c4e3bece51db6773505c04e49fabaElliott Hughes     * "http://harmony.apache.org/milestones/M9/apache-harmony.jar":
377e7637fe9734c4e3bece51db6773505c04e49fabaElliott Hughes     *
378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <pre>
379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * http:
380e7637fe9734c4e3bece51db6773505c04e49fabaElliott Hughes     * http://&#42;/milestones/M9/*
381e7637fe9734c4e3bece51db6773505c04e49fabaElliott Hughes     * http://*.apache.org/milestones/M9/*
382e7637fe9734c4e3bece51db6773505c04e49fabaElliott Hughes     * http://harmony.apache.org/milestones/-
383e7637fe9734c4e3bece51db6773505c04e49fabaElliott Hughes     * http://harmony.apache.org/milestones/M9/apache-harmony.jar
384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * </pre>
385e7637fe9734c4e3bece51db6773505c04e49fabaElliott Hughes     *
386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param cs
387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the code source to check.
388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return {@code true} if the argument code source is implied by this
389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *         {@code CodeSource}, otherwise {@code false}.
390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public boolean implies(CodeSource cs) {
392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //
393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // Here, javadoc:N refers to the appropriate item in the API spec for
394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // the CodeSource.implies()
395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // The info was taken from the 1.5 final API spec
396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // javadoc:1
398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (cs == null) {
399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // javadoc:2
403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // with a comment: the javadoc says only about certificates and does
404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // not explicitly mention CodeSigners' certs.
405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // It seems more convenient to use getCerts() to get the real
406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // certificates - with a certificates got form the signers
407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Certificate[] thizCerts = getCertificatesNoClone();
408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (thizCerts != null) {
409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            Certificate[] thatCerts = cs.getCertificatesNoClone();
410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (thatCerts == null
411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    || !PolicyUtils.matchSubset(thizCerts, thatCerts)) {
412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return false;
413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // javadoc:3
417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (this.location != null) {
418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //javadoc:3.1
419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (cs.location == null) {
420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return false;
421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //javadoc:3.2
423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (this.location.equals(cs.location)) {
424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return true;
425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //javadoc:3.3
427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!this.location.getProtocol().equals(cs.location.getProtocol())) {
428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return false;
429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //javadoc:3.4
431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            String thisHost = this.location.getHost();
432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (thisHost != null) {
433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                String thatHost = cs.location.getHost();
434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (thatHost == null) {
435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    return false;
436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // 1. According to the spec, an empty string will be considered
439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // as "localhost" in the SocketPermission
440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // 2. 'file://' URLs will have an empty getHost()
441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // so, let's make a special processing of localhost-s, I do
442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // believe this'll improve performance of file:// code sources
443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                //
445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // Don't have to evaluate both the boolean-s each time.
446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // It's better to evaluate them directly under if() statement.
447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                //
448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // boolean thisIsLocalHost = thisHost.length() == 0 || "localhost".equals(thisHost);
449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // boolean thatIsLocalHost = thatHost.length() == 0 || "localhost".equals(thatHost);
450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                //
451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // if( !(thisIsLocalHost && thatIsLocalHost) &&
452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // !thisHost.equals(thatHost)) {
453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (!((thisHost.length() == 0 || "localhost".equals(thisHost)) && (thatHost //$NON-NLS-1$
455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        .length() == 0 || "localhost".equals(thatHost))) //$NON-NLS-1$
456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        && !thisHost.equals(thatHost)) {
457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    // Obvious, but very slow way....
459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    //
460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    // SocketPermission thisPerm = new SocketPermission(
461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    //          this.location.getHost(), "resolve");
462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    // SocketPermission thatPerm = new SocketPermission(
463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    //          cs.location.getHost(), "resolve");
464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    // if (!thisPerm.implies(thatPerm)) {
465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    //      return false;
466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    // }
467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    //
468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    // let's cache it:
469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (this.sp == null) {
471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        this.sp = new SocketPermission(thisHost, "resolve"); //$NON-NLS-1$
472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (cs.sp == null) {
475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        cs.sp = new SocketPermission(thatHost, "resolve"); //$NON-NLS-1$
476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (!this.sp.implies(cs.sp)) {
479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        return false;
480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                } // if( ! this.location.getHost().equals(cs.location.getHost())
482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } // if (this.location.getHost() != null)
483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //javadoc:3.5
485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (this.location.getPort() != -1) {
486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (this.location.getPort() != cs.location.getPort()) {
487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    return false;
488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //javadoc:3.6
492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            String thisFile = this.location.getFile();
493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            String thatFile = cs.location.getFile();
494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (thisFile.endsWith("/-")) { //javadoc:3.6."/-" //$NON-NLS-1$
496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (!thatFile.startsWith(thisFile.substring(0, thisFile
497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        .length() - 2))) {
498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    return false;
499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else if (thisFile.endsWith("/*")) { //javadoc:3.6."/*" //$NON-NLS-1$
501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (!thatFile.startsWith(thisFile.substring(0, thisFile
502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        .length() - 2))) {
503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    return false;
504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // no further separators(s) allowed
506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (thatFile.indexOf("/", thisFile.length() - 1) != -1) { //$NON-NLS-1$
507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    return false;
508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // javadoc:3.6."/"
511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (!thisFile.equals(thatFile)) {
512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (!thisFile.endsWith("/")) { //$NON-NLS-1$
513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        if (!thatFile.equals(thisFile + "/")) { //$NON-NLS-1$
514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            return false;
515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        }
516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    } else {
517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        return false;
518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //javadoc:3.7
523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (this.location.getRef() != null) {
524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (!this.location.getRef().equals(cs.location.getRef())) {
525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    return false;
526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // ok, every check was made, and they all were successful.
529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // it's ok to return true.
530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } // if this.location != null
531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // javadoc: a note about CodeSource with null location and null Certs
533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // is applicable here
534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return true;
535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns a string containing a concise, human-readable description of the
539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * this {@code CodeSource} including its location, its certificates and its
540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * signers.
541e7637fe9734c4e3bece51db6773505c04e49fabaElliott Hughes     *
542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return a printable representation for this {@code CodeSource}.
543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
544e7637fe9734c4e3bece51db6773505c04e49fabaElliott Hughes    @Override
545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public String toString() {
546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        StringBuilder buf = new StringBuilder();
547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buf.append("CodeSource, url="); //$NON-NLS-1$
548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buf.append(location == null ? "<null>" : location.toString()); //$NON-NLS-1$
549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (certs == null) {
551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            buf.append(", <no certificates>"); //$NON-NLS-1$
552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            buf.append("\nCertificates [\n"); //$NON-NLS-1$
554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (int i = 0; i < certs.length; i++) {
555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                buf.append(i + 1).append(") ").append(certs[i]).append("\n"); //$NON-NLS-1$ //$NON-NLS-2$
556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            buf.append("]\n"); //$NON-NLS-1$
558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (signers != null) {
560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            buf.append("\nCodeSigners [\n"); //$NON-NLS-1$
561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (int i = 0; i < signers.length; i++) {
562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                buf.append(i + 1).append(") ").append(signers[i]).append("\n"); //$NON-NLS-1$ //$NON-NLS-2$
563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            buf.append("]\n"); //$NON-NLS-1$
565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return buf.toString();
567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private void writeObject(ObjectOutputStream oos) throws IOException {
570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        oos.defaultWriteObject();
572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (certs == null || certs.length == 0) {
574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            oos.writeInt(0);
575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            oos.writeInt(certs.length);
577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (int i = 0; i < certs.length; i++) {
578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                try {
579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    oos.writeUTF(certs[i].getType());
580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    byte[] data = certs[i].getEncoded();
581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    // hope there are no certificates with 'data==null'
582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    oos.writeInt(data.length);
583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    oos.write(data);
584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                } catch (CertificateEncodingException ex) {
585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    throw (IOException) new IOException(
586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            Messages.getString("security.18")).initCause(ex); //$NON-NLS-1$
587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (signers != null && signers.length != 0) {
591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            oos.writeObject(signers);
592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private void readObject(ObjectInputStream ois) throws IOException,
596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ClassNotFoundException {
597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ois.defaultReadObject();
599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int certsCount = ois.readInt();
601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        certs = null;
602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (certsCount != 0) {
603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            certs = new Certificate[certsCount];
604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (int i = 0; i < certsCount; i++) {
605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                String type = ois.readUTF();
606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                CertificateFactory factory;
607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                try {
608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    factory = CertificateFactory.getInstance(type);
609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                } catch (CertificateException ex) {
610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    throw new ClassNotFoundException(
611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            Messages.getString("security.19", type), //$NON-NLS-1$
612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            ex);
613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                int dataLen = ois.readInt();
615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                byte[] data = new byte[dataLen];
616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ois.readFully(data);
617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ByteArrayInputStream bais = new ByteArrayInputStream(data);
618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                try {
619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    certs[i] = factory.generateCertificate(bais);
620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                } catch (CertificateException ex) {
621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    throw (IOException) new IOException(
622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            Messages.getString("security.1A")).initCause(ex); //$NON-NLS-1$
623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        try {
627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            signers = (CodeSigner[]) ois.readObject();
628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (OptionalDataException ex) {
629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!ex.eof) {
630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throw ex;
631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // no signers (ex.eof==true <= no data left) is allowed
633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
636