Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
JDBC-533 First implementation for SPI for Firebird Embedded
Defines draft jdp-2020-05: Firebird Embedded locator service provider, and initial implementation to load Firebird Embedded from the classpath.
- Loading branch information
1 parent
6eeb3d0
commit 9028f2c
Showing
7 changed files
with
660 additions
and
10 deletions.
There are no files selected for viewing
180 changes: 180 additions & 0 deletions
180
devdoc/jdp/jdp-2020-05-firebird-embedded-locator-service-provider.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,180 @@ | ||
# jdp-2020-05: Firebird Embedded locator service provider | ||
|
||
## Status | ||
|
||
- Draft | ||
- Implemented in: Jaybird 5 | ||
|
||
## Type | ||
|
||
- Feature-specification | ||
|
||
## Context | ||
|
||
Firebird can be run as an embedded database server. Jaybird supports using | ||
Firebird Embedded. However - especially since Firebird 3 - using Firebird | ||
Embedded is really cumbersome due to the number of libraries and other files you | ||
need to deploy together with the application. As a consequence it is hard to use | ||
Firebird Embedded with Jaybird. | ||
|
||
## Decision | ||
|
||
Jaybird will introduce a service provider interface, | ||
`org.firebirdsql.jna.embedded.spi.FirebirdEmbeddedProvider`, with packaging | ||
requirements that will enable Jaybird to locate and load Firebird Embedded | ||
library files from the classpath. | ||
|
||
Jaybird will load the embedded library of the first provider that was located on | ||
the classpath for the current platform that also installed successfully. Future | ||
versions of Jaybird may introduce more advanced features like selecting a | ||
library based on version requirements. | ||
|
||
### Open questions | ||
|
||
1. Will this work for using Firebird Embedded on Linux and MacOS? | ||
|
||
## Consequences | ||
|
||
Jaybird provides a service provider interface | ||
`org.firebirdsql.jna.embedded.spi.FirebirdEmbeddedProvider`. Implementations of | ||
this interface will be discovered through `java.util.ServiceLoader`. When | ||
creating an embedded connection, Jaybird will attempt to locate a suitable | ||
Firebird Embedded instance on the classpath and install it to a temporary | ||
location. It will then try and load this library before any other libraries on | ||
the search path. | ||
|
||
### Requirements for packaging Firebird Embedded | ||
|
||
Libraries or applications packaging Firebird Embedded for use by Jaybird should | ||
follow these requirements and recommendations: | ||
|
||
- The package name of the provider should be sufficiently unique for the version | ||
and platform. It is recommended that the Firebird version and target platform | ||
are included in the package name. This will allow multiple versions and | ||
platforms to coexist on the classpath, allowing for future extensions like | ||
selecting a specific Firebird version to load, and avoiding potential resource | ||
conflicts (loading the wrong resource). \ | ||
For example for a Firebird 3.0.5 targeting Windows 64 bit, a suitable package | ||
name would be `org.example.firebird_3_0_5.win32_x86_64`. | ||
- The files of the library must be inside the folder identified by the package | ||
of the provider class. \ | ||
For example, given the provider class | ||
`org.example.firebird_3_0_5.win32_x86_64.FirebirdEmbeddedProvider`, the files | ||
must be located in `org/example/firebird_3_0_5/win32_x86_64` or a sub-folder of | ||
that location. | ||
- The platform information reported by `FirebirdEmbeddedProvider.getPlaform` | ||
must use the conventions of [JNA](https://github.com/java-native-access/jna). | ||
The returned value must match the value of `com.sun.jna.Platform.RESOURCE_PREFIX`, | ||
for example for Windows 64 bit (x86), the platform is `win32-x86-64`, for Linux | ||
64 bit (x86), it is `linux-x86-64`. | ||
- The version information reported by `FirebirdEmbeddedProvider.getVersion()` | ||
should have the format as reported by `isc_info_firebird_version` and as | ||
expected by `GDSServerVersion`. That is, its format should be | ||
`<platform>-<type><majorVersion>.<minorVersion>.<variant>.<buildNum>[-<revision>] <serverName>`, | ||
where platform is a two-character platform identification string, Windows for | ||
example is "WI", type is one of the three characters: "V" - production version, | ||
"T" - beta version, "X" - development version. \ | ||
This is not a hard requirement, but failure to comply may exclude the | ||
implementation from being used in features like selecting a suitable Firebird | ||
Embedded version based on version requirements (such a feature does not exist | ||
yet). | ||
|
||
Some of the requirements for this service provider interface are documented | ||
in the interface `org.firebirdsql.jna.embedded.spi.FirebirdEmbeddedProvider`. | ||
|
||
The files Jaybird installs from the classpath will be marked for deletion on | ||
exit, but this is a best effort cleanup only. On Windows it is not possible to | ||
delete files that are in use, and it appears that Firebird does not close all | ||
libraries on shutdown. | ||
|
||
TODO: Clean up needs further refinement. | ||
|
||
### Example provider | ||
|
||
As an example, a provider for Firebird 3.0.5 on Windows 64 bit can be packaged | ||
as: | ||
|
||
``` | ||
/--META-INF | ||
| |--services | ||
| | \--org.firebirdsql.jna.embedded.spi.FirebirdEmbeddedProvider | ||
| \--MANIFEST.MF | ||
|--org | ||
\--example | ||
\--firebird_3_0_5 | ||
\--win32_x86_64 | ||
|--fbintl | ||
| |--fbintl.conf | ||
| \--fbintl.dll | ||
|--plugins | ||
| |--engine12.dll | ||
| |--udr_engine.conf | ||
| \--udr_engine.dll | ||
|--fbclient.dll | ||
|--firebird.conf | ||
|--firebird.msg | ||
|--FirebirdEmbeddedProvider.class | ||
|--ib_util.dll | ||
|--icudt52.dll | ||
|--icudt52l.dat | ||
|--icuin52.dll | ||
|--icuuc52.dll | ||
\--plugins.conf | ||
``` | ||
|
||
Where `META-INF/services/org.firebirdsql.jna.embedded.spi.FirebirdEmbeddedProvider` | ||
would contain: | ||
|
||
``` | ||
org.example.firebird_3_0_5.win32_x86_64.FirebirdEmbeddedProvider | ||
``` | ||
|
||
and `org.example.firebird_3_0_5.win32_x86_64.FirebirdEmbeddedProvider` would be: | ||
|
||
```java | ||
package org.example.firebird3_0_5.win32_x86_64; | ||
|
||
import java.util.Arrays; | ||
import java.util.Collection; | ||
|
||
public class FirebirdEmbeddedProvider | ||
implements org.firebirdsql.jna.embedded.spi.FirebirdEmbeddedProvider { | ||
|
||
@Override | ||
public String getLibraryEntryPoint() { | ||
return "fbclient.dll"; | ||
} | ||
|
||
@Override | ||
public String getPlatform() { | ||
return "win32-x86-64"; | ||
} | ||
|
||
@Override | ||
public String getVersion() { | ||
return "WI-V3.0.5.33220 Firebird 3.0"; | ||
} | ||
|
||
@Override | ||
public Collection<String> getResourceList() { | ||
return Arrays.asList( | ||
"intl/fbintl.conf", | ||
"intl/fbintl.dll", | ||
"plugins/engine12.dll", | ||
"plugins/legacy_auth.dll", | ||
"plugins/srp.dll", | ||
"plugins/udr_engine.conf", | ||
"plugins/udr_engine.dll", | ||
"fbclient.dll", | ||
"firebird.conf", | ||
"firebird.msg", | ||
"ib_util.dll", | ||
"icudt52.dll", | ||
"icudt52l.dat", | ||
"icuin52.dll", | ||
"icuuc52.dll", | ||
"plugins.conf" | ||
); | ||
} | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
67 changes: 67 additions & 0 deletions
67
src/jna-client/org/firebirdsql/jna/embedded/FirebirdEmbeddedLibrary.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
/* | ||
* Firebird Open Source JDBC Driver | ||
* | ||
* Distributable under LGPL license. | ||
* You may obtain a copy of the License at http://www.gnu.org/copyleft/lgpl.html | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* LGPL License for more details. | ||
* | ||
* This file was created by members of the firebird development team. | ||
* All individual contributions remain the Copyright (C) of those | ||
* individuals. Contributors to this file are either listed here or | ||
* can be obtained from a source control history command. | ||
* | ||
* All rights reserved. | ||
*/ | ||
package org.firebirdsql.jna.embedded; | ||
|
||
import java.nio.file.Path; | ||
|
||
/** | ||
* Information for locating a Firebird Embedded library. | ||
* | ||
* @author <a href="mailto:mrotteveel@users.sourceforge.net">Mark Rotteveel</a> | ||
* @since 5 | ||
*/ | ||
public final class FirebirdEmbeddedLibrary { | ||
|
||
private final Path entryPointPath; | ||
private final String version; | ||
|
||
FirebirdEmbeddedLibrary(Path entryPointPath, String version) { | ||
this.entryPointPath = entryPointPath; | ||
this.version = version; | ||
} | ||
|
||
/** | ||
* @return Path of the Firebird Embedded main library file | ||
*/ | ||
public Path getEntryPointPath() { | ||
return entryPointPath; | ||
} | ||
|
||
/** | ||
* Version of the Firebird Embedded library. | ||
* <p> | ||
* This version should be parseable by {@link org.firebirdsql.gds.impl.GDSServerVersion}, but this is not | ||
* guaranteed. | ||
* </p> | ||
* | ||
* @return Version of the Firebird Embedded library | ||
*/ | ||
public String getVersion() { | ||
return version; | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return "FirebirdEmbeddedLibrary{" + | ||
"entryPointPath=" + entryPointPath + | ||
", version='" + version + '\'' + | ||
'}'; | ||
} | ||
|
||
} |
Oops, something went wrong.