View Javadoc

1   package com.atlassian.config.db;
2   
3   import com.atlassian.config.ApplicationConfiguration;
4   import com.atlassian.config.ConfigurationException;
5   import com.atlassian.config.bootstrap.BootstrapException;
6   import org.apache.log4j.Category;
7   import org.apache.log4j.Logger;
8   
9   import javax.naming.InitialContext;
10  import javax.naming.NamingException;
11  import javax.sql.DataSource;
12  import java.sql.*;
13  import java.util.Properties;
14  
15  /**
16   * The DatabaseHelper class provides methods used during bootstrap. In order to be able to mock those methods, the
17   * functionality was componentized.
18   */
19  public class DatabaseHelper
20  {
21      private final static Logger log = Logger.getLogger(DatabaseHelper.class);
22  
23      /**
24       * Test whether the database's lower function supports non-ascii characters and sets a hibernate parameter in the
25       * application configuration. This serves as a workaround for postgres which does not support lower casing of
26       * non-ascii characters in certain versions. The property set in this method will be used in
27       * GeneralUtil.specialToLowerCase() to indicate whether the database supports the lowercasing or not. The property
28       * might not be set if the database does not support the query.
29       *
30       * @param databaseProperties
31       * @param applicationConfig
32       * @throws BootstrapException
33       */
34      public void setDatabaseLowerProperty(Properties databaseProperties, ApplicationConfiguration applicationConfig) throws BootstrapException
35      {
36          Connection conn = null;
37          try
38          {
39              if (isDirectConnection(databaseProperties))
40              {
41                  String driverClassName = databaseProperties.getProperty("hibernate.connection.driver_class");
42                  String databaseUrl = databaseProperties.getProperty("hibernate.connection.url");
43                  String userName = databaseProperties.getProperty("hibernate.connection.username");
44                  String password = databaseProperties.getProperty("hibernate.connection.password");
45  
46                  if (driverClassName != null)
47                      Class.forName(driverClassName);
48                  
49                  conn = DriverManager.getConnection(databaseUrl, userName, password);
50              }
51              else
52              {
53                  conn = getDatasource(databaseProperties.getProperty("hibernate.connection.datasource")).getConnection();
54              }
55  
56              Statement st = conn.createStatement();
57              // This query is not supported by all database (eg. HSQL). Howerver, since this is mainly a workaround for postgres, we don't care much.
58              String sqlQuery = "select lower('\u00dcbersicht')";
59              ResultSet rs = st.executeQuery(sqlQuery);
60              rs.next();
61              if (rs.getString(1).equals("\u00dcbersicht"))
62              {
63                  applicationConfig.setProperty("hibernate.database.lower_non_ascii_supported", Boolean.FALSE);
64              }
65              else
66              {
67                  applicationConfig.setProperty("hibernate.database.lower_non_ascii_supported", Boolean.TRUE);
68              }
69              applicationConfig.save();
70          }
71  
72          catch (SQLException e)
73          {
74              log.info("SQL query could not be excecuted: " + e, e);
75          }
76  
77          catch (ClassNotFoundException e)
78          {
79              log.error(e, e);
80          }
81  
82          catch (ConfigurationException e)
83          {
84              log.error("Configuration file could not be saved: ", e);
85          }
86  
87          finally
88          {
89              try
90              {
91                  if (conn == null)
92                  {
93                      log.error("Connection was null. We could not successfully connect to the specified database!");
94                  }
95  
96                  else
97                      conn.close();
98              }
99              catch (SQLException e)
100             {
101                 log.fatal("Could not close database connection opened for first test! Exception: " + e);
102             }
103         }
104     }
105 
106     public DataSource getDatasource(String ds) throws BootstrapException
107     {
108         DataSource dsrc = null;
109 
110         log.debug("datasource is " + ds);
111 
112         try
113         {
114             InitialContext ctx = new InitialContext();
115             dsrc = (DataSource) ctx.lookup(ds);
116 
117             if (dsrc == null)
118             {
119                 throw new NamingException("Could not locate " + ds);
120             }
121         }
122         catch (NamingException e)
123         {
124             log.error("Could not locate datasource: " + ds, e);
125             throw new BootstrapException("Could not locate datasource: " + ds, e);
126         }
127         catch (ClassCastException e)
128         {
129             log.error("Couldn't locate Datasource (" + ds + ") in the initial context. An object was bound to this name but whatever we found, it wasn't a Datasource: " + e);
130             throw new BootstrapException("Couldn't locate Datasource (" + ds + ") in the initial context. An object was bound to this name but whatever we found, it wasn't a Datasource: ", e);
131         }
132         return dsrc;
133     }
134 
135     private boolean isDirectConnection(Properties databaseProperties)
136     {
137         return databaseProperties.getProperty("hibernate.connection.datasource") == null;
138     }
139 }
140 
141