Skip to content

Commit

Permalink
Make slf4j optional, fall back on j.u.logging
Browse files Browse the repository at this point in the history
In order to avoid the hard dependency on slf4j, this patch
abstracts the Logger interface and LoggerFactory factory to fall
back on a java.util.logging-based implementation if slf4j is not
present.

Fixes #1094
  • Loading branch information
headius committed Sep 19, 2024
1 parent 02bac1a commit 580932e
Show file tree
Hide file tree
Showing 13 changed files with 172 additions and 35 deletions.
9 changes: 2 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ DOCKER_RUN_OPTS=--rm
MVN:=mvn
CODESIGN:=docker run $(DOCKER_RUN_OPTS) -v $$PWD:/workdir gotson/rcodesign sign
SRC:=src/main/java
JAVA_CLASSPATH:=$(TARGET)/classpath/slf4j-api.jar
SQLITE_OUT:=$(TARGET)/$(sqlite)-$(OS_NAME)-$(OS_ARCH)
SQLITE_OBJ?=$(SQLITE_OUT)/sqlite3.o
SQLITE_ARCHIVE:=$(TARGET)/$(sqlite)-amal.zip
Expand Down Expand Up @@ -44,19 +43,15 @@ $(SQLITE_UNPACKED): $(SQLITE_ARCHIVE)
(mv $(TARGET)/tmp.$(version)/$(SQLITE_AMAL_PREFIX) $(TARGET) && rmdir $(TARGET)/tmp.$(version)) || mv $(TARGET)/tmp.$(version)/ $(TARGET)/$(SQLITE_AMAL_PREFIX)
touch $@

$(JAVA_CLASSPATH):
@mkdir -p $(@D)
curl -L -f -o$@ https://search.maven.org/remotecontent?filepath=org/slf4j/slf4j-api/1.7.36/slf4j-api-1.7.36.jar

$(TARGET)/common-lib/org/sqlite/%.class: src/main/java/org/sqlite/%.java
@mkdir -p $(@D)
$(JAVAC) -source 1.6 -target 1.6 -sourcepath $(SRC) -d $(TARGET)/common-lib $<

jni-header: $(TARGET)/common-lib/NativeDB.h

$(TARGET)/common-lib/NativeDB.h: src/main/java/org/sqlite/core/NativeDB.java $(JAVA_CLASSPATH)
$(TARGET)/common-lib/NativeDB.h: src/main/java/org/sqlite/core/NativeDB.java
@mkdir -p $(TARGET)/common-lib
$(JAVAC) -cp $(JAVA_CLASSPATH) -d $(TARGET)/common-lib -sourcepath $(SRC) -h $(TARGET)/common-lib src/main/java/org/sqlite/core/NativeDB.java
$(JAVAC) -d $(TARGET)/common-lib -sourcepath $(SRC) -h $(TARGET)/common-lib src/main/java/org/sqlite/core/NativeDB.java
mv target/common-lib/org_sqlite_core_NativeDB.h target/common-lib/NativeDB.h

test:
Expand Down
12 changes: 4 additions & 8 deletions Makefile.common
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,20 @@ JAVAC := "$$JAVA_HOME/bin/javac"
JAVAH := "$$JAVA_HOME/bin/javah"

TARGET := target
SRC:=src/main/java
OSINFO_CLASS := org.sqlite.util.OSInfo
OSINFO_PROG := lib/org/sqlite/util/OSInfo.class
JAVA_CLASSPATH:=$(TARGET)/classpath/slf4j-api.jar

