001 package org.cumulus4j.keymanager.api; 002 003 import java.io.Serializable; 004 import java.util.Arrays; 005 006 import org.cumulus4j.keystore.KeyStore; 007 008 /** 009 * <p> 010 * Configuration of the {@link KeyManagerAPI}. 011 * </p><p> 012 * An instance of this class tells the <code>KeyManagerAPI</code> {@link #getKeyManagerBaseURL() where} the key store 013 * is located and which key-store (identified by its {@link #getKeyStoreID() keyStoreID}) is to be used (among other things). 014 * </p><p> 015 * When you pass a <code>KeyManagerAPIConfiguration</code> instance to {@link KeyManagerAPI#setConfiguration(KeyManagerAPIConfiguration)}, 016 * it becomes {@link #isReadOnly() immutable}. If you want to change the configuration afterwards, 017 * {@link #KeyManagerAPIConfiguration(KeyManagerAPIConfiguration) create a new one} and call 018 * <code>KeyManagerAPI.setConfiguration(KeyManagerAPIConfiguration)</code> again. 019 * </p> 020 * 021 * @author Marco หงุ่ยตระกูล-Schulze - marco at nightlabs dot de 022 */ 023 public class KeyManagerAPIConfiguration 024 implements Serializable 025 { 026 private static final long serialVersionUID = 1L; 027 028 private boolean readOnly; 029 030 private String authUserName; 031 032 private char[] authPassword; 033 034 private String keyStoreID; 035 036 private String keyManagerBaseURL; 037 038 /** 039 * Create an empty configuration. 040 */ 041 public KeyManagerAPIConfiguration() { } 042 043 /** 044 * Create a copy of another configuration. You can use this to modify an existing (already immutable) configuration. 045 * @param source the original configuration to be copied. Can be <code>null</code>, which means that the new configuration 046 * will be completely empty (just as if it was created by the default constructor). 047 */ 048 public KeyManagerAPIConfiguration(KeyManagerAPIConfiguration source) 049 { 050 if (source != null) { 051 setAuthUserName(source.getAuthUserName()); 052 setAuthPassword(source.getAuthPassword()); 053 setKeyStoreID(source.getKeyStoreID()); 054 setKeyManagerBaseURL(source.getKeyManagerBaseURL()); 055 } 056 } 057 058 /** 059 * Ensure that the configuration can be modified. 060 * 061 * @throws IllegalStateException if {@link #isReadOnly()}<code> == true</code>. 062 */ 063 private void assertNotReadOnly() 064 throws IllegalStateException 065 { 066 if (readOnly) 067 throw new IllegalStateException("This instance of KeyManagerAPIConfiguration is read-only! Cannot modify it, anymore!"); 068 } 069 070 /** 071 * Get the immutable flag. Iff <code>true</code>, every attempt to modify this instance (i.e. every setter) 072 * will throw an {@link IllegalStateException}. 073 * @return the immutable flag. 074 * @see #markReadOnly() 075 */ 076 public boolean isReadOnly() { 077 return readOnly; 078 } 079 080 /** 081 * Set the immutable flag. After this method was called, every setter will throw an {@link IllegalStateException} 082 * rendering this instance read-only. 083 * @see #isReadOnly() 084 */ 085 public void markReadOnly() { 086 this.readOnly = true; 087 } 088 089 /** 090 * Get the user name that will be used for authentication at the {@link KeyStore}. 091 * @return the user name for authentication at the {@link KeyStore}. 092 * @see #setAuthUserName(String) 093 */ 094 public String getAuthUserName() { 095 return authUserName; 096 } 097 098 /** 099 * Set the user name that will be used for authentication at the {@link KeyStore}. 100 * @param authUserName the user name for authentication at the {@link KeyStore}. 101 * @see #getAuthUserName() 102 */ 103 public void setAuthUserName(String authUserName) { 104 assertNotReadOnly(); 105 this.authUserName = authUserName; 106 } 107 108 /** 109 * Get the password that will be used for authentication at the {@link KeyStore}. 110 * @return the password for authentication at the {@link KeyStore}. 111 * @see #setAuthPassword(char[]) 112 */ 113 public char[] getAuthPassword() { 114 return authPassword; 115 } 116 117 /** 118 * Set the password that will be used for authentication at the {@link KeyStore}. 119 * @param authPassword the password for authentication at the {@link KeyStore}. 120 * This will be copied, i.e. later modifications to the given password will not 121 * affect this configuration. You indeed should zero-out the given password as soon 122 * as you don't need to keep it in memory, anymore. 123 * @see #getAuthPassword() 124 */ 125 public void setAuthPassword(char[] authPassword) { 126 assertNotReadOnly(); 127 128 char[] oldPw = this.authPassword; 129 if (oldPw != null) 130 Arrays.fill(oldPw, (char)0); 131 132 this.authPassword = authPassword == null ? null : authPassword.clone(); // Cloning is essential, because we clear it later on. 133 } 134 135 /** 136 * <p> 137 * Get the {@link KeyStore}'s identifier. 138 * </p><p> 139 * One key manager can manage multiple key stores. This identifier specifies which one to use. 140 * </p> 141 * @return the {@link KeyStore}'s identifier. 142 * @see #setKeyStoreID(String) 143 */ 144 public String getKeyStoreID() { 145 return keyStoreID; 146 } 147 148 /** 149 * Set the {@link KeyStore}'s identifier. 150 * @param keyStoreID the {@link KeyStore}'s identifier. This should not contain spaces and other special characters that 151 * might not be used in restricted operating-systems (like Windows), because this might be used as (part of) a file name. 152 * Actually, it should contain only characters that can be used in URLs. 153 * @see #getKeyStoreID() 154 */ 155 public void setKeyStoreID(String keyStoreID) { 156 assertNotReadOnly(); 157 this.keyStoreID = keyStoreID; 158 } 159 160 /** 161 * Get the URL where the {@link KeyStore} is accessible. This can either be a local directory (the URL starts with 162 * "file:") or a key-server (accessible via REST over HTTP or HTTPS). 163 * @return the {@link KeyStore}'s base-URL (the complete URL is composed of this and the {@link #getKeyStoreID() key-store-ID}. 164 * @see #setKeyManagerBaseURL(String) 165 */ 166 public String getKeyManagerBaseURL() { 167 return keyManagerBaseURL; 168 } 169 170 /** 171 * Set the URL where the {@link KeyStore} is accessible. This can either be a local directory (the URL starts with 172 * "file:") or a key-server (accessible via REST over HTTP or HTTPS). 173 * @param keyManagerBaseURL the base-URL of the remote key-server or a local file-URL (referencing a directory!), 174 * if a local key-store is to be used. This argument can be <code>null</code>, which means to use a local file in 175 * the default directory "${user.home}/.cumulus4j/". 176 * @see #getKeyManagerBaseURL() 177 */ 178 public void setKeyManagerBaseURL(String keyManagerBaseURL) { 179 assertNotReadOnly(); 180 this.keyManagerBaseURL = keyManagerBaseURL; 181 } 182 183 @Override 184 protected void finalize() throws Throwable { 185 readOnly = false; // otherwise the following setAuthPassword(...) fails. 186 setAuthPassword(null); 187 super.finalize(); 188 } 189 }