001package runwar.mariadb4j; 002 003import java.io.File; 004import java.io.FileInputStream; 005import java.io.IOException; 006import java.io.InputStream; 007import java.net.URLClassLoader; 008import java.nio.file.Files; 009import runwar.logging.Logger; 010import static runwar.util.Reflection.invoke; 011import static runwar.util.Reflection.method; 012import static runwar.util.Reflection.load; 013 014public class MariaDB4jManager { 015 016 private File baseDir; 017 private File dataDir; 018 private Object server; 019 private String username, password, dbName = null; 020 private int port; 021 private URLClassLoader classLoader; 022 private static Logger log = Logger.getLogger("RunwarLogger"); 023 volatile boolean isShuttingDown; 024 025 public MariaDB4jManager(URLClassLoader _classLoader) { 026 classLoader = _classLoader; 027 } 028 029 public boolean canLoad() { 030 try { 031 log.debug("Checking for MariaDB4j class avaiability"); 032 load(classLoader, "ch.vorburger.mariadb4j.DBConfigurationBuilder"); 033 return true; 034 } catch (Exception e) { 035 log.debug("MariaDB4j classes are not available"); 036 return false; 037 } 038 } 039 040 public void start(int port, File baseDirectory, File dataDirectory, File importSQLFile) throws IOException { 041 this.port = port; 042 System.out.println("Starting MariaDB server on port " + port); 043 if (baseDirectory == null) { 044 baseDir = Files.createTempDirectory("mariadb4j").toFile(); 045 } else { 046 baseDir = baseDirectory; 047 } 048 System.out.println("MariaDB4j base directory " + baseDir.getAbsolutePath()); 049 if (dataDirectory == null) { 050 dataDir = new File(baseDir.getAbsolutePath(), "data-dir"); 051 } else { 052 dataDir = dataDirectory; 053 } 054 System.out.println("MariaDB4j datadirectory " + dataDir.getAbsolutePath()); 055 056 Class<?> builderClass = load(classLoader, "ch.vorburger.mariadb4j.DBConfigurationBuilder"); 057 if (builderClass == null) { 058 throw new RuntimeException("COULD NOT LOAD DB CLASS"); 059 } 060 Object builder = invoke(method(builderClass, "newBuilder"), null); 061 062 invoke(method(builderClass, "setPort", int.class), builder, port); 063 invoke(method(builderClass, "setBaseDir", String.class), builder, baseDir.getAbsolutePath()); 064 invoke(method(builderClass, "setDataDir", String.class), builder, dataDir.getAbsolutePath()); 065 066 Class<?> DBClass = load(classLoader, "ch.vorburger.mariadb4j.DB"); 067 ClassLoader OCL = Thread.currentThread().getContextClassLoader(); 068 try { 069 Thread.currentThread().setContextClassLoader(classLoader); 070 server = invoke( 071 method(DBClass, "newEmbeddedDB", load(classLoader, "ch.vorburger.mariadb4j.DBConfiguration")), 072 DBClass, method(builderClass, "build").invoke(builder)); 073 invoke(method(server.getClass(), "start"), server); 074 System.out.println("Started MariaDB4j server"); 075 if (importSQLFile != null) { 076 if (importSQLFile.exists()) { 077 // source(String resource, String username, String password, 078 // String dbName) 079 System.out.println("importing SQL file: " + importSQLFile.getAbsolutePath()); 080 run(importSQLFile, username, password, dbName); 081 } else { 082 log.error("Could not load MariaDB4j SQL file, file does not exist: " 083 + importSQLFile.getAbsolutePath()); 084 System.out.println("Could not load MariaDB4j SQL file, file does not exist: : " 085 + importSQLFile.getAbsolutePath()); 086 } 087 } 088 089 } catch (Exception e) { 090 e.printStackTrace(); 091 } finally { 092 Thread.currentThread().setContextClassLoader(OCL); 093 } 094 isShuttingDown = false; 095 // INSTANCE = this; 096 // final Thread mainThread = Thread.currentThread(); 097 // Runtime.getRuntime().addShutdownHook(new Thread() { 098 // public void run() { 099 // try { 100 // if(!isShuttingDown) 101 // INSTANCE.stop(); 102 // mainThread.join(); 103 // } catch ( Exception e) { 104 // e.printStackTrace(); 105 // } 106 // } 107 // }); 108 109 } 110 111 public void run(File file, String username, String password, String dbName) throws IOException { 112 FileInputStream from = new FileInputStream(file); 113 // run("source " + file.getAbsolutePath(), username, password, dbName); 114 run("[MariaDB4j] importing " + file.getAbsolutePath(), from, username, password, dbName); 115 } 116 117 public void createDB(String dbName) throws IOException { 118 ClassLoader OCL = Thread.currentThread().getContextClassLoader(); 119 try { 120 invoke(method(server.getClass(), "createDB", String.class), server, dbName); 121 } catch (Exception e) { 122 e.printStackTrace(); 123 } finally { 124 Thread.currentThread().setContextClassLoader(OCL); 125 } 126 } 127 128 public void run(String logInfoText, InputStream fromIS, String username, String password, String dbName) 129 throws IOException { 130 ClassLoader OCL = Thread.currentThread().getContextClassLoader(); 131 try { 132 java.lang.reflect.Method runMethod = method(server.getClass(), "run", String.class, InputStream.class, 133 String.class, String.class, String.class); 134 // dirty hack so we don't have to pass in a potentially huge string 135 runMethod.setAccessible(true); 136 invoke(runMethod, server, logInfoText, fromIS, username, password, dbName); 137 } catch (Exception e) { 138 try { 139 // this will print out the SQL exception if the problem was 140 // there 141 System.out.println("[MariaDB4j] Error running SQL: "); 142 System.out.print(" "); 143 System.out.println(e.getCause().getCause().getMessage()); 144 } catch (Exception e2) { 145 e.printStackTrace(); 146 } 147 } finally { 148 if (fromIS != null) { 149 fromIS.close(); 150 } 151 Thread.currentThread().setContextClassLoader(OCL); 152 } 153 } 154 155 public void run(String command, String username, String password, String dbName) { 156 System.out.println("[MariaDB4j] Running SQL command: " + command); 157 ClassLoader OCL = Thread.currentThread().getContextClassLoader(); 158 try { 159 invoke(method(server.getClass(), "run", String.class, String.class, String.class, String.class), server, 160 command, username, password, dbName); 161 } catch (Exception e) { 162 e.printStackTrace(); 163 } finally { 164 Thread.currentThread().setContextClassLoader(OCL); 165 } 166 } 167 168 public void stop() throws InterruptedException { 169 isShuttingDown = true; 170 System.out.println("*** Stopping MariaDB server on port " + port + " ..."); 171 try { 172 invoke(method(server.getClass(), "stop"), server); 173 System.out.println("*** Stopped MariaDB server on port " + port); 174 } catch (Exception e) { 175 System.out.println("*** Error stopping MariaDB server on port " + port); 176 e.printStackTrace(); 177 } 178 } 179 180 public String getUsername() { 181 return username; 182 } 183 184 public void setUsername(String username) { 185 this.username = username; 186 } 187 188 public String getPassword() { 189 return password; 190 } 191 192 public void setPassword(String password) { 193 this.password = password; 194 } 195 196 public String getDbName() { 197 return dbName; 198 } 199 200 public void setDbName(String dbName) { 201 this.dbName = dbName; 202 } 203 204}