## building OSInfo.java
ifeq ("$(wildcard $(OSINFO_PROG))","")
$(info Building OSInfo tool)
$(shell mkdir -p $(TARGET)/classpath)
$(shell curl -L -f -o$(JAVA_CLASSPATH) https://search.maven.org/remotecontent?filepath=org/slf4j/slf4j-api/1.7.36/slf4j-api-1.7.36.jar)
$(shell $(JAVAC) -cp $(JAVA_CLASSPATH) -sourcepath $(SRC) -d lib src/main/java/org/sqlite/util/OSInfo.java)
$(shell $(JAVAC) -cp src/main/java -d lib src/main/java/org/sqlite/util/OSInfo.java)
endif

ifndef OS_NAME
OS_NAME := $(shell $(JAVA) -cp lib:$(JAVA_CLASSPATH) $(OSINFO_CLASS) --os)
OS_NAME := $(shell $(JAVA) -cp lib $(OSINFO_CLASS) --os)
endif
ifndef OS_ARCH
OS_ARCH := $(shell $(JAVA) -cp lib:$(JAVA_CLASSPATH) $(OSINFO_CLASS) --arch)
OS_ARCH := $(shell $(JAVA) -cp lib $(OSINFO_CLASS) --arch)
endif

# Windows uses different path separators
Expand Down Expand Up @@ -59,7 +55,7 @@ ifeq (,$(findstring $(strip $(target)),$(known_targets)))
target := Default
endif

$(info Will build using target: $(target) (detected os: $(OS_NAME), arch: $(OS_ARCH)))
$(info Will build using target: $(target) (detected os: $(OS_NAME) arch: $(OS_ARCH)))

# cross-compilation toolchain prefix (e.g. "arm-linux-gnueabi-")
CROSS_PREFIX :=
Expand Down
7 changes: 3 additions & 4 deletions README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,18 @@ SQLite JDBC is a library for accessing SQLite databases through the JDBC API. Fo

. <<Download,Download>> `sqlite-jdbc-{project-version}.jar`
then append this jar file into your classpath.
. https://search.maven.org/remotecontent?filepath=org/slf4j/slf4j-api/1.7.36/slf4j-api-1.7.36.jar[Download] `slf4j-api-1.7.36.jar` then append this jar file into your classpath.
. Open a SQLite database connection from your code. (see the example below)

=== Example usage

Assuming `sqlite-jdbc-{project-version}.jar` and `slf4j-api-1.7.36.jar` are placed in the current directory.
Assuming `sqlite-jdbc-{project-version}.jar` is placed in the current directory.

[source,shell,subs="attributes+"]
----
> javac Sample.java
> java -classpath ".;sqlite-jdbc-{project-version}.jar;slf4j-api-1.7.36.jar" Sample # in Windows
> java -classpath ".;sqlite-jdbc-{project-version}.jar" Sample # in Windows
or
> java -classpath ".:sqlite-jdbc-{project-version}.jar:slf4j-api-1.7.36.jar" Sample # in macOS or Linux
> java -classpath ".:sqlite-jdbc-{project-version}.jar" Sample # in macOS or Linux
name = leo
id = 1
name = yui
Expand Down
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,7 @@
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.36</version>
<scope>compile</scope>
</dependency>
<!--
This dependency makes compilation on non-GraalVM versions possible.
Expand Down
8 changes: 4 additions & 4 deletions src/main/java/org/sqlite/JDBC.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@

import java.sql.*;
import java.util.Properties;
import java.util.logging.Logger;
import org.slf4j.LoggerFactory;
import org.sqlite.jdbc4.JDBC4Connection;
import org.sqlite.util.Logger;
import org.sqlite.util.LoggerFactory;

public class JDBC implements Driver {
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(JDBC.class);
private static final Logger logger = LoggerFactory.getLogger(JDBC.class);
public static final String PREFIX = "jdbc:sqlite:";

static {
Expand All @@ -49,7 +49,7 @@ public boolean jdbcCompliant() {
return false;
}

public Logger getParentLogger() throws SQLFeatureNotSupportedException {
public java.util.logging.Logger getParentLogger() throws SQLFeatureNotSupportedException {
// TODO
return null;
}
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/org/sqlite/SQLiteJDBCLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@
import java.util.Properties;
import java.util.UUID;
import java.util.stream.Stream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sqlite.util.LibraryLoaderUtil;
import org.sqlite.util.Logger;
import org.sqlite.util.LoggerFactory;
import org.sqlite.util.OSInfo;
import org.sqlite.util.StringUtils;

Expand Down
4 changes: 2 additions & 2 deletions src/main/java/org/sqlite/core/NativeDB.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.sql.SQLException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sqlite.BusyHandler;
import org.sqlite.Collation;
import org.sqlite.Function;
import org.sqlite.ProgressHandler;
import org.sqlite.SQLiteConfig;
import org.sqlite.SQLiteJDBCLoader;
import org.sqlite.util.Logger;
import org.sqlite.util.LoggerFactory;

/** This class provides a thin JNI layer over the SQLite3 C API. */
public final class NativeDB extends DB {
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/org/sqlite/jdbc3/JDBC3DatabaseMetaData.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sqlite.SQLiteConnection;
import org.sqlite.core.CoreDatabaseMetaData;
import org.sqlite.core.CoreStatement;
import org.sqlite.jdbc3.JDBC3DatabaseMetaData.ImportedKeyFinder.ForeignKey;
import org.sqlite.util.Logger;
import org.sqlite.util.LoggerFactory;
import org.sqlite.util.QueryUtils;
import org.sqlite.util.StringUtils;

Expand Down
4 changes: 2 additions & 2 deletions src/main/java/org/sqlite/jdbc3/JDBC3Statement.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@
import java.sql.SQLWarning;
import java.sql.Statement;
import java.util.Arrays;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sqlite.ExtendedCommand;
import org.sqlite.ExtendedCommand.SQLExtension;
import org.sqlite.SQLiteConnection;
import org.sqlite.core.CoreStatement;
import org.sqlite.core.DB;
import org.sqlite.core.DB.ProgressObserver;
import org.sqlite.util.Logger;
import org.sqlite.util.LoggerFactory;

public abstract class JDBC3Statement extends CoreStatement {

Expand Down
20 changes: 20 additions & 0 deletions src/main/java/org/sqlite/util/Logger.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.sqlite.util;

/**
* A simple internal Logger interface.
*/
public interface Logger {
boolean isTraceEnabled();

void trace(String format, Object o1, Object o2);

void info(String format, Object o1, Object o2);

void warn(String msg);

void error(String message, Throwable t);

void error(String format, Object o1, Throwable t);

void error(String format, Object o1, Object o2, Throwable t);
}
130 changes: 130 additions & 0 deletions src/main/java/org/sqlite/util/LoggerFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package org.sqlite.util;

import java.text.MessageFormat;

/**
* A factory for {@link Logger} instances that uses SLF4J if present, falling back on a java.util.logging implementation
* otherwise.
*/
public class LoggerFactory {
static final boolean USE_SLF4J;

static {
boolean useSLF4J;
try {
Class.forName("org.slf4j.Logger");
useSLF4J = true;
} catch (Exception e) {
useSLF4J = false;
}
USE_SLF4J = useSLF4J;
}

/**
* Get a {@link Logger} instance for the given host class.
*
* @param hostClass the host class from which log messages will be issued
* @return a Logger
*/
public static Logger getLogger(Class<?> hostClass) {
if (USE_SLF4J) {
return new SLF4JLogger(hostClass);
}

return new JDKLogger(hostClass);
}

private static class JDKLogger implements Logger {
final java.util.logging.Logger logger;

public JDKLogger(Class<?> hostClass) {
logger = java.util.logging.Logger.getLogger(hostClass.getCanonicalName());
}

@Override
public boolean isTraceEnabled() {
return logger.isLoggable(java.util.logging.Level.FINEST);
}

@Override
public void trace(String format, Object o1, Object o2) {
if (logger.isLoggable(java.util.logging.Level.FINEST)) {
logger.log(java.util.logging.Level.FINEST, MessageFormat.format(format, o1, o2));
}
}

@Override
public void info(String format, Object o1, Object o2) {
if (logger.isLoggable(java.util.logging.Level.INFO)) {
logger.log(java.util.logging.Level.INFO, MessageFormat.format(format, o1, o2));
}
}

@Override
public void warn(String msg) {
logger.log(java.util.logging.Level.WARNING, msg);
}

@Override
public void error(String message, Throwable t) {
logger.log(java.util.logging.Level.SEVERE, message, t);
}

@Override
public void error(String format, Object o1, Throwable t) {
if (logger.isLoggable(java.util.logging.Level.SEVERE)) {
logger.log(java.util.logging.Level.SEVERE, MessageFormat.format(format, o1), t);
}
}

@Override
public void error(String format, Object o1, Object o2, Throwable t) {
if (logger.isLoggable(java.util.logging.Level.SEVERE)) {
logger.log(java.util.logging.Level.SEVERE, MessageFormat.format(format, o1, o2), t);
}
}
}

private static class SLF4JLogger implements Logger {
final org.slf4j.Logger logger;

SLF4JLogger(Class<?> hostClass) {
logger = org.slf4j.LoggerFactory.getLogger(hostClass);
}

@Override
public boolean isTraceEnabled() {
return logger.isTraceEnabled();
}

@Override
public void trace(String format, Object o1, Object o2) {
logger.trace(format, o1, o2);
}

@Override
public void info(String format, Object o1, Object o2) {
logger.info(format, o1, o2);
}

@Override
public void warn(String msg) {
logger.warn(msg);
}

@Override
public void error(String message, Throwable t) {
logger.error(message, t);
}

@Override
public void error(String format, Object o1, Throwable t) {
logger.error(format, o1, t);
}

@Override
public void error(String format, Object o1, Object o2, Throwable t) {
logger.error(format, o1, o2, t);
}
}
}
2 changes: 0 additions & 2 deletions src/main/java/org/sqlite/util/OSInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@
import java.util.HashMap;
import java.util.Locale;
import java.util.stream.Stream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Provides OS name and architecture name.
Expand Down
2 changes: 0 additions & 2 deletions src/test/java/org/sqlite/architecture/CodingRulesTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@ void no_access_to_standard_streams(JavaClasses importedClasses) {

@ArchTest private final ArchRule no_jodatime = NO_CLASSES_SHOULD_USE_JODATIME;

@ArchTest private final ArchRule no_java_util_logging = NO_CLASSES_SHOULD_USE_JAVA_UTIL_LOGGING;

@ArchTest
private final ArchRule no_driver_manager_println =
noClasses()
Expand Down

0 comments on commit 580932e

Please sign in to comment.