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 implements the functionality of a builder for an unverified
29 * <i>Certification Path</i>s from a specified certificate to a trust anchor.
30 */
31public class CertPathBuilder {
32
33    // Store CertPathBuilder service name
34    private static final String SERVICE = "CertPathBuilder";
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 = "certpathbuilder.type";
41
42    // Default value of CertPathBuilder type.
43    private static final String DEFAULT_PROPERTY = "PKIX";
44
45    // Store used provider
46    private final Provider provider;
47
48    // Store spi implementation
49    private final CertPathBuilderSpi spiImpl;
50
51    // Store algorithm name
52    private final String algorithm;
53
54    /**
55     * Creates a new {@code CertPathBuilder}.
56     *
57     * @param builderSpi
58     *            the implementation delegate.
59     * @param provider
60     *            the provider.
61     * @param algorithm
62     *            the desired algorithm available at the provider.
63     */
64    protected CertPathBuilder(CertPathBuilderSpi builderSpi, Provider provider,
65            String algorithm) {
66        this.provider = provider;
67        this.algorithm = algorithm;
68        this.spiImpl = builderSpi;
69    }
70
71    /**
72     * Returns the algorithm name of this instance.
73     *
74     * @return the algorithm name of this instance.
75     */
76    public final String getAlgorithm() {
77        return algorithm;
78    }
79
80    /**
81     * Returns the provider of this instance.
82     *
83     * @return the provider of this instance.
84     */
85    public final Provider getProvider() {
86        return provider;
87    }
88
89    /**
90     * Creates a new {@code CertPathBuilder} instance with the specified
91     * algorithm.
92     *
93     * @param algorithm
94     *            the name of the algorithm.
95     * @return a builder for the requested algorithm.
96     * @throws NullPointerException
97     *             if the algorithm is {@code null}.
98     * @throws NoSuchAlgorithmException
99     *             if no installed provider can provide the algorithm.
100     */
101    public static CertPathBuilder 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 CertPathBuilder((CertPathBuilderSpi) sap.spi, sap.provider, algorithm);
108    }
109
110    /**
111     * Creates a new {@code CertPathBuilder} instance from the specified
112     * provider providing the specified algorithm.
113     *
114     * @param algorithm
115     *            the name of the algorithm.
116     * @param provider
117     *            the name of the provider.
118     * @return a builder for the requested algorithm.
119     * @throws NoSuchAlgorithmException
120     *             if the specified provider cannot provide the algorithm.
121     * @throws NoSuchProviderException
122     *             if no provider with the specified name can be found.
123     * @throws NullPointerException
124     *             if algorithm is {@code null}.
125     * @throws IllegalArgumentException if {@code provider == null || provider.isEmpty()}
126     */
127    public static CertPathBuilder getInstance(String algorithm, String provider)
128            throws NoSuchAlgorithmException, NoSuchProviderException {
129        if (provider == null || provider.isEmpty()) {
130            throw new IllegalArgumentException("provider == null || provider.isEmpty()");
131        }
132        Provider impProvider = Security.getProvider(provider);
133        if (impProvider == null) {
134            throw new NoSuchProviderException(provider);
135        }
136        return getInstance(algorithm, impProvider);
137
138    }
139
140    /**
141     * Creates a new {@code CertPathBuilder} instance from the specified
142     * provider providing the specified algorithm.
143     *
144     * @param algorithm
145     *            the name of the algorithm.
146     * @param provider
147     *            the provider.
148     * @return a builder for the requested algorithm
149     * @throws NoSuchAlgorithmException
150     *             if the specified provider cannot provide the algorithm.
151     * @throws IllegalArgumentException if {@code provider == null}
152     * @throws NullPointerException
153     *             if algorithm is {@code null}.
154     */
155    public static CertPathBuilder getInstance(String algorithm,
156            Provider provider) throws NoSuchAlgorithmException {
157        if (provider == null) {
158            throw new IllegalArgumentException("provider == null");
159        }
160        if (algorithm == null) {
161            throw new NullPointerException("algorithm == null");
162        }
163        Object spi = ENGINE.getInstance(algorithm, provider, null);
164        return new CertPathBuilder((CertPathBuilderSpi) spi, provider, algorithm);
165    }
166
167    /**
168     * Builds a certification path with the specified algorithm parameters.
169     *
170     * @param params
171     *            the algorithm parameters.
172     * @return the built certification path.
173     * @throws CertPathBuilderException
174     *             if the build fails.
175     * @throws InvalidAlgorithmParameterException
176     *             if the specified parameters cannot be used to build with this
177     *             builder.
178     * @see CertPathBuilderResult
179     */
180    public final CertPathBuilderResult build(CertPathParameters params)
181            throws CertPathBuilderException, InvalidAlgorithmParameterException {
182        return spiImpl.engineBuild(params);
183    }
184
185    /**
186     * Returns the default {@code CertPathBuilder} type from the <i>Security
187     * Properties</i>.
188     *
189     * @return the default {@code CertPathBuilder} type from the <i>Security
190     *         Properties</i>, or the string "{@code PKIX}" if it cannot be
191     *         determined.
192     */
193    public static final String getDefaultType() {
194        String defaultType = Security.getProperty(PROPERTY_NAME);
195        return (defaultType != null ? defaultType : DEFAULT_PROPERTY);
196    }
197}
198