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 }