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.cert;
19
20import java.security.InvalidAlgorithmParameterException;
21import java.security.NoSuchAlgorithmException;
22import java.security.NoSuchProviderException;
23import java.security.Provider;
24import java.security.Security;
25import org.apache.harmony.security.fortress.Engine;
26
27/**
28 * This class provides the functionality for validating certification paths
29 * (certificate chains) establishing a trust chain from a certificate to a trust
30 * anchor.
31 */
32public class CertPathValidator {
33    // Store CertPathValidator implementation service name
34    private static final String SERVICE = "CertPathValidator";
35
36    // Used to access common engine functionality
37    private static final Engine ENGINE = new Engine(SERVICE);
38
39    // Store default property name
40    private static final String PROPERTY_NAME = "certpathvalidator.type";
41
42    // Default value of CertPathBuilder type. It returns if certpathbuild.type
43    // property is not defined in java.security file
44    private static final String DEFAULT_PROPERTY = "PKIX";
45
46    // Store used provider
47    private final Provider provider;
48
49    // Store used spi implementation
50    private final CertPathValidatorSpi spiImpl;
51
52    // Store used algorithm value
53    private final String algorithm;
54
55    /**
56     * Creates a new {@code CertPathValidator} instance.
57     *
58     * @param validatorSpi
59     *            the implementation delegate.
60     * @param provider
61     *            the security provider.
62     * @param algorithm
63     *            the name of the algorithm.
64     */
65    protected CertPathValidator(CertPathValidatorSpi validatorSpi,
66            Provider provider, String algorithm) {
67        this.provider = provider;
68        this.algorithm = algorithm;
69        this.spiImpl = validatorSpi;
70    }
71
72    /**
73     * Returns the certification path algorithm name.
74     *
75     * @return the certification path algorithm name.
76     */
77    public final String getAlgorithm() {
78        return algorithm;
79    }
80
81    /**
82     * Returns the security provider.
83     *
84     * @return the provider.
85     */
86    public final Provider getProvider() {
87        return provider;
88    }
89
90    /**
91     * Returns a new certification path validator for the specified algorithm.
92     *
93     * @param algorithm
94     *            the algorithm name.
95     * @return a certification path validator for the requested algorithm.
96     * @throws NoSuchAlgorithmException
97     *             if no installed provider provides the specified algorithm.
98     * @throws NullPointerException
99     *             if algorithm is {@code null}.
100     */
101    public static CertPathValidator getInstance(String algorithm)
102            throws NoSuchAlgorithmException {
103        if (algorithm == null) {
104            throw new NullPointerException("algorithm == null");
105        }
106        Engine.SpiAndProvider sap = ENGINE.getInstance(algorithm, null);
107        return new CertPathValidator((CertPathValidatorSpi) sap.spi, sap.provider, algorithm);
108    }
109
110    /**
111     * Returns a new certification path validator for the specified algorithm
112     * from the specified provider.
113     *
114     * @param algorithm
115     *            the algorithm name.
116     * @param provider
117     *            the security provider name.
118     * @return a certification path validator for the requested algorithm.
119     * @throws NoSuchAlgorithmException
120     *             if the specified security provider cannot provide the
121     *             requested algorithm.
122     * @throws NoSuchProviderException
123     *             if no provider with the specified name can be found.
124     * @throws NullPointerException
125     *             if algorithm is {@code null}.
126     * @throws IllegalArgumentException if {@code provider == null || provider.isEmpty()}
127     */
128    public static CertPathValidator getInstance(String algorithm,
129            String provider) throws NoSuchAlgorithmException,
130            NoSuchProviderException {
131        if (provider == null || provider.isEmpty()) {
132            throw new IllegalArgumentException();
133        }
134        Provider impProvider = Security.getProvider(provider);
135        if (impProvider == null) {
136            throw new NoSuchProviderException(provider);
137        }
138        return getInstance(algorithm, impProvider);
139    }
140
141    /**
142     * Returns a new certification path validator for the specified algorithm
143     * from the specified provider.
144     *
145     * @param algorithm
146     *            the algorithm name.
147     * @param provider
148     *            the security provider name.
149     * @return a certification path validator for the requested algorithm.
150     * @throws NoSuchAlgorithmException
151     *             if the specified provider cannot provide the requested
152     *             algorithm.
153     * @throws IllegalArgumentException if {@code provider == null}
154     * @throws NullPointerException
155     *             if algorithm is {@code null}.
156     */
157    public static CertPathValidator getInstance(String algorithm,
158            Provider provider) throws NoSuchAlgorithmException {
159        if (provider == null) {
160            throw new IllegalArgumentException("provider == null");
161        }
162        if (algorithm == null) {
163            throw new NullPointerException("algorithm == null");
164        }
165        Object spi = ENGINE.getInstance(algorithm, provider, null);
166        return new CertPathValidator((CertPathValidatorSpi) spi, provider, algorithm);
167    }
168
169    /**
170     * Validates the {@code CertPath} with the algorithm of this {@code
171     * CertPathValidator} using the specified algorithm parameters.
172     *
173     * @param certPath
174     *            the certification path to be validated.
175     * @param params
176     *            the certification path validator algorithm parameters.
177     * @return the validation result.
178     * @throws CertPathValidatorException
179     *             if the validation fails, or the algorithm of the specified
180     *             certification path cannot be validated using the algorithm of
181     *             this instance.
182     * @throws InvalidAlgorithmParameterException
183     *             if the specified algorithm parameters cannot be used with
184     *             this algorithm.
185     * @see CertPathValidatorResult
186     */
187    public final CertPathValidatorResult validate(CertPath certPath,
188            CertPathParameters params) throws CertPathValidatorException,
189            InvalidAlgorithmParameterException {
190        return spiImpl.engineValidate(certPath, params);
191    }
192
193    /**
194     * Returns the default {@code CertPathValidator} type from the <i>Security
195     * Properties</i>.
196     *
197     * @return the default {@code CertPathValidator} type from the <i>Security
198     *         Properties</i>, or the string {@code "PKIX"} if it cannot be
199     *         determined.
200     */
201    public static final String getDefaultType() {
202        String defaultType = Security.getProperty(PROPERTY_NAME);
203        return (defaultType != null ? defaultType : DEFAULT_PROPERTY);
204    }
205}
206