1 package com.atlassian.config.bootstrap;
2
3 import com.atlassian.config.ApplicationConfiguration;
4 import com.atlassian.config.ConfigurationException;
5 import com.atlassian.config.HomeLocator;
6 import com.atlassian.config.db.DatabaseDetails;
7 import com.atlassian.config.db.HibernateConfig;
8 import com.atlassian.config.db.HibernateConfigurator;
9 import com.atlassian.config.setup.SetupPersister;
10 import org.apache.commons.lang.StringUtils;
11 import org.slf4j.Logger;
12 import org.slf4j.LoggerFactory;
13
14 import javax.naming.InitialContext;
15 import javax.naming.NamingException;
16 import javax.sql.DataSource;
17 import java.sql.Connection;
18 import java.sql.DriverManager;
19 import java.sql.SQLException;
20 import java.sql.Statement;
21 import java.util.*;
22
23
24
25
26 public class DefaultAtlassianBootstrapManager implements AtlassianBootstrapManager
27 {
28
29 @Deprecated
30 public static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(DefaultAtlassianBootstrapManager.class);
31 private static final Logger privateLog = LoggerFactory.getLogger(DefaultAtlassianBootstrapManager.class);
32
33
34
35 protected boolean bootstrapped;
36 protected String bootstrapFailureReason;
37
38
39
40 private String operation;
41
42
43 private List tables;
44
45
46 protected ApplicationConfiguration applicationConfig;
47 protected SetupPersister setupPersister;
48 protected HomeLocator homeLocator;
49 protected HibernateConfigurator hibernateConfigurator;
50 protected HibernateConfig hibernateConfig;
51
52
53
54
55 public void init() throws BootstrapException
56 {
57
58
59
60
61
62 try
63 {
64 if (StringUtils.isNotEmpty(homeLocator.getHomePath()))
65 {
66 applicationConfig.setApplicationHome(homeLocator.getHomePath());
67 applicationConfig.setConfigurationFileName(homeLocator.getConfigFileName());
68
69 if (applicationConfig.configFileExists())
70 {
71 applicationConfig.load();
72 }
73
74 afterConfigurationLoaded();
75
76 setupPersister.setSetupType(applicationConfig.getSetupType());
77 if (SetupPersister.SETUP_STATE_COMPLETE.equals(setupPersister.getCurrentStep()))
78 {
79
80 if (!performPersistenceUpgrade())
81 {
82 return;
83 }
84
85 applicationConfig.setSetupComplete(true);
86 publishConfiguration();
87 }
88 }
89 else
90 {
91
92
93 privateLog.warn("Unable to set up application config: no home set");
94 }
95
96 finishBootstrapInitialisation();
97
98 bootstrapped = true;
99 }
100 catch (ConfigurationException e)
101 {
102 privateLog.error("Home is not configured properly: ", e);
103 bootstrapped = false;
104 bootstrapFailureReason = e.getMessage();
105 }
106 }
107
108 public void publishConfiguration()
109 {
110
111 }
112
113
114
115
116
117
118 public Object getProperty(String key)
119 {
120 Object o = null;
121 try
122 {
123 o = applicationConfig.getProperty(key);
124 }
125 catch (NullPointerException e)
126 {
127 privateLog.error("BootstrapManager was asked to fetch property ({}) and found a NullPointer", key);
128 }
129
130 return o;
131 }
132
133
134
135
136 public void setProperty(String key, Object value)
137 {
138 if (value == null)
139 {
140 applicationConfig.removeProperty(key);
141 }
142 else
143 {
144 applicationConfig.setProperty(key, value);
145 }
146 if (isSetupComplete())
147 {
148 publishConfiguration();
149 }
150 }
151
152 public boolean isPropertyTrue(String prop)
153 {
154 return "true".equals(getString(prop));
155 }
156
157
158
159
160 public void removeProperty(String key)
161 {
162 applicationConfig.removeProperty(key);
163 }
164
165
166
167
168 public String getString(String key)
169 {
170 return (String) applicationConfig.getProperty(key);
171 }
172
173 public String getFilePathProperty(String key)
174 {
175 return getString(key);
176 }
177
178
179
180
181 public Collection getPropertyKeys()
182 {
183 return applicationConfig.getProperties().keySet();
184 }
185
186
187
188
189 public Map getPropertiesWithPrefix(String prefix)
190 {
191 return applicationConfig.getPropertiesWithPrefix(prefix);
192 }
193
194 public void save() throws ConfigurationException
195 {
196 applicationConfig.save();
197 }
198
199 public String getConfiguredApplicationHome()
200 {
201 return homeLocator.getHomePath();
202 }
203
204
205
206
207
208
209 public boolean isSetupComplete()
210 {
211 return isBootstrapped() && applicationConfig.isSetupComplete();
212 }
213
214 public void setSetupComplete(boolean complete)
215 {
216 applicationConfig.setSetupComplete(complete);
217 }
218
219
220 public String getBuildNumber()
221 {
222 return applicationConfig.getBuildNumber();
223 }
224
225 public void setBuildNumber(String buildNumber)
226 {
227 applicationConfig.setBuildNumber(buildNumber);
228 }
229
230
231
232
233
234
235
236
237
238 public Properties getHibernateProperties()
239 {
240 Properties props = new Properties();
241 props.putAll(applicationConfig.getPropertiesWithPrefix("hibernate."));
242 return props;
243 }
244
245
246
247
248
249
250
251
252 public void bootstrapDatabase(DatabaseDetails dbDetails, boolean embedded)
253 throws BootstrapException
254 {
255 try
256 {
257 hibernateConfigurator.configureDatabase(dbDetails, embedded);
258 }
259 catch (ConfigurationException e)
260 {
261 privateLog.error("Could not successfully configure database:\n db: {}\n embedded = {}", dbDetails, embedded);
262 privateLog.error("ConfigurationException reads thus: ", e);
263 hibernateConfigurator.unconfigureDatabase();
264 throw new BootstrapException(e);
265 }
266
267 Connection conn = null;
268 try
269 {
270 conn = getTestDatabaseConnection(dbDetails);
271 if (!databaseContainsExistingData(conn))
272 {
273 throw new BootstrapException("Schema creation complete, but database tables don't seem to exist.");
274 }
275 }
276 finally
277 {
278 try
279 {
280 if (conn != null) conn.close();
281 }
282 catch (SQLException e)
283 {
284
285 }
286 }
287
288 postBootstrapDatabase();
289 }
290
291
292
293
294
295
296
297 public void bootstrapDatasource(String datasourceName, String hibernateDialect)
298 throws BootstrapException
299 {
300 try
301 {
302 hibernateConfigurator.configureDatasource(datasourceName, hibernateDialect);
303 }
304 catch (ConfigurationException e)
305 {
306 privateLog.error("Could not successfully configure datasource:\n db: {}\n dialect = {}", datasourceName, hibernateDialect);
307 privateLog.error("ConfigurationException reads thus: ", e);
308 hibernateConfigurator.unconfigureDatabase();
309 throw new BootstrapException(e);
310 }
311 Connection connection = null;
312 try
313 {
314 connection = getTestDatasourceConnection(datasourceName);
315 if (!databaseContainsExistingData(connection))
316 {
317 throw new BootstrapException("Schema creation complete, but tables could not be found.");
318 }
319 }
320 finally
321 {
322 try
323 {
324 if (connection != null) connection.close();
325 }
326 catch (SQLException e)
327 {
328
329 }
330 }
331 postBootstrapDatabase();
332 }
333
334
335
336
337
338
339
340 public Connection getTestDatabaseConnection(DatabaseDetails databaseDetails) throws BootstrapException
341 {
342 Connection conn = null;
343 try
344 {
345 Class.forName(databaseDetails.getDriverClassName());
346 conn = DriverManager.getConnection(getDbUrl(databaseDetails),
347 databaseDetails.getUserName(),
348 databaseDetails.getPassword());
349 if (conn == null)
350 {
351 throw new BootstrapException("Connection was null. We could not successfully connect to the specified database!");
352 }
353 return conn;
354 }
355 catch (SQLException e)
356 {
357 privateLog.error("Could not successfully test your database: ", e);
358 throw new BootstrapException(e);
359 }
360 catch (ClassNotFoundException e)
361 {
362 privateLog.error("Could not successfully test your database: ", e);
363 throw new BootstrapException(e);
364 }
365 }
366
367
368
369
370
371
372
373 public Connection getTestDatasourceConnection(String datasourceName) throws BootstrapException
374 {
375 DataSource dsrc;
376
377 privateLog.debug("datasource is {}", datasourceName);
378
379 try
380 {
381 InitialContext ctx = new InitialContext();
382 dsrc = (DataSource) ctx.lookup(datasourceName);
383
384 if (dsrc == null)
385 {
386 throw new NamingException("Could not locate " + datasourceName);
387 }
388 }
389 catch (NamingException e)
390 {
391 privateLog.error("Could not locate datasource: " + datasourceName, e);
392 throw new BootstrapException("Could not locate datasource: " + datasourceName, e);
393 }
394 catch (ClassCastException e)
395 {
396 privateLog.error("Couldn't locate Datasource (" + datasourceName + ") in the initial context. An object was bound to this name but whatever we found, it wasn't a Datasource: ", e);
397 throw new BootstrapException("Couldn't locate Datasource (" + datasourceName + ") in the initial context. An object was bound to this name but whatever we found, it wasn't a Datasource: ", e);
398 }
399
400 try
401 {
402 Connection conn = dsrc.getConnection();
403 conn.createStatement();
404 return conn;
405 }
406 catch (SQLException e)
407 {
408 privateLog.error("Couldn't open a connection on Datasource (" + datasourceName + "): ", e);
409 throw new BootstrapException("Couldn't open a connection on Datasource (" + datasourceName + "): ", e);
410 }
411 catch (NullPointerException e)
412 {
413 privateLog.error("Couldn't open a connection on Datasource (" + datasourceName + "): ", e);
414 throw new BootstrapException("Couldn't open a connection on Datasource (" + datasourceName + "): ", e);
415 }
416 }
417
418
419
420
421
422
423
424 public boolean databaseContainsExistingData(Connection connection)
425 {
426 for (Iterator iterator = getTables().iterator(); iterator.hasNext();)
427 {
428 String table = (String) iterator.next();
429 if (tableExists(connection, table))
430 return true;
431 }
432 return false;
433 }
434
435 private boolean tableExists(Connection conn, String table)
436 {
437 Statement st = null;
438 try
439 {
440 st = conn.createStatement();
441 st.executeQuery("select count(*) from " + table);
442 return true;
443 }
444 catch (SQLException e)
445 {
446 return false;
447 }
448 finally
449 {
450 if (st != null)
451 {
452 try
453 {
454 st.close();
455 }
456 catch (SQLException e)
457 {
458
459 }
460 }
461 }
462 }
463
464
465 public boolean isApplicationHomeValid()
466 {
467 return applicationConfig.isApplicationHomeValid();
468 }
469
470
471
472
473
474
475
476 protected boolean performPersistenceUpgrade()
477 {
478
479 return true;
480 }
481
482
483
484
485
486
487 protected void finishBootstrapInitialisation() throws ConfigurationException
488 {
489
490 }
491
492
493
494
495 protected String getDbUrl(DatabaseDetails dbDetails)
496 {
497 return dbDetails.getDatabaseUrl();
498 }
499
500
501
502
503 protected void postBootstrapDatabase() throws BootstrapException
504 {
505
506 }
507
508
509
510
511 protected void afterConfigurationLoaded() throws ConfigurationException
512 {
513
514 }
515
516
517
518
519 public void setApplicationConfig(ApplicationConfiguration applicationConfig)
520 {
521 this.applicationConfig = applicationConfig;
522 }
523
524 public void setHomeLocator(HomeLocator homeLocator)
525 {
526 this.homeLocator = homeLocator;
527 }
528
529 public void setSetupPersister(SetupPersister setupPersister)
530 {
531 this.setupPersister = setupPersister;
532 }
533
534 public HomeLocator getHomeLocator()
535 {
536 return homeLocator;
537 }
538
539 public ApplicationConfiguration getApplicationConfig()
540 {
541 return applicationConfig;
542 }
543
544 public String getApplicationHome()
545 {
546 return applicationConfig.getApplicationHome();
547 }
548
549 public SetupPersister getSetupPersister()
550 {
551 return setupPersister;
552 }
553
554
555
556
557 public boolean isBootstrapped()
558 {
559 return bootstrapped;
560 }
561
562 public String getOperation()
563 {
564 return operation;
565 }
566
567 public void setOperation(String operation)
568 {
569 this.operation = operation;
570 }
571
572 public HibernateConfigurator getHibernateConfigurator()
573 {
574 return hibernateConfigurator;
575 }
576
577 public void setHibernateConfigurator(HibernateConfigurator hibernateConfigurator)
578 {
579 this.hibernateConfigurator = hibernateConfigurator;
580 }
581
582 public HibernateConfig getHibernateConfig()
583 {
584 return hibernateConfig;
585 }
586
587 public void setHibernateConfig(HibernateConfig hibernateConfig)
588 {
589 this.hibernateConfig = hibernateConfig;
590 }
591
592 public String getBootstrapFailureReason()
593 {
594 return bootstrapFailureReason;
595 }
596
597 public List getTables()
598 {
599 return tables;
600 }
601
602 public void setTables(List tables)
603 {
604 this.tables = tables;
605 }
606 }