View Javadoc
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  
45      private String provider = null;
46  
47      private char[] password = null;
48  
49      private byte[] data = null;
50  
51      /**
52       * Creates a new {@link KeyStore}. This method will be called
53       * by the base class when Spring creates a bean using this FactoryBean.
54       *
55       * @return a new {@link KeyStore} instance.
56       * @throws KeyStoreException If we can't create an instance of the KeyStore for the given type
57       * @throws NoSuchProviderException If we don't have the provider registered to create the KeyStore
58       * @throws NoSuchAlgorithmException If the KeyStore algorithm cannot be used
59       * @throws CertificateException If the KeyStore certificate cannot be loaded 
60       * @throws IOException If the KeyStore cannot be loaded
61       */
62      public KeyStore newInstance() throws KeyStoreException, NoSuchProviderException, NoSuchAlgorithmException,
63              CertificateException, IOException {
64          if (data == null) {
65              throw new IllegalStateException("data property is not set.");
66          }
67  
68          KeyStore ks;
69          if (provider == null) {
70              ks = KeyStore.getInstance(type);
71          } else {
72              ks = KeyStore.getInstance(type, provider);
73          }
74  
75          InputStream is = new ByteArrayInputStream(data);
76          
77          try {
78              ks.load(is, password);
79          } finally {
80              try {
81                  is.close();
82              } catch (IOException ignored) {
83                  // Do nothing
84              }
85          }
86  
87          return ks;
88      }
89  
90      /**
91       * Sets the type of key store to create. The default is to create a
92       * JKS key store.
93       *
94       * @param type the type to use when creating the key store.
95       * @throws IllegalArgumentException if the specified value is
96       *         <code>null</code>.
97       */
98      public void setType(String type) {
99          if (type == null) {
100             throw new IllegalArgumentException("type");
101         }
102         this.type = type;
103     }
104 
105     /**
106      * Sets the key store password. If this value is <code>null</code> no
107      * password will be used to check the integrity of the key store.
108      *
109      * @param password the password or <code>null</code> if no password is
110      *        needed.
111      */
112     public void setPassword(String password) {
113         if (password != null) {
114             this.password = password.toCharArray();
115         } else {
116             this.password = null;
117         }
118     }
119 
120     /**
121      * Sets the name of the provider to use when creating the key store. The
122      * default is to use the platform default provider.
123      *
124      * @param provider the name of the provider, e.g. <tt>"SUN"</tt>.
125      */
126     public void setProvider(String provider) {
127         this.provider = provider;
128     }
129 
130     /**
131      * Sets the data which contains the key store.
132      *
133      * @param data the byte array that contains the key store
134      */
135     public void setData(byte[] data) {
136         byte[] copy = new byte[data.length];
137         System.arraycopy(data, 0, copy, 0, data.length);
138         this.data = copy;
139     }
140 
141     /**
142      * Sets the data which contains the key store.
143      *
144      * @param dataStream the {@link InputStream} that contains the key store
145      * @throws IOException If we can't process the stream
146      */
147     private void setData(InputStream dataStream) throws IOException {
148         ByteArrayOutputStream out = new ByteArrayOutputStream();
149         try {
150             for (;;) {
151                 int readByte = dataStream.read();
152                 
153                 if (readByte < 0) {
154                     break;
155                 }
156                 
157                 out.write(readByte);
158             }
159             
160             setData(out.toByteArray());
161         } finally {
162             try {
163                 dataStream.close();
164             } catch (IOException e) {
165                 // Ignore.
166             }
167         }
168     }
169 
170     /**
171      * Sets the data which contains the key store.
172      *
173      * @param dataFile the {@link File} that contains the key store
174      * @throws IOException If we can't process the file
175      */
176     public void setDataFile(File dataFile) throws IOException {
177         setData(new BufferedInputStream(new FileInputStream(dataFile)));
178     }
179 
180     /**
181      * Sets the data which contains the key store.
182      *
183      * @param dataUrl the {@link URL} that contains the key store.
184      * @throws IOException If we can't process the URL
185      */
186     public void setDataUrl(URL dataUrl) throws IOException {
187         setData(dataUrl.openStream());
188     }
189 }