View Javadoc
1   /*
2    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
3    * The software in this package is published under the terms of the CPAL v1.0
4    * license, a copy of which has been included with this distribution in the
5    * LICENSE.txt file.
6    */
7   package org.mule.tck.util;
8   
9   import org.mule.util.ClassUtils;
10  import org.mule.util.FileUtils;
11  
12  import java.io.File;
13  import java.io.IOException;
14  import java.lang.reflect.Method;
15  import java.net.URL;
16  import java.sql.Connection;
17  import java.sql.Driver;
18  import java.sql.DriverManager;
19  import java.sql.SQLException;
20  import java.sql.Statement;
21  import java.util.Properties;
22  
23  import javax.sql.DataSource;
24  
25  public class MuleDerbyTestUtils
26  {
27      private static final String DERBY_DRIVER_CLASS = "org.apache.derby.jdbc.EmbeddedDriver";
28      private static final String DERBY_DATASOURCE_CLASS = "org.apache.derby.jdbc.EmbeddedDataSource";
29      
30      //class cannot be instantiated
31      private MuleDerbyTestUtils()
32      {
33          super();
34      }
35      
36      //by default, set the derby home to the target directory
37      public static String setDerbyHome()
38      {
39          return setDerbyHome("target");
40      }
41      
42      public static String setDerbyHome(String path)
43      {
44          File derbySystemHome = new File(System.getProperty("user.dir"), path);
45          System.setProperty("derby.system.home",  derbySystemHome.getAbsolutePath());
46          return derbySystemHome.getAbsolutePath();
47      }
48      
49      /**
50       * Properly shutdown an embedded Derby database
51       * 
52       * @throws SQLException
53       * @see <h href="http://db.apache.org/derby/docs/10.3/devguide/tdevdvlp20349.html">Derby docs</a>
54       */
55      public static void stopDatabase() throws SQLException
56      {
57          try
58          {
59              // force loading the driver so it's available even if no prior connection to the
60              // database was made
61              ClassUtils.instanciateClass(DERBY_DRIVER_CLASS);
62  
63              DriverManager.getConnection("jdbc:derby:;shutdown=true");
64          }
65          catch (SQLException sqlex)
66          {
67              // this exception is documented to be thrown upon shutdown
68              if (!"XJ015".equals(sqlex.getSQLState()))
69              {
70                  throw sqlex;
71              }
72          }
73          catch (Exception ex)
74          {
75              // this can only happen when the driver class is not in classpath. In this case, just
76              // throw up
77              throw new RuntimeException(ex);
78          }
79      }
80      
81      public static void cleanupDerbyDb(String databaseName) throws IOException, SQLException
82      {
83          cleanupDerbyDb(setDerbyHome(), databaseName);
84      }
85      
86      public static void cleanupDerbyDb(String derbySystemHome, String databaseName) throws IOException, SQLException
87      {
88          stopDatabase();
89          FileUtils.deleteTree(new File(derbySystemHome + File.separator + databaseName));
90      }
91      
92      /** 
93       * Start a previously created (and stopped) database 
94       */
95      public static void startDataBase(String databaseName) throws Exception
96      {
97          Driver derbyDriver = (Driver) ClassUtils.instanciateClass(DERBY_DRIVER_CLASS);
98  
99          Method connectMethod = derbyDriver.getClass().getMethod("connect", String.class, Properties.class);
100 
101         String connectionName = "jdbc:derby:" + databaseName;
102         connectMethod.invoke(derbyDriver, connectionName, null);
103     }
104 
105     /**
106      * Create a new embedded database
107      * @param databaseName
108      * @throws SQLException
109      */
110     public static void createDataBase(String databaseName) throws SQLException
111     {
112         createDataBase(databaseName, (String[]) null);
113     }
114 
115     /**
116      * Create a new embedded database
117      * @param databaseName
118      * @param creationSql - SQL used to create and populate initial database tables
119      * @throws SQLException
120      */
121     public static void createDataBase(String databaseName, String creationSql) throws SQLException
122     {
123         createDataBase(databaseName, new String[] { creationSql } );
124     }
125     
126     /**
127      * Create a new embedded database
128      * @param databaseName
129      * @param creationSql - SQL used to create and populate initial database tables
130      * @throws SQLException
131      */
132     public static void createDataBase(String databaseName, String[] creationSql) throws SQLException
133     {
134         createDataBase(databaseName, creationSql, null);
135     }
136     
137     /**
138      * Create a new embedded database
139      * @param databaseName
140      * @param creationSql - SQL used to create and populate initial database tables
141      * @throws SQLException
142      */
143     public static void createDataBase(String databaseName, String[] creationSql, Properties properties) throws SQLException
144     {
145         // Do not use the EmbeddedDriver class here directly to avoid compile time references
146         // on derby.jar
147         try
148         {
149             String connectionName = "jdbc:derby:" + databaseName + ";create=true";
150             /*
151              * EmbeddedDriver derbyDriver = new EmbeddedDriver();
152              * derbyDriver.connect(connectionName, null);
153              */
154             Driver derbyDriver = (Driver) ClassUtils.instanciateClass(DERBY_DRIVER_CLASS);
155             Method connectMethod = derbyDriver.getClass().getMethod("connect", String.class, Properties.class);
156             connectMethod.invoke(derbyDriver, connectionName, properties);
157 
158             if (creationSql != null)
159             {
160                 /*
161                  * EmbeddedDataSource embeddedDS = new EmbeddedDataSource();
162                  * embeddedDS.setDatabaseName(databaseName);
163                  */
164                 DataSource embeddedDS = (DataSource) ClassUtils.instanciateClass(DERBY_DATASOURCE_CLASS);
165                 Method m = embeddedDS.getClass().getMethod("setDatabaseName", String.class);
166                 m.invoke(embeddedDS, databaseName);
167 
168                 Connection con = null;
169                 try
170                 {
171                     con = embeddedDS.getConnection();
172                     Statement st = con.createStatement();
173                     for (String aCreationSql : creationSql)
174                     {
175                         st.execute(aCreationSql);
176                     }
177                     con.commit();
178                 }
179                 finally
180                 {
181                     if (con != null && !con.isClosed())
182                     {
183                         con.close();
184                     }
185                 }
186             }
187         }
188         catch (Exception ex)
189         {
190             throw new RuntimeException("Error creating the database " + databaseName, ex);
191         }
192     }
193     
194     public static String loadDatabaseName(String propertiesLocation, String propertyName) throws IOException
195     {
196         Properties derbyProperties = new Properties();
197         URL resource = ClassUtils.getResource(propertiesLocation, MuleDerbyTestUtils.class);
198         derbyProperties.load(resource.openStream());
199         return derbyProperties.getProperty(propertyName);
200     }
201 
202     public static void defaultDerbyCleanAndInit(String propertiesLocation, String propertyName) throws IOException, SQLException
203     {
204         String derbyHome = setDerbyHome();
205         String dbName = loadDatabaseName(propertiesLocation, propertyName);
206         cleanupDerbyDb(derbyHome, dbName);
207         createDataBase(dbName);
208     }
209 }
210 
211