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 }