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.external.ActiveObjects;
6 import com.atlassian.activeobjects.spi.DatabaseType;
7 import com.atlassian.activeobjects.spi.TenantAwareDataSourceProvider;
8 import com.atlassian.activeobjects.spi.TransactionSynchronisationManager;
9 import com.atlassian.beehive.ClusterLockService;
10 import com.atlassian.sal.api.transaction.TransactionCallback;
11 import com.atlassian.sal.api.transaction.TransactionTemplate;
12 import com.atlassian.tenancy.api.Tenant;
13 import net.java.ao.EntityManager;
14
15 import javax.sql.DataSource;
16 import java.io.PrintWriter;
17 import java.sql.Connection;
18 import java.sql.SQLException;
19 import java.sql.SQLFeatureNotSupportedException;
20 import java.util.logging.Logger;
21
22 import static com.google.common.base.Preconditions.checkNotNull;
23
24
25
26
27 public final class DataSourceProviderActiveObjectsFactory extends AbstractActiveObjectsFactory {
28 private final EntityManagerFactory entityManagerFactory;
29 private final TenantAwareDataSourceProvider tenantAwareDataSourceProvider;
30
31 private TransactionSynchronisationManager transactionSynchronizationManager;
32
33 public DataSourceProviderActiveObjectsFactory(ActiveObjectUpgradeManager aoUpgradeManager,
34 EntityManagerFactory entityManagerFactory, TenantAwareDataSourceProvider tenantAwareDataSourceProvider,
35 TransactionTemplate transactionTemplate, ClusterLockService clusterLockService) {
36 super(DataSourceType.APPLICATION, aoUpgradeManager, transactionTemplate, clusterLockService);
37 this.entityManagerFactory = checkNotNull(entityManagerFactory);
38 this.tenantAwareDataSourceProvider = checkNotNull(tenantAwareDataSourceProvider);
39 }
40
41 public void setTransactionSynchronizationManager(TransactionSynchronisationManager transactionSynchronizationManager) {
42 this.transactionSynchronizationManager = transactionSynchronizationManager;
43 }
44
45
46
47
48
49
50
51
52
53
54 @Override
55 protected ActiveObjects doCreate(final ActiveObjectsConfiguration configuration, final Tenant tenant) {
56 return transactionTemplate.execute(new TransactionCallback<ActiveObjects>() {
57 @Override
58 public ActiveObjects doInTransaction() {
59 final DataSource dataSource = getDataSource(tenant);
60 final DatabaseType dbType = getDatabaseType(tenant);
61 final EntityManager entityManager = entityManagerFactory.getEntityManager(dataSource, dbType, tenantAwareDataSourceProvider.getSchema(tenant), configuration);
62 return new EntityManagedActiveObjects(entityManager,
63 new SalTransactionManager(transactionTemplate, entityManager, transactionSynchronizationManager), dbType);
64 }
65 });
66 }
67
68 private DataSource getDataSource(final Tenant tenant) {
69 final DataSource dataSource = tenantAwareDataSourceProvider.getDataSource(tenant);
70 if (dataSource == null) {
71 throw new ActiveObjectsPluginException("No data source defined in the application");
72 }
73 return new ActiveObjectsDataSource(dataSource);
74 }
75
76 private DatabaseType getDatabaseType(final Tenant tenant) {
77 final DatabaseType databaseType = tenantAwareDataSourceProvider.getDatabaseType(tenant);
78 if (databaseType == null) {
79 throw new ActiveObjectsPluginException("No database type defined in the application");
80 }
81 return databaseType;
82 }
83
84 public static class ActiveObjectsDataSource implements DataSource {
85 private final DataSource dataSource;
86
87 ActiveObjectsDataSource(DataSource dataSource) {
88 this.dataSource = dataSource;
89 }
90
91 @Override
92 public Connection getConnection() throws SQLException {
93 return dataSource.getConnection();
94 }
95
96 @Override
97 public Connection getConnection(String username, String password) throws SQLException {
98 throw new IllegalStateException("Not allowed to get a connection for non default username/password");
99 }
100
101
102
103
104 @Override
105 public int getLoginTimeout() throws SQLException {
106 return 0;
107 }
108
109
110
111
112 @Override
113 public void setLoginTimeout(int timeout) throws SQLException {
114 throw new UnsupportedOperationException("setLoginTimeout");
115 }
116
117
118
119
120 @Override
121 public PrintWriter getLogWriter() {
122 throw new UnsupportedOperationException("getLogWriter");
123 }
124
125
126
127
128 @Override
129 public void setLogWriter(PrintWriter pw) throws SQLException {
130 throw new UnsupportedOperationException("setLogWriter");
131 }
132
133 @Override
134 public <T> T unwrap(Class<T> tClass) throws SQLException {
135 throw new UnsupportedOperationException("unwrap");
136 }
137
138 @Override
139 public boolean isWrapperFor(Class<?> aClass) throws SQLException {
140 throw new UnsupportedOperationException("isWrapperFor");
141 }
142
143
144 public Logger getParentLogger() throws SQLFeatureNotSupportedException {
145 throw new SQLFeatureNotSupportedException();
146 }
147 }
148 }