001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020package org.apache.mina.filter.ssl; 021 022import java.io.BufferedInputStream; 023import java.io.ByteArrayInputStream; 024import java.io.ByteArrayOutputStream; 025import java.io.File; 026import java.io.FileInputStream; 027import java.io.IOException; 028import java.io.InputStream; 029import java.net.URL; 030import java.security.KeyStore; 031import java.security.KeyStoreException; 032import java.security.NoSuchAlgorithmException; 033import java.security.NoSuchProviderException; 034import java.security.cert.CertificateException; 035 036/** 037 * A factory that creates and configures a new {@link KeyStore} instance. 038 * 039 * @author <a href="http://mina.apache.org">Apache MINA Project</a> 040 */ 041public class KeyStoreFactory { 042 043 private String type = "JKS"; 044 045 private String provider = null; 046 047 private char[] password = null; 048 049 private byte[] data = null; 050 051 /** 052 * Creates a new {@link KeyStore}. This method will be called 053 * by the base class when Spring creates a bean using this FactoryBean. 054 * 055 * @return a new {@link KeyStore} instance. 056 * @throws KeyStoreException If we can't create an instance of the KeyStore for the given type 057 * @throws NoSuchProviderException If we don't have the provider registered to create the KeyStore 058 * @throws NoSuchAlgorithmException If the KeyStore algorithm cannot be used 059 * @throws CertificateException If the KeyStore certificate cannot be loaded 060 * @throws IOException If the KeyStore cannot be loaded 061 */ 062 public KeyStore newInstance() throws KeyStoreException, NoSuchProviderException, NoSuchAlgorithmException, 063 CertificateException, IOException { 064 if (data == null) { 065 throw new IllegalStateException("data property is not set."); 066 } 067 068 KeyStore ks; 069 if (provider == null) { 070 ks = KeyStore.getInstance(type); 071 } else { 072 ks = KeyStore.getInstance(type, provider); 073 } 074 075 InputStream is = new ByteArrayInputStream(data); 076 077 try { 078 ks.load(is, password); 079 } finally { 080 try { 081 is.close(); 082 } catch (IOException ignored) { 083 // Do nothing 084 } 085 } 086 087 return ks; 088 } 089 090 /** 091 * Sets the type of key store to create. The default is to create a 092 * JKS key store. 093 * 094 * @param type the type to use when creating the key store. 095 * @throws IllegalArgumentException if the specified value is 096 * <code>null</code>. 097 */ 098 public void setType(String type) { 099 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 data = dataStream.read(); 152 if (data < 0) { 153 break; 154 } 155 out.write(data); 156 } 157 setData(out.toByteArray()); 158 } finally { 159 try { 160 dataStream.close(); 161 } catch (IOException e) { 162 // Ignore. 163 } 164 } 165 } 166 167 /** 168 * Sets the data which contains the key store. 169 * 170 * @param dataFile the {@link File} that contains the key store 171 * @throws IOException If we can't process the file 172 */ 173 public void setDataFile(File dataFile) throws IOException { 174 setData(new BufferedInputStream(new FileInputStream(dataFile))); 175 } 176 177 /** 178 * Sets the data which contains the key store. 179 * 180 * @param dataUrl the {@link URL} that contains the key store. 181 * @throws IOException If we can't process the URL 182 */ 183 public void setDataUrl(URL dataUrl) throws IOException { 184 setData(dataUrl.openStream()); 185 } 186}