-
Notifications
You must be signed in to change notification settings - Fork 0
/
DerbyResourceConfig.java
514 lines (453 loc) · 18.8 KB
/
DerbyResourceConfig.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
/*
* Copyright 2015 Development Entropy (deventropy.org) Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.deventropy.junithelper.derby;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import org.deventropy.shared.utils.ArgumentCheck;
/**
* Configurations to control the {@link EmbeddedDerbyResource}.
*
* <p>This class provides a fluid interface to build the config object to pass to the constructor of the resource.
* Example usage:
*
* <pre>
* EmbeddedDerbyResource derbyResource = new EmbeddedDerbyResource(
* DerbyResourceConfig.buildDefault().);
* </pre>
*
* <p>
* Some methods in this class, for example the methods setting the subSubProtocol, can be mutually exclusive and unset /
* alter values set by other methods. Certain configuration values have valid values as <code>null</code> and do not
* have corresponding <code>getDefaultXXX</code> methods.
* </p>
*
* @author Bindul Bhowmik
*/
public class DerbyResourceConfig {
// ---------------------------------------------------------------------------------- Database location and protocol
/**
* The database subsubprotocol for the JDBC URL
*/
private JdbcDerbySubSubProtocol subSubProtocol;
/**
* This is a multi purpose field; it is used as the end of the JDBC URL.
* <ul>
* <li>For a memory database, it is the database name;</li>
* <li>For a directory, it is the absolute / relative directory path;</li>
* <li>For a jar database, it is the path of the database inside the jar file;</li>
* </ul>
*/
private String databasePath;
/**
* Right now only used for the :jar: protocol for the jar file.
*/
private String jarDatabaseJarFile;
/**
* Skip the <code>create=true</code> attribute in the connection URL
*/
private boolean directoryDatabaseSkipCreate = false;
// --------------------------------------------- Parameters to control restoring a DB or creating one from a backup.
/**
* How are we restoring
*/
private DbCreateFromRestroreMode dbCreateFromRestoreMode;
/**
* Where are we restoring from
*/
private File dbCreateFromRestoreFrom;
/**
* Where are the archive logs
*/
private File dbRecoveryLogDevice;
// Logging controls
// TODO Complete configuring logging
private ErrorLoggingMode errorLoggingMode;
/**
* Post init scripts
*/
private List<String> postInitScripts;
/**
* Sets up a default config that can be used as is to start a database. See the appropriate
* <code>getDefaultXXX</code> methods to see the default values.
*
* @return A config setup with defaults.
*/
public static DerbyResourceConfig buildDefault () {
final DerbyResourceConfig config = new DerbyResourceConfig();
config.useInMemoryDatabase();
config.errorLoggingMode = getDefaultErrorLoggingMode();
// TODO Complete setting defaults
return config;
}
// -----------------------------------------------------------------------------------------------------------------
// START: Database location and protocol
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/**
* Returns the Jar database jar file path. Right now only used for the <code>:jar:</code> protocol for the jar file.
* Returns the file path of the jar file with the read only database.
*
* @return The jar file path
* @see #useJarSubSubProtocol(String, String)
* @see <a href="http://db.apache.org/derby/docs/10.12/devguide/cdevdeploy11201.html">Accessing a read-only database
* in a zip/jar file</a>
*/
public String getJarDatabaseJarFile () {
return jarDatabaseJarFile;
}
/**
* Returns the name/path of the database to use. This is a multi purpose field; it is used as the end of the JDBC
* URL.
* <ul>
* <li>For a memory database, it is the database name;</li>
* <li>For a directory, it is the absolute / relative directory path;</li>
* <li>For a jar database, it is the path of the database inside the jar file;</li>
* </ul>
*
* <p>Consult the documentation for Derby Sub Sub Protocols on database name formats and use.
*
* @return The database name.
* @see #getDefaultDatabasePathName()
* @see <a href="http://db.apache.org/derby/docs/10.11/ref/rrefjdbc37352.html">Syntax of db connection URLs</a>
*/
public String getDatabasePath () {
return databasePath;
}
/**
* For a database using the {@link JdbcDerbySubSubProtocol#Directory} subsubprotocol, skip the
* <code>create=true</code> attribute.
*
* @return the directoryDatabaseSkipCreate
*/
public boolean isDirectoryDatabaseSkipCreate () {
return directoryDatabaseSkipCreate;
}
/**
* Returns the default database name value, which is a UUID string.
* @return The default database name.
*/
public static String getDefaultDatabasePathName () {
return UUID.randomUUID().toString();
}
/**
* Will have the database start up as an in-memory database with a database name generated using
* {@link #getDefaultDatabasePathName()}.
*
* @return This instance
*/
public DerbyResourceConfig useInMemoryDatabase () {
resetSubSubProtocolSpecificValues();
this.subSubProtocol = JdbcDerbySubSubProtocol.Memory;
this.databasePath = getDefaultDatabasePathName();
return this;
}
/**
* Will have the database start up as an in-memory database with the specified database name.
*
* @param databaseName The name of the database
* @return This instance
*/
public DerbyResourceConfig useInMemoryDatabase (final String databaseName) {
ArgumentCheck.notNullOrEmpty(databaseName, "database name");
resetSubSubProtocolSpecificValues();
this.subSubProtocol = JdbcDerbySubSubProtocol.Memory;
this.databasePath = databaseName;
return this;
}
/**
* Use the <code>:directory:</code> Derby sub sub protocol. The database will be created in a directory named
* with the {@link #getDefaultDatabasePathName()} as the directory name.
*
* @return This instance
*/
public DerbyResourceConfig useDatabaseInDirectory () {
resetSubSubProtocolSpecificValues();
this.subSubProtocol = JdbcDerbySubSubProtocol.Directory;
this.databasePath = getDefaultDatabasePathName();
return this;
}
/**
* Use the <code>:directory:</code> Derby sub sub protocol, with the database in the specified
* <code>directorpyDbPath</code>. The path is either relative or absolute as interpreted by the Derby engine.
*
* @param directorpyDbPath The relative or absolute path where the database is created.
* @return This instance
*/
public DerbyResourceConfig useDatabaseInDirectory (final String directorpyDbPath) {
return useDatabaseInDirectory(directorpyDbPath, false);
}
/**
* Use the <code>:directory:</code> Derby sub sub protocol, with the database in the specified
* <code>directorpyDbPath</code>. The path is either relative or absolute as interpreted by the Derby engine. If the
* <code>skipCreateAttribute</code> attribute is set to <code>true</code>, the Database will be initialized without
* the <code>create=true</code> attribute.
*
* @param directorpyDbPath The relative or absolute path where the database is created.
* @param skipCreateAttribute Skip the <code>create=true</code> attribute in the connection URL
* @return This instance
*/
public DerbyResourceConfig useDatabaseInDirectory (final String directorpyDbPath,
final boolean skipCreateAttribute) {
ArgumentCheck.notNullOrEmpty(directorpyDbPath, "database path");
resetSubSubProtocolSpecificValues();
this.subSubProtocol = JdbcDerbySubSubProtocol.Directory;
this.databasePath = directorpyDbPath;
this.directoryDatabaseSkipCreate = skipCreateAttribute;
return this;
}
/**
* Use the <code>:jar:</code> Derby sub sub protocol. The jar file containing the read only database is a relative
* or absolute path in <code>jarFilePath</code> and the database path in the <code>dbPath</code> parameter. The
* <code>jarFilePath</code> is either relative or absolute as interpreted by the Derby engine.
*
* <p>For more format information see <a href="http://db.apache.org/derby/docs/10.12/devguide/cdevdeploy11201.html">
* Accessing a read-only database in a zip/jar file</a> and <a
* href="http://db.apache.org/derby/docs/10.12/devguide/cdevdvlp24155.html">Accessing databases from a jar or zip
* file</a> in the Derby Developer's guide.
*
* @param jarFilePath The relative or absolute path where the jar file with the read-only database.
* @param dbPath The path of the database inside the jar file.
* @return This instance
*/
public DerbyResourceConfig useJarSubSubProtocol (final String jarFilePath, final String dbPath) {
ArgumentCheck.notNullOrEmpty(jarFilePath, "Jar database path");
ArgumentCheck.notNullOrEmpty(dbPath, "database path");
resetSubSubProtocolSpecificValues();
this.subSubProtocol = JdbcDerbySubSubProtocol.Jar;
this.jarDatabaseJarFile = jarFilePath;
this.databasePath = dbPath;
return this;
}
/**
* Use the <code>:classpath:</code> Derby sub sub protocol. This allows access to a read only database in the
* classpath (see Derby documentation on <a href="http://db.apache.org/derby/docs/10.12/devguide/cdevdvlp91854.html"
* >Accessing databases from the classpath</a>). The database can be either in a Jar file or directly in the
* classpath.
*
* <p>The <code>dbPath</code> parameter designates the path to the database in the classpath. All databaseNames must
* begin with at least a slash, because you specify them "relative" to the classpath directory or archive. See also
* <a href="http://db.apache.org/derby/docs/10.12/ref/rrefjdbc37352.html">Syntax of database connection URLs for
* applications with embedded databases</a> and <a
* href="http://db.apache.org/derby/docs/10.12/devguide/tdevdeploy39856.html">Accessing databases within a jar file
* using the classpath</a>.
*
* @param dbPath The path of the database in the classpath
* @return This instance
*/
public DerbyResourceConfig useClasspathSubSubProtocol (final String dbPath) {
ArgumentCheck.notNullOrEmpty(dbPath, "database path");
resetSubSubProtocolSpecificValues();
this.subSubProtocol = JdbcDerbySubSubProtocol.Classpath;
this.databasePath = dbPath;
return this;
}
/**
* The JDBC sub-sub protocol to use for the embedded database.
*
* @return A valid Derby sub-sub protocol
*/
public JdbcDerbySubSubProtocol getSubSubProtocol () {
return this.subSubProtocol;
}
/**
* The default sub-sub protocol value.
* @return {@link JdbcDerbySubSubProtocol#Memory}
*/
public static JdbcDerbySubSubProtocol getDefaultSubSubProtocol () {
return JdbcDerbySubSubProtocol.Memory;
}
private void resetSubSubProtocolSpecificValues () {
this.databasePath = null;
this.jarDatabaseJarFile = null;
this.directoryDatabaseSkipCreate = false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// END: Database location and protocol
// -----------------------------------------------------------------------------------------------------------------
// -----------------------------------------------------------------------------------------------------------------
// START: Parameters to control restoring a DB or creating one from a backup.
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/**
* Controls if the database should be created or restored from a backup. A <code>null</code> value returned from
* this method means no restore. If this is not null, the location of the backup database is returned from
* {@link #getDbCreateFromRestoreFrom()}; and for roll-forward recovery, the log device is at
* {@link #getDbRecoveryLogDevice()}.
*
* <p>See the <a href="http://db.apache.org/derby/docs/10.12/adminguide/cadminhubbkup98797.html">Backing up and
* restoring a database</a> section of the Derby Administration guide for more information on means to backup and
* restore a database.
*
* @see EmbeddedDerbyResource#backupLiveDatabase(File, boolean, boolean, boolean)
*
* @return The mode to create / restore a database from a backup.
*/
public DbCreateFromRestroreMode getDbCreateFromRestoreMode () {
return dbCreateFromRestoreMode;
}
/**
* The location of the database backup to use. This is usually a full backup of the database.
*
* @see #getDbCreateFromRestoreMode()
*
* @return The database backup location.
*/
public File getDbCreateFromRestoreFrom () {
return dbCreateFromRestoreFrom;
}
/**
* Archive log location for roll-forward database recovery. See
* <a href="http://db.apache.org/derby/docs/10.12/adminguide/cadminrollforward.html">Roll-forward recovery</a> in
* the Derby administration guide to learn more about archive logging.
*
* @return The Database directory from which archive logs are available.
*/
public File getDbRecoveryLogDevice () {
return dbRecoveryLogDevice;
}
/**
* Restore a database from a backup location. If a database with the same name exists, the system will delete the
* database, copy it from the backup and restart it.
*
* @param dbBackupDir The backup location.
* @return This instance.
*/
public DerbyResourceConfig restoreDatabaseFrom (final File dbBackupDir) {
ArgumentCheck.notNull(dbBackupDir, "Database backup directory");
resetDbCreateRestoreConfigs ();
this.dbCreateFromRestoreMode = DbCreateFromRestroreMode.RestoreFrom;
this.dbCreateFromRestoreFrom = dbBackupDir;
return this;
}
/**
* Create a new database from a backup copy. If there is already a database with the same name in derby.system.home,
* an error will occur and the existing database will be left intact.
*
* @param dbBackupDir The location of the database backup.
* @return This instance.
*/
public DerbyResourceConfig createDatabaseFrom (final File dbBackupDir) {
ArgumentCheck.notNull(dbBackupDir, "Database backup directory");
resetDbCreateRestoreConfigs ();
this.dbCreateFromRestoreMode = DbCreateFromRestroreMode.CreateFrom;
this.dbCreateFromRestoreFrom = dbBackupDir;
return this;
}
/**
* Restore a database with roll forward recovery, optionally with archive logs. To see the steps involved in
* performing a roll forward recovery, see
* <a href="http://db.apache.org/derby/docs/10.12/adminguide/cadminrollforward.html">Roll Forward Recovery</a> in
* the Derby Administrative Guide.
*
* @param dbBackupDir The database backup location.
* @param recoveryLogDevice The archive log location.
* @return This instance.
*/
public DerbyResourceConfig recoverDatabaseFrom (final File dbBackupDir, final File recoveryLogDevice) {
ArgumentCheck.notNull(dbBackupDir, "Database backup directory");
ArgumentCheck.notNull(recoveryLogDevice, "Recovery log device");
resetDbCreateRestoreConfigs ();
this.dbCreateFromRestoreMode = DbCreateFromRestroreMode.RollForwardRecoveryFrom;
this.dbCreateFromRestoreFrom = dbBackupDir;
this.dbRecoveryLogDevice = recoveryLogDevice;
return this;
}
private void resetDbCreateRestoreConfigs () {
this.dbCreateFromRestoreMode = null;
this.dbCreateFromRestoreFrom = null;
this.dbRecoveryLogDevice = null;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// END: Parameters to control restoring a DB or creating one from a backup.
// -----------------------------------------------------------------------------------------------------------------
// -----------------------------------------------------------------------------------------------------------------
// START: Logging controls
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/**
* Sets the {@link #getErrorLoggingMode()} value to {@link ErrorLoggingMode#Null}; and clears other logging
* properties.
*
* @return This instance
*/
public DerbyResourceConfig useDevNullErrorLogging () {
this.errorLoggingMode = ErrorLoggingMode.Null;
//TODO clean out other values?
return this;
}
/**
* Sets the {@link #getErrorLoggingMode()} value to {@link ErrorLoggingMode#Default}; and clears other logging
* properties.
*
* @return This instance
*/
public DerbyResourceConfig useDefaultErrorLogging () {
this.errorLoggingMode = ErrorLoggingMode.Default;
//TODO clean out other values?
return this;
}
/**
* The configured error logging mode.
* @return the configured error logging mode
*/
public ErrorLoggingMode getErrorLoggingMode () {
return errorLoggingMode;
}
/**
* The default logging setup.
* @return {@link ErrorLoggingMode#Default}
*/
public static ErrorLoggingMode getDefaultErrorLoggingMode () {
return ErrorLoggingMode.Default;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// END: Logging controls
// -----------------------------------------------------------------------------------------------------------------
// -----------------------------------------------------------------------------------------------------------------
// START: Post init scripts
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/**
* Gets the configured post init scripts in the config; or an empty list.
* @return Post init scripts to execute
*/
public List<String> getPostInitScripts () {
if (null == postInitScripts) {
return Collections.emptyList();
}
return postInitScripts;
}
/**
* Adds a post init script to the config.
*
* <p>A post init script should refer to a file containing SQL DDL or DML statements that will be executed
* against the new derby instance. Script locations can be on the classpath or file system or on a HTTP(s)
* location, for format, see {@linkplain org.deventropy.shared.utils.UrlResourceUtil}.
*
* @param postInitScript A post init script to add
* @return this object
*/
public DerbyResourceConfig addPostInitScript (final String postInitScript) {
ArgumentCheck.notNullOrEmpty(postInitScript, "Post Init Script");
if (null == postInitScripts) {
postInitScripts = new ArrayList<>();
}
postInitScripts.add(postInitScript);
return this;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// END: Post init scripts
// -----------------------------------------------------------------------------------------------------------------
}