001package co.codewizards.cloudstore.local; 002 003import static co.codewizards.cloudstore.core.io.StreamUtil.*; 004import static co.codewizards.cloudstore.core.oio.OioFileFactory.*; 005import static co.codewizards.cloudstore.core.repo.local.LocalRepoManager.*; 006import static co.codewizards.cloudstore.core.util.StringUtil.*; 007import static java.util.Objects.*; 008 009import java.io.InputStream; 010import java.sql.Connection; 011import java.sql.DriverManager; 012import java.sql.SQLException; 013import java.util.Map; 014import java.util.Properties; 015import java.util.UUID; 016 017import javax.jdo.PersistenceManagerFactory; 018 019import org.slf4j.Logger; 020import org.slf4j.LoggerFactory; 021 022import co.codewizards.cloudstore.core.oio.File; 023 024/** 025 * Factory creating JDBC connections to the repository's derby database. 026 * <p> 027 * <b>Important: This is for maintenance only!</b> Ordinary operations work with a {@link PersistenceManagerFactory} 028 * which is managed by {@link LocalRepoManagerImpl}. 029 * @author Marco หงุ่ยตระกูล-Schulze - marco at codewizards dot co 030 */ 031public class JdbcConnectionFactory { 032 private static final Logger logger = LoggerFactory.getLogger(JdbcConnectionFactory.class); 033 034 private final File localRoot; 035 036 private String connectionURL; 037 038 private String connectionDriverName; 039 040 private String connectionUserName; 041 042 private String connectionPassword; 043 044 public JdbcConnectionFactory(final File localRoot) { 045 this.localRoot = requireNonNull(localRoot, "localRoot"); 046 if (!localRoot.isDirectory()) 047 throw new IllegalArgumentException("The given localRoot is not an existing directory: " + localRoot.getAbsolutePath()); 048 049 initProperties(); 050 initDriverClass(); 051 } 052 053 private UUID readRepositoryIdFromRepositoryPropertiesFile() { 054 final File repositoryPropertiesFile = createFile(getMetaDir(), REPOSITORY_PROPERTIES_FILE_NAME); 055 try { 056 final Properties repositoryProperties = new Properties(); 057 try (InputStream in = castStream(repositoryPropertiesFile.createInputStream())) { 058 repositoryProperties.load(in); 059 } 060 final String repositoryIdStr = repositoryProperties.getProperty(PROP_REPOSITORY_ID); 061 if (isEmpty(repositoryIdStr)) 062 throw new IllegalStateException("repositoryProperties.getProperty(PROP_REPOSITORY_ID) is empty!"); 063 064 final UUID repositoryId = UUID.fromString(repositoryIdStr); 065 return repositoryId; 066 } catch (Exception x) { 067 throw new RuntimeException("Reading readRepositoryId from '" + repositoryPropertiesFile.getAbsolutePath() + "' failed: " + x, x); 068 } 069 } 070 071 private void initProperties() { 072 UUID repositoryId = readRepositoryIdFromRepositoryPropertiesFile(); 073 Map<String, String> persistenceProperties = new PersistencePropertiesProvider(repositoryId, localRoot).getPersistenceProperties(); 074 connectionDriverName = persistenceProperties.get(PersistencePropertiesEnum.CONNECTION_DRIVER_NAME.key); 075 connectionURL = persistenceProperties.get(PersistencePropertiesEnum.CONNECTION_URL.key); 076 connectionUserName = persistenceProperties.get(PersistencePropertiesEnum.CONNECTION_USER_NAME.key); 077 connectionPassword = persistenceProperties.get(PersistencePropertiesEnum.CONNECTION_PASSWORD.key); 078 }; 079 080 protected File getMetaDir() { 081 return createFile(localRoot, META_DIR_NAME); 082 } 083 084 private void initDriverClass() { 085 if (isEmpty(connectionDriverName)) 086 return; 087 088 try { 089 Class.forName(connectionDriverName); 090 } catch (Throwable e) { // Might theoretically be a link error (i.e. a sub-class of Error instead of Exception) => catch Throwable 091 logger.warn("initDriverClass" + e, e); 092 } 093 } 094 095 public Connection createConnection() throws SQLException { 096 if (isEmpty(connectionUserName) && isEmpty(connectionPassword)) 097 return DriverManager.getConnection(connectionURL); 098 else 099 return DriverManager.getConnection(connectionURL, connectionUserName, connectionPassword); 100 } 101}