001 package org.cumulus4j.keymanager.front.webapp;
002
003 import java.io.File;
004 import java.io.IOException;
005 import java.util.HashMap;
006 import java.util.Map;
007
008 import javax.ws.rs.core.Context;
009
010 import org.cumulus4j.keymanager.AppServerManager;
011 import org.cumulus4j.keymanager.back.shared.SystemPropertyUtil;
012 import org.cumulus4j.keystore.KeyStore;
013 import org.slf4j.Logger;
014 import org.slf4j.LoggerFactory;
015
016 /**
017 * <p>
018 * Manager for {@link KeyStore}s mapping a <code>keyStoreID</code> to a file name in the local
019 * file system.
020 * </p><p>
021 * One instance of this class is held as a REST-app-singleton and injected into the REST services
022 * via {@link Context} like this example:
023 * </p>
024 * <pre>
025 * private @Context KeyStoreManager keyStoreManager;
026 * </pre>
027 *
028 * @author Marco หงุ่ยตระกูล-Schulze - marco at nightlabs dot de
029 */
030 public class KeyStoreManager
031 {
032 private static final Logger logger = LoggerFactory.getLogger(KeyStoreManager.class);
033
034 /**
035 * <p>
036 * System property to control which directory is used to manage key store files. If not specified,
037 * the directory "${user.home}/.cumulus4j/" will be used.
038 * </p>
039 * <p>
040 * You can use system properties in this system-property's value. For example
041 * passing "-Dcumulus4j.keyStoreDir=${java.io.tmpdir}/cumulus4j-key-stores"
042 * to the java command will be resolved to "/tmp/cumulus4j-key-stores" on GNU+Linux.
043 * </p>
044 */
045 public static final String SYSTEM_PROPERTY_KEY_STORE_DIR = "cumulus4j.keyStoreDir";
046
047 private static File getUserHome()
048 {
049 String userHome = System.getProperty("user.home"); //$NON-NLS-1$
050 if (userHome == null)
051 throw new IllegalStateException("System property user.home is not set! This should never happen!"); //$NON-NLS-1$
052
053 return new File(userHome);
054 }
055
056 private Map<String, KeyStore> keyStoreID2keyStore = new HashMap<String, KeyStore>();
057
058 private Map<String, AppServerManager> keyStoreID2appServerManager = new HashMap<String, AppServerManager>();
059
060 private File getKeyStoreDir() throws IOException
061 {
062 String keyStoreDirSysPropVal = System.getProperty(SYSTEM_PROPERTY_KEY_STORE_DIR);
063 File keyStoreDir;
064
065 if (keyStoreDirSysPropVal == null || keyStoreDirSysPropVal.trim().isEmpty()) {
066 keyStoreDir = new File(getUserHome(), ".cumulus4j");
067 logger.info(
068 "getSingletons: System property '{}' is empty or not specified. Using default keyStoreDir '{}'.",
069 SYSTEM_PROPERTY_KEY_STORE_DIR, keyStoreDir.getAbsolutePath()
070 );
071 }
072 else {
073 String keyStoreDirSysPropValResolved = SystemPropertyUtil.resolveSystemProperties(keyStoreDirSysPropVal);
074 keyStoreDir = new File(keyStoreDirSysPropValResolved);
075 logger.info(
076 "getSingletons: System property '{}' was set to '{}'. Using keyStoreDir '{}'.",
077 new Object[] { SYSTEM_PROPERTY_KEY_STORE_DIR, keyStoreDirSysPropVal, keyStoreDir.getAbsolutePath() }
078 );
079 }
080
081 if (!keyStoreDir.isDirectory()) {
082 keyStoreDir.mkdirs();
083
084 if (!keyStoreDir.isDirectory())
085 throw new IOException("Creating directory \"" + keyStoreDir.getAbsolutePath() + "\" failed! Check permissions!");
086 }
087 return keyStoreDir;
088 }
089
090 /**
091 * Get the <code>KeyStore</code> identified by the given <code>keyStoreID</code>. If it does not exist,
092 * it is implicitely created.
093 * @param keyStoreID the identfier of the {@link KeyStore} to be returned. Must not be <code>null</code>.
094 * @return the <code>KeyStore</code> identified by the given <code>keyStoreID</code>.
095 * @throws IOException if reading from / writing to the local file system failed.
096 */
097 public synchronized KeyStore getKeyStore(String keyStoreID) throws IOException
098 {
099 if (keyStoreID == null)
100 throw new IllegalArgumentException("keyStoreID == null");
101
102 KeyStore keyStore = keyStoreID2keyStore.get(keyStoreID);
103 if (keyStore == null) {
104 File keyStoreFile = new File(getKeyStoreDir(), keyStoreID + ".keystore");
105 keyStore = new KeyStore(keyStoreID, keyStoreFile);
106 keyStoreID2keyStore.put(keyStoreID, keyStore);
107 }
108 return keyStore;
109 }
110
111 /**
112 * Get the <code>AppServerManager</code> that is assigned (in a 1-1-relation) to the {@link KeyStore}
113 * identified by the given ID.
114 *
115 * @param keyStoreID the identfier of the {@link KeyStore} whose <code>AppServerManager</code> shall be returned. Must not be <code>null</code>.
116 * @return the <code>AppServerManager</code> that is assigned (in a 1-1-relation) to the {@link KeyStore}
117 * identified by the given ID.
118 * @throws IOException if reading from / writing to the local file system failed.
119 */
120 public synchronized AppServerManager getAppServerManager(String keyStoreID) throws IOException
121 {
122 if (keyStoreID == null)
123 throw new IllegalArgumentException("keyStoreID == null");
124
125 AppServerManager appServerManager = keyStoreID2appServerManager.get(keyStoreID);
126 if (appServerManager == null) {
127 appServerManager = new AppServerManager(getKeyStore(keyStoreID));
128 keyStoreID2appServerManager.put(keyStoreID, appServerManager);
129 }
130 return appServerManager;
131 }
132 }