11package cloudgene .mapred .database .util ;
22
3- import genepi .io .FileUtil ;
4-
53import java .io .BufferedReader ;
6- import java .io .DataInputStream ;
74import java .io .File ;
85import java .io .FileInputStream ;
96import java .io .IOException ;
107import java .io .InputStream ;
118import java .io .InputStreamReader ;
129import java .net .URISyntaxException ;
10+ import java .net .URL ;
1311import java .sql .Connection ;
1412import java .sql .PreparedStatement ;
1513import java .sql .ResultSet ;
1614import java .sql .SQLException ;
1715import java .util .HashMap ;
1816import java .util .Map ;
1917
18+ import io .micronaut .core .annotation .NonNull ;
2019import org .slf4j .Logger ;
2120import org .slf4j .LoggerFactory ;
2221
2322public class DatabaseUpdater {
2423
2524 protected static final Logger log = LoggerFactory .getLogger (DatabaseUpdater .class );
2625
27- private final DatabaseConnector connector ;
28- private final Database database ;
29- private final String oldVersion ;
30- private final String currentVersion ;
31- private final String filename ;
32- private final InputStream updateFileAsStream ;
26+ private final @ NonNull Database database ;
27+ private final @ NonNull File versionFile ;
28+ private final @ NonNull URL updatesFile ;
29+ private final @ NonNull String currentVersion ;
30+
31+ private final @ NonNull DatabaseConnector connector ;
32+ private final @ NonNull Map <String , IUpdateListener > listeners ;
33+
34+ private final @ NonNull String oldVersion ;
3335 private final boolean needUpdate ;
34- private final Map <String , IUpdateListener > listeners ;
3536
36- public DatabaseUpdater (Database database , String filename , InputStream updateFileAsStream , String currentVersion ) {
37- this .filename = filename ;
37+ public DatabaseUpdater (
38+ @ NonNull Database database ,
39+ @ NonNull File versionFile ,
40+ @ NonNull URL updatesFile ,
41+ @ NonNull String currentVersion ) {
42+
3843 this .database = database ;
39- this .connector = database . getConnector () ;
40- this .updateFileAsStream = updateFileAsStream ;
44+ this .versionFile = versionFile ;
45+ this .updatesFile = updatesFile ;
4146 this .currentVersion = currentVersion ;
47+
48+ // TODO(Marc): database.getConnector() is nullable, but here we assume connector
49+ // is not null!
50+ this .connector = database .getConnector ();
4251 this .listeners = new HashMap <>();
4352
4453 if (isVersionTableAvailable ()) {
@@ -47,30 +56,38 @@ public DatabaseUpdater(Database database, String filename, InputStream updateFil
4756
4857 // Should not happen, since an entry is created when metadata table exists.
4958 if (oldVersion == null ) {
50- oldVersion = readVersion (filename );
59+ oldVersion = readVersion ();
5160 log .info ("Read current version from DB was not successful, read it from file: {}" , oldVersion );
5261 }
5362
5463 this .oldVersion = oldVersion ;
5564 } else {
5665 // check also file for backwards compatibility
57- this .oldVersion = readVersion (filename );
66+ this .oldVersion = readVersion ();
5867 log .info ("Read current version from file: {}" , oldVersion );
5968 }
6069
6170 log .info ("Current app version: {}" , currentVersion );
6271 needUpdate = (compareVersion (currentVersion , oldVersion ) > 0 );
6372 }
6473
65- public void addUpdate (String version , IUpdateListener listener ) {
74+ /**
75+ * Assigns {@code listener} as the one and only update listener for
76+ * {@code version}.
77+ * Replaces any existing listeners for the same version.
78+ */
79+ public void addListener (String version , IUpdateListener listener ) {
6680 listeners .put (version , listener );
6781 }
6882
83+ /**
84+ * If the database needs updating, updates it. Otherwise, inserts the current
85+ * version to the version table.
86+ */
6987 public boolean updateDB () {
70-
7188 if (needUpdate ()) {
7289 log .info ("Database needs update..." );
73- if (!update ()) {
90+ if (!update ()) { // TODO: update() ALWAYS returns true...
7491 log .error ("Updating database failed." );
7592 try {
7693 database .disconnect ();
@@ -98,12 +115,13 @@ public boolean updateDB() {
98115 return true ;
99116 }
100117
101- public boolean update () {
118+ // TODO(Marc): Only called from updateDB(). Consider merging.
119+ private boolean update () {
102120 if (needUpdate ) {
103121 log .info ("Updating database from {} to {}..." , oldVersion , currentVersion );
104122
105123 try {
106- readAndPrepareSqlClasspath (updateFileAsStream , oldVersion , currentVersion );
124+ readAndPrepareSqlClasspath (oldVersion , currentVersion );
107125 } catch (IOException | URISyntaxException | SQLException e ) {
108126 // TODO Auto-generated catch block
109127 e .printStackTrace ();
@@ -129,20 +147,27 @@ public boolean needUpdate() {
129147 return needUpdate ;
130148 }
131149
132- public void writeVersion (String newVersion ) {
150+ /**
151+ * Creates the database version table if not already present, and inserts
152+ * {@code version} as the latest version. If a version file exists, it is
153+ * deleted. Exceptions are ignored.
154+ *
155+ * @param version Newest application version (semver format expected).
156+ */
157+ private void writeVersion (String version ) {
133158 try {
134159 if (!isVersionTableAvailable ()) {
135160 createVersionTable ();
136161 }
137162
138163 Connection connection = connector .getDataSource ().getConnection ();
139164 PreparedStatement ps = connection .prepareStatement ("INSERT INTO database_versions (version) VALUES (?)" );
140- ps .setString (1 , newVersion );
165+ ps .setString (1 , version );
141166 ps .executeUpdate ();
142- log .info ("Version in DB updated to: {}" , newVersion );
167+ log .info ("Version in DB updated to: {}" , version );
143168
144- if (new File ( filename ) .exists ()) {
145- FileUtil . deleteFile ( filename );
169+ if (versionFile .exists ()) {
170+ versionFile . delete ( );
146171 log .info ("Deleted version.txt on file system." );
147172 }
148173
@@ -153,10 +178,13 @@ public void writeVersion(String newVersion) {
153178 }
154179 }
155180
156- public String readVersion (String versionFile ) {
157- File file = new File (versionFile );
158-
159- if (file .exists ()) {
181+ /**
182+ * If {@code versionFile} exists, returns its contents (expects semver version).
183+ * Defaults to {@code 0.0.0}.
184+ */
185+ @ NonNull
186+ private String readVersion () {
187+ if (versionFile .exists ()) {
160188 try {
161189 return readFileAsString (versionFile );
162190 } catch (Exception e ) {
@@ -167,7 +195,7 @@ public String readVersion(String versionFile) {
167195 }
168196 }
169197
170- public String readVersionDB () {
198+ private String readVersionDB () {
171199 String sql = "SELECT version FROM database_versions "
172200 + "WHERE updated_on = (SELECT MAX(updated_on) FROM database_versions) "
173201 + "ORDER BY updated_on, id DESC" ;
@@ -193,27 +221,33 @@ public String readVersionDB() {
193221 return version ;
194222 }
195223
196- public static String readFileAsString (String filename ) throws java .io .IOException , URISyntaxException {
197- InputStream is = new FileInputStream (filename );
224+ // TODO(Marc): Why is this here???
225+ private static String readFileAsString (File file ) throws IOException {
226+ InputStream is = new FileInputStream (file );
227+ InputStreamReader sr = new InputStreamReader (is );
228+ BufferedReader br = new BufferedReader (sr );
198229
199- DataInputStream in = new DataInputStream (is );
200- BufferedReader br = new BufferedReader (new InputStreamReader (in ));
201230 String strLine ;
202231 StringBuilder builder = new StringBuilder ();
203232
204233 while ((strLine = br .readLine ()) != null ) {
205234 builder .append (strLine );
206235 }
207236
208- in .close ();
237+ br .close ();
238+ sr .close ();
239+ is .close ();
240+
209241 return builder .toString ();
210242 }
211243
212- public String readAndPrepareSqlClasspath (InputStream filestream , String minVersion , String maxVersion )
213- throws java .io .IOException , URISyntaxException , SQLException {
244+ private String readAndPrepareSqlClasspath (String minVersion , String maxVersion )
245+ throws IOException , URISyntaxException , SQLException {
246+
247+ InputStream is = updatesFile .openStream ();
248+ InputStreamReader sr = new InputStreamReader (is );
249+ BufferedReader br = new BufferedReader (sr );
214250
215- DataInputStream in = new DataInputStream (filestream );
216- BufferedReader br = new BufferedReader (new InputStreamReader (in ));
217251 String strLine ;
218252 StringBuilder builder = new StringBuilder ();
219253 boolean reading = false ;
@@ -250,7 +284,10 @@ public String readAndPrepareSqlClasspath(InputStream filestream, String minVersi
250284 // last block
251285 executeSQLFile (builder .toString (), version );
252286
253- in .close ();
287+ br .close ();
288+ sr .close ();
289+ is .close ();
290+
254291 return builder .toString ();
255292 }
256293
0 commit comments