1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 *
19 */
20 package org.apache.mina.filter.ssl;
21
22 import java.io.BufferedInputStream;
23 import java.io.ByteArrayInputStream;
24 import java.io.ByteArrayOutputStream;
25 import java.io.File;
26 import java.io.FileInputStream;
27 import java.io.IOException;
28 import java.io.InputStream;
29 import java.net.URL;
30 import java.security.KeyStore;
31 import java.security.KeyStoreException;
32 import java.security.NoSuchAlgorithmException;
33 import java.security.NoSuchProviderException;
34 import java.security.cert.CertificateException;
35
36 /**
37 * A factory that creates and configures a new {@link KeyStore} instance.
38 *
39 * @author <a href="http://mina.apache.org">Apache MINA Project</a>
40 */
41 public class KeyStoreFactory {
42
43 private String type = "JKS";
44 private String provider = null;
45 private char[] password = null;
46 private byte[] data = null;
47
48 /**
49 * Creates a new {@link KeyStore}. This method will be called
50 * by the base class when Spring creates a bean using this FactoryBean.
51 *
52 * @return a new {@link KeyStore} instance.
53 */
54 public KeyStore newInstance() throws KeyStoreException, NoSuchProviderException, NoSuchAlgorithmException, CertificateException, IOException {
55 if (data == null) {
56 throw new IllegalStateException("data property is not set.");
57 }
58
59 KeyStore ks;
60 if (provider == null) {
61 ks = KeyStore.getInstance(type);
62 } else {
63 ks = KeyStore.getInstance(type, provider);
64 }
65
66 InputStream is = new ByteArrayInputStream(data);
67 try {
68 ks.load(is, password);
69 } finally {
70 try {
71 is.close();
72 } catch (IOException ignored) {
73 // Do nothing
74 }
75 }
76
77 return ks;
78 }
79
80 /**
81 * Sets the type of key store to create. The default is to create a
82 * JKS key store.
83 *
84 * @param type the type to use when creating the key store.
85 * @throws IllegalArgumentException if the specified value is
86 * <code>null</code>.
87 */
88 public void setType(String type) {
89 if (type == null) {
90 throw new NullPointerException("type");
91 }
92 this.type = type;
93 }
94
95 /**
96 * Sets the key store password. If this value is <code>null</code> no
97 * password will be used to check the integrity of the key store.
98 *
99 * @param password the password or <code>null</code> if no password is
100 * needed.
101 */
102 public void setPassword(String password) {
103 if (password != null) {
104 this.password = password.toCharArray();
105 } else {
106 this.password = null;
107 }
108 }
109
110 /**
111 * Sets the name of the provider to use when creating the key store. The
112 * default is to use the platform default provider.
113 *
114 * @param provider the name of the provider, e.g. <tt>"SUN"</tt>.
115 */
116 public void setProvider(String provider) {
117 this.provider = provider;
118 }
119
120 /**
121 * Sets the data which contains the key store.
122 *
123 * @param data the byte array that contains the key store
124 */
125 public void setData(byte[] data) {
126 byte[] copy = new byte[data.length];
127 System.arraycopy(data, 0, copy, 0, data.length);
128 this.data = copy;
129 }
130
131 /**
132 * Sets the data which contains the key store.
133 *
134 * @param dataStream the {@link InputStream} that contains the key store
135 */
136 private void setData(InputStream dataStream) throws IOException {
137 ByteArrayOutputStream out = new ByteArrayOutputStream();
138 try {
139 for (;;) {
140 int data = dataStream.read();
141 if (data < 0) {
142 break;
143 }
144 out.write(data);
145 }
146 setData(out.toByteArray());
147 } finally {
148 try {
149 dataStream.close();
150 } catch (IOException e) {
151 // Ignore.
152 }
153 }
154 }
155
156 /**
157 * Sets the data which contains the key store.
158 *
159 * @param dataFile the {@link File} that contains the key store
160 */
161 public void setDataFile(File dataFile) throws IOException {
162 setData(new BufferedInputStream(new FileInputStream(dataFile)));
163 }
164
165 /**
166 * Sets the data which contains the key store.
167 *
168 * @param dataUrl the {@link URL} that contains the key store.
169 */
170 public void setDataUrl(URL dataUrl) throws IOException {
171 setData(dataUrl.openStream());
172 }
173 }