001package co.codewizards.cloudstore.local.db; 002 003import static co.codewizards.cloudstore.core.oio.OioFileFactory.*; 004import static co.codewizards.cloudstore.core.repo.local.LocalRepoManager.*; 005import static java.util.Objects.*; 006 007import java.io.IOException; 008import java.util.HashMap; 009import java.util.Map; 010import java.util.UUID; 011 012import co.codewizards.cloudstore.core.appid.AppId; 013import co.codewizards.cloudstore.core.oio.File; 014import co.codewizards.cloudstore.core.util.IOUtil; 015 016public abstract class AbstractDatabaseAdapter implements DatabaseAdapter { 017 /** 018 * The template for the name of the persistence-properties-file. 019 * <p> 020 * The variables (most importantly "${databaseAdapter.name}") are replaced by the coordinates of the 021 * actual database being used (e.g. databaseAdapter.name = "derby") and the file then copied from the JAR 022 * {@code co.codewizards.cloudstore.local} using the class-loader (e.g. resource "/cloudstore-persistence.derby.properties"). 023 * Since the class-loader is used, the file might exist in another JAR, too. 024 * <p> 025 * <b>Important:</b> This name is independent from the {@link AppId}, because obviously the resource in the JAR 026 * always has the same name - no matter in which application it is packaged! 027 * <p> 028 * <b>Important 2:</> The name of the generated file in the application's config directory is dependent on the {@code AppId}! 029 */ 030 private static final String PERSISTENCE_PROPERTIES_TEMPLATE_FILE_NAME = "cloudstore-persistence.${databaseAdapter.name}.properties"; 031 032 private AbstractDatabaseAdapterFactory factory; 033 034 private UUID repositoryId; 035 private File localRoot; 036 037 public AbstractDatabaseAdapterFactory getFactory() { 038 return factory; 039 } 040 public AbstractDatabaseAdapterFactory getFactoryOrFail() { 041 return requireNonNull(factory, "factory"); 042 } 043 protected void setFactory(AbstractDatabaseAdapterFactory factory) { 044 this.factory = factory; 045 } 046 047 @Override 048 public UUID getRepositoryId() { 049 return repositoryId; 050 } 051 public UUID getRepositoryIdOrFail() { 052 return requireNonNull(repositoryId, "repositoryId"); 053 } 054 @Override 055 public void setRepositoryId(UUID repositoryId) { 056 this.repositoryId = repositoryId; 057 } 058 059 @Override 060 public File getLocalRoot() { 061 return localRoot; 062 } 063 public File getLocalRootOrFail() { 064 return requireNonNull(localRoot, "localRoot"); 065 } 066 @Override 067 public void setLocalRoot(File localRoot) { 068 this.localRoot = localRoot; 069 } 070 071 protected File getMetaDir() { 072 return createFile(localRoot, META_DIR_NAME); 073 } 074 075 protected File getPersistencePropertiesFile() { 076 return createFile(getMetaDir(), PERSISTENCE_PROPERTIES_FILE_NAME); 077 } 078 079 protected void createPersistencePropertiesFile() { 080 final Map<String, Object> variables = new HashMap<>(); 081 variables.put("databaseAdapter.name", getFactoryOrFail().getName()); 082 final String resolvedPersistencePropertiesTemplateFileName = 083 IOUtil.replaceTemplateVariables(PERSISTENCE_PROPERTIES_TEMPLATE_FILE_NAME, variables); 084 085 try { 086 IOUtil.copyResource(this.getClass(), "/" + resolvedPersistencePropertiesTemplateFileName, 087 getPersistencePropertiesFile()); 088 } catch (final IOException e) { 089 throw new RuntimeException(e); 090 } 091 } 092 093 @Override 094 public void createPersistencePropertiesFileAndDatabase() throws Exception { 095 createPersistencePropertiesFile(); 096 createDatabase(); 097 } 098 099 protected abstract void createDatabase() throws Exception; 100 101 @Override 102 public void close() throws Exception { 103 // nothing to do - sub-classes may extend 104 } 105}