View Javadoc
1   package net.avcompris.commons3.core.it.utils;
2   
3   import static com.google.common.base.Preconditions.checkNotNull;
4   import static net.avcompris.commons3.it.utils.IntegrationTestUtils.getTestProperty;
5   
6   import java.io.IOException;
7   import java.sql.Connection;
8   import java.sql.DatabaseMetaData;
9   import java.sql.PreparedStatement;
10  import java.sql.ResultSet;
11  import java.sql.SQLException;
12  import java.util.concurrent.ExecutionException;
13  
14  import javax.sql.DataSource;
15  
16  import org.springframework.boot.jdbc.DataSourceBuilder;
17  
18  import com.google.common.cache.CacheBuilder;
19  import com.google.common.cache.CacheLoader;
20  import com.google.common.cache.LoadingCache;
21  import com.zaxxer.hikari.HikariDataSource;
22  
23  import net.avcompris.commons3.dao.DbTable;
24  import net.avcompris.commons3.dao.DbTablesUtils;
25  
26  public abstract class RDSTestUtils {
27  
28  	public static final String DEFAULT_PROPERTY_PREFIX_RDS = "rds";
29  
30  	private RDSTestUtils() {
31  
32  		throw new IllegalStateException();
33  	}
34  
35  	private static final CacheLoader<String, DataSource> DATASOURCES_LOADER = new CacheLoader<String, DataSource>() {
36  
37  		@Override
38  		public DataSource load(final String prefix) throws Exception {
39  
40  			return setUpDataSource(prefix);
41  		}
42  	};
43  
44  	private static final LoadingCache<String, DataSource> DATASOURCES = CacheBuilder.newBuilder()
45  			.build(DATASOURCES_LOADER);
46  
47  	private static DataSource setUpDataSource(final String prefix) throws SQLException, IOException {
48  
49  		final String dbURL = getTestProperty(prefix + ".url");
50  		final String dbUsername = getTestProperty(prefix + ".username");
51  		final String dbPassword = getTestProperty(prefix + ".password");
52  
53  		System.out.println(prefix + ".url: " + dbURL);
54  		System.out.println(prefix + ".username: " + dbUsername);
55  
56  		final DataSource dataSource = DataSourceBuilder.create() //
57  				.type(HikariDataSource.class) //
58  				.url(dbURL) //
59  				.username(dbUsername) //
60  				.password(dbPassword) //
61  				.build();
62  
63  		((HikariDataSource) dataSource).setConnectionInitSql("SET TIME ZONE 'UTC'");
64  
65  		return dataSource;
66  	}
67  
68  	public static DataSource getDataSource() throws SQLException, IOException {
69  
70  		return getDataSource(DEFAULT_PROPERTY_PREFIX_RDS);
71  	}
72  
73  	public static DataSource getDataSource(final String prefix) throws SQLException, IOException {
74  
75  		try {
76  
77  			return DATASOURCES.get(prefix);
78  
79  		} catch (final ExecutionException e) {
80  
81  			final Throwable cause = e.getCause();
82  
83  			if (cause == null) {
84  
85  				throw new RuntimeException(e);
86  
87  			} else if (cause instanceof SQLException) {
88  
89  				throw (SQLException) cause;
90  
91  			} else if (cause instanceof IOException) {
92  
93  				throw (IOException) cause;
94  
95  			} else if (cause instanceof RuntimeException) {
96  
97  				throw (RuntimeException) cause;
98  
99  			} else if (cause instanceof Error) {
100 
101 				throw (Error) cause;
102 
103 			} else {
104 
105 				throw new RuntimeException(e);
106 			}
107 		}
108 	}
109 
110 	/**
111 	 * Make sure the corresponding table exists in the database and complies to the
112 	 * description given in the XxxDbTable enum.
113 	 *
114 	 * @return the DB table’s name.
115 	 */
116 	public static String ensureDbTableName(final DbTable dbTable) throws IOException, SQLException {
117 
118 		return ensureDbTableName(dbTable, DEFAULT_PROPERTY_PREFIX_RDS);
119 	}
120 
121 	private static boolean hasDbTable(final DatabaseMetaData metadata, final String runtimeDbTableName)
122 			throws SQLException {
123 
124 		System.err.println("runtimeDbTableName: " + runtimeDbTableName);
125 
126 		try (ResultSet rs = metadata.getTables(null, null, runtimeDbTableName, null)) {
127 
128 			if (rs.next()) {
129 
130 				return true;
131 			}
132 		}
133 
134 		return false;
135 	}
136 
137 	private static boolean isDbTableCompatible(final DatabaseMetaData metadata, final String runtimeDbTableName,
138 			final DbTable dbTable) throws SQLException {
139 
140 		return false;
141 	}
142 
143 	private static String ensureDbTableName(final DbTable dbTable, final String prefix)
144 			throws IOException, SQLException {
145 
146 		checkNotNull(dbTable, "dbTable");
147 		checkNotNull(prefix, "prefix");
148 
149 		final String tableNamePrefix = getTestProperty(prefix + ".tableNamePrefix");
150 
151 		final String runtimeDbTableName = dbTable.getRuntimeDbTableNameWithPrefix(tableNamePrefix);
152 
153 		final DataSource dataSource = getDataSource(prefix);
154 
155 		try (Connection cxn = dataSource.getConnection()) {
156 
157 			final DatabaseMetaData metadata = cxn.getMetaData();
158 
159 			final boolean toCreate;
160 
161 			if (!hasDbTable(metadata, runtimeDbTableName)) {
162 
163 				toCreate = true;
164 
165 			} else if (isDbTableCompatible(metadata, runtimeDbTableName, dbTable)) {
166 
167 				toCreate = false;
168 
169 			} else {
170 
171 				for (final String sqlDropCommand : DbTablesUtils.composeSQLDropCommands(tableNamePrefix, dbTable)) {
172 
173 					System.out.println("Executing DROP command: " + sqlDropCommand);
174 
175 					try (PreparedStatement pstmt = cxn.prepareStatement(sqlDropCommand)) {
176 
177 						pstmt.executeUpdate();
178 
179 					} catch (final SQLException e) {
180 
181 						System.err.println(e);
182 					}
183 				}
184 
185 				toCreate = true;
186 			}
187 
188 			if (toCreate) {
189 
190 				for (final String sqlCreateCommand : DbTablesUtils.composeSQLCreateCommands(tableNamePrefix, dbTable)) {
191 
192 					System.out.println("Executing CREATE command: " + sqlCreateCommand);
193 
194 					try (PreparedStatement pstmt = cxn.prepareStatement(sqlCreateCommand)) {
195 
196 						pstmt.executeUpdate();
197 					}
198 				}
199 			}
200 		}
201 
202 		return runtimeDbTableName;
203 	}
204 }