2 * Copyright 2005 the original author or authors.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package org.wamblee.persistence;
19 import java.io.PrintWriter;
20 import java.sql.Connection;
21 import java.sql.DriverManager;
22 import java.sql.SQLException;
23 import java.util.Properties;
25 import junit.framework.TestCase;
27 import org.apache.derby.drda.NetworkServerControl;
28 import org.apache.derby.jdbc.ClientDriver;
29 import org.apache.derby.jdbc.EmbeddedDriver;
30 import org.apache.log4j.Logger;
31 import org.wamblee.io.FileSystemUtils;
34 * Derby database setup. The external JDBC url used to connect to a running
38 * jdbc:derby:net://localhost:1527/testdb
41 * and the driver class is
44 * com.ibm.db2.jcc.DB2Driver
47 * The following jars will have to be used <code>db2jcc.jar</code> and
48 * <code>db2jcc_license_c.jar</code>.
50 public class DerbyDatabase implements Database {
55 private static final Logger LOGGER = Logger.getLogger(DerbyDatabase.class);
60 private static final String USERNAME = "sa";
65 private static final String PASSWORD = "123";
68 * Poll interval for the checking the server status.
70 private static final int POLL_INTERVAL = 100;
73 * Maximum time to wait until the server has started or stopped.
75 private static final int MAX_WAIT_TIME = 10000;
78 * Database name to use.
80 private static final String DATABASE_NAME = "testdb";
83 * Path on the file system where derby files are stored.
85 private static final String DATABASE_PATH = "target/db/persistence/derby";
88 * Derby property required to set the file system path
89 * {@link #DATABASE_PATH}.
91 private static final String SYSTEM_PATH_PROPERTY = "derby.system.home";
94 * Constructs derby database class to allow creation of derby database
97 public DerbyDatabase() {
104 * @see org.wamblee.persistence.Database#start()
106 public void start() {
108 // just in case a previous run was killed without the
110 cleanPersistentStorage();
112 // set database path.
113 Properties lProperties = System.getProperties();
114 lProperties.put(SYSTEM_PATH_PROPERTY, DATABASE_PATH);
116 Class.forName("org.apache.derby.jdbc.EmbeddedDriver").newInstance();
120 waitUntilStartedOrStopped(true);
122 // Force creation of the database.
123 Connection lConnection = createConnection();
125 } catch (Exception e) {
126 throw new RuntimeException("Problem starting database", e);
131 * Waits until the database server has started or stopped.
134 * If true, waits until the server is up, if false, waits until
135 * the server is down.
136 * @throws InterruptedException
138 private void waitUntilStartedOrStopped(boolean aStarted)
139 throws InterruptedException {
142 while (aStarted != isStarted()) {
143 Thread.sleep(POLL_INTERVAL);
144 lWaited += POLL_INTERVAL;
146 if (lWaited > MAX_WAIT_TIME) {
147 throw new RuntimeException(
148 "Derby database did not start within " + MAX_WAIT_TIME
155 * Checks if the database server has started or not.
157 * @return True if started, false otherwise.
159 private boolean isStarted() {
164 } catch (Exception e) {
170 * Gets the controller for the database server.
172 * @return Controller.
175 private NetworkServerControl getControl() throws Exception {
176 return new NetworkServerControl();
183 private void runDatabase() {
185 getControl().start(new PrintWriter(System.out));
186 } catch (Exception e) {
187 throw new RuntimeException(e);
194 * @see org.wamblee.persistence.Database#getJdbcUrl()
196 public String getJdbcUrl() {
197 return getBaseJdbcUrl()
198 + ";create=true;retrieveMessagesFromServerOnGetMessage=true;";
201 private String getBaseJdbcUrl() {
202 return "jdbc:derby:" + DATABASE_NAME;
208 * @see org.wamblee.persistence.Database#getExternalJdbcUrl()
210 public String getExternalJdbcUrl() {
211 return "jdbc:derby:net://localhost:1527/" + DATABASE_NAME;
215 * Shuts down the derby database and cleans up all created files.
218 private void shutdownDerby() {
220 DriverManager.getConnection("jdbc:derby:;shutdown=true");
221 throw new RuntimeException("Derby did not shutdown, "
222 + " should always throw exception at shutdown");
223 } catch (Exception e) {
224 LOGGER.info("Derby has been shut down.");
231 * @see org.wamblee.persistence.Database#getDriverClassName()
233 public String getDriverClassName() {
234 return ClientDriver.class.getName();
238 * Gets the user name.
240 public String getUsername() {
249 public String getPassword() {
256 * @see org.wamblee.persistence.Database#createConnection()
258 public Connection createConnection() throws SQLException {
259 Connection c = DriverManager.getConnection(getJdbcUrl(), getUsername(),
266 * Stops the derby database and cleans up all derby files.
270 // shutdown network server.
271 getControl().shutdown();
272 waitUntilStartedOrStopped(false);
274 // shutdown inmemory access.
276 cleanPersistentStorage();
277 } catch (Exception e) {
278 LOGGER.warn("Problem stopping database", e);
283 * Cleans up persistent storage of Derby.
285 private void cleanPersistentStorage() {
286 File lFile = new File(DATABASE_PATH);
288 if (lFile.isFile()) {
289 TestCase.fail("A regular file by the name " + DATABASE_PATH
290 + " exists, clean this up first");
293 if (!lFile.isDirectory()) {
294 return; // no-op already cleanup up.
297 FileSystemUtils.deleteDirRecursively(DATABASE_PATH);