1 package com.atlassian.activeobjects.internal;
2
3 import com.atlassian.activeobjects.ActiveObjectsPluginException;
4 import com.atlassian.activeobjects.config.ActiveObjectsConfiguration;
5 import com.atlassian.activeobjects.config.PluginKey;
6 import com.atlassian.activeobjects.external.ActiveObjects;
7 import com.atlassian.activeobjects.spi.ActiveObjectsPluginConfiguration;
8 import com.atlassian.activeobjects.spi.DatabaseType;
9 import com.atlassian.beehive.ClusterLockService;
10 import com.atlassian.sal.api.ApplicationProperties;
11 import com.atlassian.sal.api.transaction.TransactionTemplate;
12 import com.atlassian.tenancy.api.Tenant;
13 import net.java.ao.EntityManager;
14 import net.java.ao.builder.EntityManagerBuilder;
15 import org.slf4j.Logger;
16 import org.slf4j.LoggerFactory;
17
18 import java.io.File;
19
20 import static com.google.common.base.Preconditions.checkNotNull;
21
22 public final class DatabaseDirectoryAwareActiveObjectsFactory extends AbstractActiveObjectsFactory {
23 private static final String USER_NAME = "sa";
24 private static final String PASSWORD = "";
25
26 private final Logger log = LoggerFactory.getLogger(this.getClass());
27
28 private final ApplicationProperties applicationProperties;
29 private final ActiveObjectsPluginConfiguration dbConfiguration;
30
31 public DatabaseDirectoryAwareActiveObjectsFactory(ActiveObjectUpgradeManager aoUpgradeManager,
32 ApplicationProperties applicationProperties, ActiveObjectsPluginConfiguration dbConfiguration,
33 TransactionTemplate transactionTemplate, ClusterLockService clusterLockService) {
34 super(DataSourceType.HSQLDB, aoUpgradeManager, transactionTemplate, clusterLockService);
35 this.applicationProperties = checkNotNull(applicationProperties);
36 this.dbConfiguration = checkNotNull(dbConfiguration);
37 }
38
39 @Override
40 protected ActiveObjects doCreate(ActiveObjectsConfiguration configuration, Tenant tenant) {
41 final File dbDir = getDatabaseDirectory(getDatabasesDirectory(getHomeDirectory()), configuration.getPluginKey());
42 final EntityManager entityManager = getEntityManager(dbDir, configuration);
43 return new DatabaseDirectoryAwareEntityManagedActiveObjects(entityManager, new EntityManagedTransactionManager(entityManager));
44 }
45
46 private EntityManager getEntityManager(File dbDirectory, ActiveObjectsConfiguration configuration) {
47 return EntityManagerBuilder.url(getUri(dbDirectory)).username(USER_NAME).password(PASSWORD).auto()
48 .tableNameConverter(configuration.getNameConverters().getTableNameConverter())
49 .fieldNameConverter(configuration.getNameConverters().getFieldNameConverter())
50 .sequenceNameConverter(configuration.getNameConverters().getSequenceNameConverter())
51 .triggerNameConverter(configuration.getNameConverters().getTriggerNameConverter())
52 .indexNameConverter(configuration.getNameConverters().getIndexNameConverter())
53 .schemaConfiguration(configuration.getSchemaConfiguration())
54 .build();
55 }
56
57 private static String getUri(File dbDirectory) {
58 return "jdbc:hsqldb:file:" + dbDirectory.getAbsolutePath() + "/db;hsqldb.default_table_type=cached";
59 }
60
61 private File getDatabaseDirectory(File databasesDirectory, PluginKey pluginKey) {
62 final File dbDir = new File(databasesDirectory, pluginKey.asString());
63 if (!dbDir.exists() && !dbDir.mkdir()) {
64 throw new ActiveObjectsPluginException("Could not create database directory for plugin <" + pluginKey + "> at <" + dbDir.getAbsolutePath() + ">");
65 }
66
67 log.debug("Database directory {} initialised", dbDir);
68
69 return dbDir;
70 }
71
72 private File getDatabasesDirectory(File home) {
73 String path = dbConfiguration.getDatabaseBaseDirectory();
74 if (path.startsWith("/")) {
75 path = path.substring(1);
76 }
77 final File dbDirectory = new File(home, path);
78
79 if (dbDirectory.exists() && dbDirectory.isFile()) {
80 throw new ActiveObjectsPluginException("Database directory already exists, but is a file, at <" + dbDirectory.getPath() + ">");
81 }
82
83 if (!dbDirectory.exists() && !dbDirectory.mkdirs()) {
84 throw new ActiveObjectsPluginException("Could not create directory for database at <" + dbDirectory.getPath() + ">");
85 }
86
87 log.debug("ActiveObjects databases directory {} initialized", dbDirectory.getAbsolutePath());
88
89 return dbDirectory;
90 }
91
92 private File getHomeDirectory() {
93 final File home = applicationProperties.getHomeDirectory();
94 if (home == null) {
95 throw new ActiveObjectsPluginException("Home directory undefined!");
96 }
97 if (!home.exists() || !home.isDirectory()) {
98 throw new ActiveObjectsPluginException("The ActiveObjects plugin couldn't find a home directory at <" + home.getAbsolutePath() + ">");
99 }
100 return home;
101 }
102
103 private static final class DatabaseDirectoryAwareEntityManagedActiveObjects extends EntityManagedActiveObjects implements DatabaseDirectoryAware {
104 DatabaseDirectoryAwareEntityManagedActiveObjects(EntityManager entityManager, TransactionManager transactionManager) {
105 super(entityManager, transactionManager, DatabaseType.HSQL);
106 }
107 }
108 }