001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.camel.util.jsse;
018
019 import java.io.IOException;
020 import java.io.InputStream;
021 import java.security.GeneralSecurityException;
022 import java.security.KeyStore;
023 import java.security.Security;
024 import java.util.Enumeration;
025 import java.util.LinkedList;
026 import java.util.List;
027
028 import org.slf4j.Logger;
029 import org.slf4j.LoggerFactory;
030
031 /**
032 * A representation of configuration options for creating and loading a
033 * {@link KeyStore} instance.
034 */
035 public class KeyStoreParameters extends JsseParameters {
036
037 private static final Logger LOG = LoggerFactory.getLogger(KeyStoreParameters.class);
038
039 /**
040 * The optional type of the key store to load. See Appendix A in the
041 * <a href="http://download.oracle.com/javase/6/docs/technotes/guides/security/StandardNames.html#KeyStore">
042 * Java Cryptography Architecture Standard Algorithm Name Documentation</a> for more information on standard names.
043 */
044 protected String type;
045
046 /**
047 * The optional password for reading/opening/verifying the key store.
048 */
049 protected String password;
050
051 /**
052 * The optional provider identifier for instantiating the key store.
053 */
054 protected String provider;
055
056 /**
057 * The optional file path, class path resource, or URL of the resource
058 * used to load the key store.
059 */
060 protected String resource;
061
062 /**
063 * @see #setType(String)
064 */
065 public String getType() {
066 return type;
067 }
068
069 /**
070 * Sets the type of the key store to create and load. See Appendix A in the
071 * <a href="http://download.oracle.com/javase/6/docs/technotes/guides/security/StandardNames.html#KeyStore"
072 * >Java Cryptography Architecture Standard Algorithm Name
073 * Documentation</a> for more information on standard names.
074 *
075 * @param value the key store type identifier (may be {@code null})
076 */
077 public void setType(String value) {
078 this.type = value;
079 }
080
081 /**
082 * @see #getPassword()
083 */
084 public String getPassword() {
085 return password;
086 }
087
088 /**
089 * Set the optional password for reading/opening/verifying the key store.
090 *
091 * @param value the password value (may be {@code null})
092 */
093 public void setPassword(String value) {
094 this.password = value;
095 }
096
097 /**
098 * @see #setProvider(String)
099 */
100 public String getProvider() {
101 return provider;
102 }
103
104 /**
105 * Sets the optional provider identifier for instantiating the key store.
106 *
107 * @param value the provider identifier (may be {@code null})
108 *
109 * @see Security#getProviders()
110 */
111 public void setProvider(String value) {
112 this.provider = value;
113 }
114
115 /**
116 * @see #getResource()
117 */
118 public String getResource() {
119 return resource;
120 }
121
122 /**
123 * Sets the optional file path, class path resource, or URL of the resource
124 * used to load the key store.
125 *
126 * @param value the resource (may be {@code null})
127 */
128 public void setResource(String value) {
129 this.resource = value;
130 }
131
132 /**
133 * Creates a {@link KeyStoreParameters} instance based off of the configuration state
134 * of this instance. If {@link #getType()} returns {@code null}, the default
135 * key store type is loaded, otherwise the type will be of that specified.
136 * <p/>
137 * The created instance will always be loaded, but if the type requires an
138 * input stream and {@link #getResource()} returns {@code null}, the
139 * instance will be empty. The loading of the resource, if not {@code null},
140 * is attempted by treating the resource as a file path, a class path
141 * resource, and a URL in that order. An exception is thrown if the resource
142 * cannot be resolved to readable input stream using any of the above
143 * methods.
144 *
145 * @return a configured and loaded key store
146 * @throws GeneralSecurityException if there is an error creating an instance
147 * with the given configuration
148 * @throws IOException if there is an error resolving the configured
149 * resource to an input stream
150 */
151 public KeyStore createKeyStore() throws GeneralSecurityException, IOException {
152 LOG.trace("Creating KeyStore instance from KeyStoreParameters [{}].", this);
153
154 String ksType = this.parsePropertyValue(this.type);
155 if (ksType == null) {
156 ksType = KeyStore.getDefaultType();
157 }
158
159 char[] ksPassword = null;
160 if (this.password != null) {
161 ksPassword = this.parsePropertyValue(this.password).toCharArray();
162 }
163
164 KeyStore ks;
165 if (this.provider == null) {
166 ks = KeyStore.getInstance(ksType);
167 } else {
168 ks = KeyStore.getInstance(ksType, this.parsePropertyValue(this.provider));
169 }
170
171 if (this.resource == null) {
172 ks.load(null, ksPassword);
173 } else {
174 InputStream is = this.resolveResource(this.parsePropertyValue(this.resource));
175 ks.load(is, ksPassword);
176 }
177
178 if (LOG.isDebugEnabled()) {
179 List<String> aliases = new LinkedList<String>();
180
181 Enumeration<String> aliasEnum = ks.aliases();
182 while (aliasEnum.hasMoreElements()) {
183 aliases.add(aliasEnum.nextElement());
184 }
185
186 LOG.debug("KeyStore [{}], initialized from [{}], is using provider [{}], has type [{}], and contains aliases {}.",
187 new Object[] {ks, this, ks.getProvider(), ks.getType(), aliases});
188 }
189
190 return ks;
191 }
192
193 @Override
194 public String toString() {
195 StringBuilder builder = new StringBuilder();
196 builder.append("KeyStoreParameters [type=");
197 builder.append(type);
198 builder.append(", password=");
199 builder.append("********");
200 builder.append(", provider=");
201 builder.append(provider);
202 builder.append(", resource=");
203 builder.append(resource);
204 builder.append(", getContext()=");
205 builder.append(getCamelContext());
206 builder.append("]");
207 return builder.toString();
208 }
209 }