View Javadoc
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   * Creates a new instance of ActiveObjects given a dataSourceProvider
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       * Creates an {@link com.atlassian.activeobjects.external.ActiveObjects} using the
47       * {@link com.atlassian.activeobjects.spi.TenantAwareDataSourceProvider}
48       *
49       * @param configuration the configuration of active objects
50       * @return a new configured, ready to go ActiveObjects instance
51       * @throws ActiveObjectsPluginException if the data source obtained from the {@link com.atlassian.activeobjects.spi.TenantAwareDataSourceProvider}
52       *                                      is {@code null}
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          * Returns 0, indicating to use the default system timeout.
103          */
104         @Override
105         public int getLoginTimeout() throws SQLException {
106             return 0;
107         }
108 
109         /**
110          * Setting a login timeout is not supported.
111          */
112         @Override
113         public void setLoginTimeout(int timeout) throws SQLException {
114             throw new UnsupportedOperationException("setLoginTimeout");
115         }
116 
117         /**
118          * LogWriter methods are not supported.
119          */
120         @Override
121         public PrintWriter getLogWriter() {
122             throw new UnsupportedOperationException("getLogWriter");
123         }
124 
125         /**
126          * LogWriter methods are not supported.
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         // @Override Java 7 only
144         public Logger getParentLogger() throws SQLFeatureNotSupportedException {
145             throw new SQLFeatureNotSupportedException();
146         }
147     }
148 }