https://bugs.documentfoundation.org/show_bug.cgi?id=150295
Bug ID: 150295
Summary: JDBC exception details lost
Product: LibreOffice
Version: 7.0.4.2 release
Hardware: All
OS: All
Status: UNCONFIRMED
Severity: normal
Priority: medium
Component: Base
Assignee: [email protected]
Reporter: [email protected]
Description:
I am working on a JDBC driver to access CardDAV addresses on a Nextcloud
server.
In the development my code produced a NullPointerException. In LibreOffice Base
there is an error message about a NullPointerException. But what is missing is
the Java stack trace (where in the Java code the NullPointerException has
happened).
Steps to Reproduce:
1. Create a buggy JDBC driver
1a. Compile class Driver, see code below (with javac -d classes
de/greinerinformatik/carddavjdbc/Driver)
(-d classes denotes the target directory)
1.b Create a text file classes/META-INF/services/java.sql.driver containing the
line
de.greinerinformatik.CardDAVxJDBC
1c. (optionally? ...maybe also works by working directly with the classes
directory) create a jar file from the classes directory
2. Register the JDBC driver in LibreOffice: Tools -> Options -> Extended ->
Class Path...
3. Create a odb file with JDBC Database jdbc:CardDAV:Ray
4. Click on tables, and the NullPointerException will come up. You will not see
the stack trace, where in the Java code the Exception occured.
Actual Results:
No stack trace from the Java JDBC code is available.
Expected Results:
The stack trace from Java should be available somewhere, in the error dialog,
or in the console output, to help debug the JDBC driver code.
Reproducible: Always
User Profile Reset: Yes
Additional Info:
package de.greinerinformatik.carddavjdbc;
import java.sql.Connection;
import java.sql.DriverPropertyInfo;
import java.sql.SQLException;
import java.util.Properties;
import java.io.IOException;
import java.sql.Array;
import java.sql.Blob;
import java.sql.CallableStatement;
import java.sql.Clob;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.NClob;
import java.sql.PreparedStatement;
import java.sql.SQLClientInfoException;
import java.sql.SQLWarning;
import java.sql.SQLXML;
import java.sql.Savepoint;
import java.sql.Statement;
import java.sql.Struct;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
public class Driver implements java.sql.Driver {
private static Driver registeredDriver;
private static final Logger PARENT_LOGGER =
Logger.getLogger("de.greinerinformatik.CardDAVxJDBC");
private static final Logger LOGGER =
Logger.getLogger("de.greinerinformatik.CardDAVxJDBC.Driver");
static {
try {
FileHandler fileHandler;
try {
fileHandler = new FileHandler("%t/CardDAV_%g.log", 10000, 5,
true);
fileHandler.setEncoding("UTF8");
} catch (IOException ioe) {
throw new SQLException("Error creating logging FileHandler for
TEMP dir CardDAV_n.log.", ioe);
}
fileHandler.setLevel(Level.FINEST);
fileHandler.setFormatter(new SimpleFormatter());
fileHandler.publish(new LogRecord(Level.SEVERE, "Test"));
LOGGER.addHandler(fileHandler);
LOGGER.setLevel(Level.FINEST);
LOGGER.log(Level.FINE, "Register database driver for
'jdbc:CardDAV:'.");
register();
} catch (SQLException e) {
throw new ExceptionInInitializerError(e);
}
}
private class ConnectionInfo {
Properties info;
public ConnectionInfo(String url, Properties info) {
if (info.getProperty("David") != null) {
this.info = info;
}
}
public String getName() {
return info.getProperty("name");
}
}
private class CardDAVConnection implements Connection {
@Override
public Statement createStatement() throws SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public PreparedStatement prepareStatement(String sql) throws
SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public CallableStatement prepareCall(String sql) throws SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public String nativeSQL(String sql) throws SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void setAutoCommit(boolean autoCommit) throws SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public boolean getAutoCommit() throws SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void commit() throws SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void rollback() throws SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void close() throws SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public boolean isClosed() throws SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public DatabaseMetaData getMetaData() throws SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void setReadOnly(boolean readOnly) throws SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public boolean isReadOnly() throws SQLException {
return true;
}
@Override
public void setCatalog(String catalog) throws SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public String getCatalog() throws SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void setTransactionIsolation(int level) throws SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public int getTransactionIsolation() throws SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public SQLWarning getWarnings() throws SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void clearWarnings() throws SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public Statement createStatement(int resultSetType, int
resultSetConcurrency) throws SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public PreparedStatement prepareStatement(String sql, int
resultSetType, int resultSetConcurrency) throws SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public CallableStatement prepareCall(String sql, int resultSetType, int
resultSetConcurrency) throws SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public Map<String, Class<?>> getTypeMap() throws SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void setHoldability(int holdability) throws SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public int getHoldability() throws SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public Savepoint setSavepoint() throws SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public Savepoint setSavepoint(String name) throws SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void rollback(Savepoint savepoint) throws SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void releaseSavepoint(Savepoint savepoint) throws SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public Statement createStatement(int resultSetType, int
resultSetConcurrency, int resultSetHoldability) throws SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public PreparedStatement prepareStatement(String string, int
resultSetType, int resultSetConcurrency, int resultSetHoldability) throws
SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public CallableStatement prepareCall(String string, int resultSetType,
int resultSetConcurrency, int resultSetHoldability) throws SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public PreparedStatement prepareStatement(String string, int
autoGeneratedKeys) throws SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public PreparedStatement prepareStatement(String string, int[]
columnIndexes) throws SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public PreparedStatement prepareStatement(String string, String[]
columnNames) throws SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public Clob createClob() throws SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public Blob createBlob() throws SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public NClob createNClob() throws SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public SQLXML createSQLXML() throws SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public boolean isValid(int timeout) throws SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void setClientInfo(String name, String value) throws
SQLClientInfoException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void setClientInfo(Properties properties) throws
SQLClientInfoException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public String getClientInfo(String name) throws SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public Properties getClientInfo() throws SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public Array createArrayOf(String typeName, Object[] elements) throws
SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public Struct createStruct(String typeName, Object[] attributes) throws
SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void setSchema(String schema) throws SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public String getSchema() throws SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void abort(Executor exctr) throws SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void setNetworkTimeout(Executor executor, int milliseconds)
throws SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public int getNetworkTimeout() throws SQLException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public <T> T unwrap(Class<T> type) throws SQLException {
throw new SQLException("This class is not a wrapper.");
}
@Override
public boolean isWrapperFor(Class<?> type) throws SQLException {
return false;
}
}
@Override
public Connection connect(String url, Properties info) throws SQLException
{
LOGGER.log(Level.FINE, "Connecting with URL: {0}", url);
ConnectionInfo ci = new ConnectionInfo(url, info);
LOGGER.log(Level.FINE, "User name: {0}", ci.getName());
return new CardDAVConnection();
}
@Override
public boolean acceptsURL(String url) {
LOGGER.log(Level.FINE, "Checking URL: {0}", url);
return url.toLowerCase().startsWith("jdbc:carddav:");
}
@Override
public DriverPropertyInfo[] getPropertyInfo(String url, Properties info)
throws SQLException {
LOGGER.log(Level.FINE, "getPropertyInfo URL: {0}", url);
if (info == null) {
throw new SQLException("info may be empty, but must not be null.");
}
return new DriverPropertyInfo[0];
}
@Override
public int getMajorVersion() {
return 0;
}
@Override
public int getMinorVersion() {
return 1;
}
@Override
public boolean jdbcCompliant() {
return false;
}
@Override
public java.util.logging.Logger getParentLogger() {
return PARENT_LOGGER;
}
/**
* Register the driver against {@link DriverManager}. This is done
* automatically when the class is loaded. Dropping the driver from
* DriverManager's list is possible using {@link #deregister()} method.
*
* @throws IllegalStateException if the driver is already registered
* @throws SQLException if registering the driver fails
*/
public static void register() throws SQLException {
if (isRegistered()) {
throw new IllegalStateException(
"Driver is already registered. It can only be registered
once.");
}
Driver registeredDriver = new Driver();
DriverManager.registerDriver(registeredDriver);
Driver.registeredDriver = registeredDriver;
}
/**
* According to JDBC specification, this driver is registered against
* {@link DriverManager} when the class is loaded. To avoid leaks, this
* method allow unregistering the driver so that the class can be gc'ed if
* necessary.
*
* @throws IllegalStateException if the driver is not registered
* @throws SQLException if deregistering the driver fails
*/
public static void deregister() throws SQLException {
if (registeredDriver == null) {
throw new IllegalStateException(
"Driver is not registered (or it has not been registered
using Driver.register() method)");
}
DriverManager.deregisterDriver(registeredDriver);
registeredDriver = null;
}
/**
* @return {@code true} if the driver is registered against
* {@link DriverManager}
*/
public static boolean isRegistered() {
return registeredDriver != null;
}
}
--
You are receiving this mail because:
You are the assignee for the bug.