aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pom.xml3
-rw-r--r--src/changes/changes.xml15
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/Column.java21
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/ColumnBuilder.java7
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/DataType.java17
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/CalculatedColumnUtil.java6
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java53
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java3
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/JetFormat.java4
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/OleUtil.java3
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/PageChannel.java3
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/SqlHelper.java71
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/SqlHelperImpl.java73
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/util/ImportUtil.java19
-rw-r--r--src/site/site.xml9
-rw-r--r--src/site/xdoc/index.xml18
-rw-r--r--src/site/xdoc/jackcess-3_5.xml2
-rw-r--r--src/site/xdoc/jackcess-4.xml64
-rw-r--r--src/site/xdoc/jackcess_upgrades.xml22
-rw-r--r--src/test/java/com/healthmarketscience/jackcess/TestUtil.java4
-rw-r--r--src/test/java/com/healthmarketscience/jackcess/impl/JetFormatTest.java4
21 files changed, 331 insertions, 90 deletions
diff --git a/pom.xml b/pom.xml
index dc51de6..3dfbd30 100644
--- a/pom.xml
+++ b/pom.xml
@@ -9,7 +9,7 @@
<artifactId>jackcess</artifactId>
<name>Jackcess</name>
<description>A pure Java library for reading from and writing to MS Access databases.</description>
- <version>3.5.2-SNAPSHOT</version>
+ <version>4.0.0-SNAPSHOT</version>
<url>https://jackcess.sourceforge.io</url>
<inceptionYear>2005</inceptionYear>
<developers>
@@ -142,6 +142,7 @@
<extensions>true</extensions>
<configuration>
<instructions>
+ <Automatic-Module-Name>com.healthmarketscience.jackcess</Automatic-Module-Name>
</instructions>
</configuration>
<executions>
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 99d943e..14bed22 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -4,6 +4,21 @@
<author email="javajedi@users.sf.net">Tim McCune</author>
</properties>
<body>
+ <release version="4.0.0" date="TBD">
+ <action dev="jahlborn" type="update">
+ Add Automatic-Module-Name in order to make Jackcess safe to use in the
+ module path in Java 9+ environments.
+ </action>
+ <action dev="jahlborn" type="update">
+ Make a few classes and constants public in order to facilitate use in
+ different packages.
+ </action>
+ <action dev="jahlborn" type="update">
+ Alter access to java.sql classes so that usage is dependent on whether
+ or not the module is loaded in Java 9+ environments. Tweak a few
+ methods to no longer throw SQLException.
+ </action>
+ </release>
<release version="3.5.1" date="2020-09-10">
<action dev="jahlborn" type="update">
Add more static utility methods to DatabaseBuilder to enable more
diff --git a/src/main/java/com/healthmarketscience/jackcess/Column.java b/src/main/java/com/healthmarketscience/jackcess/Column.java
index 333f977..d05fb2a 100644
--- a/src/main/java/com/healthmarketscience/jackcess/Column.java
+++ b/src/main/java/com/healthmarketscience/jackcess/Column.java
@@ -17,7 +17,6 @@ limitations under the License.
package com.healthmarketscience.jackcess;
import java.io.IOException;
-import java.sql.SQLException;
import java.util.Map;
import com.healthmarketscience.jackcess.complex.ComplexColumnInfo;
@@ -34,7 +33,7 @@ import com.healthmarketscience.jackcess.util.ColumnValidator;
* @author James Ahlborn
* @usage _general_class_
*/
-public interface Column
+public interface Column
{
/**
* Meaningless placeholder object for inserting values in an autonumber
@@ -43,14 +42,14 @@ public interface Column
* @usage _general_field_
*/
public static final Object AUTO_NUMBER = "<AUTO_NUMBER>";
-
+
/**
* Meaningless placeholder object for updating rows which indicates that a
* given column should keep its existing value.
* @usage _general_field_
*/
public static final Object KEEP_VALUE = "<KEEP_VALUE>";
-
+
/**
* @usage _general_method_
*/
@@ -89,7 +88,7 @@ public interface Column
/**
* @usage _general_method_
*/
- public int getSQLType() throws SQLException;
+ public int getSQLType() throws IOException;
/**
* @usage _general_method_
@@ -149,7 +148,7 @@ public interface Column
* @usage _general_method_
*/
public PropertyMap getProperties() throws IOException;
-
+
/**
* Returns the column which tracks the version history for an "append only"
* column.
@@ -162,7 +161,7 @@ public interface Column
* @usage _intermediate_method_
*/
public ColumnValidator getColumnValidator();
-
+
/**
* Sets a new ColumnValidator. If {@code null}, resets to the value
* returned from the Database's ColumnValidatorFactory (if the factory
@@ -173,12 +172,12 @@ public interface Column
* @usage _intermediate_method_
*/
public void setColumnValidator(ColumnValidator newValidator);
-
+
public Object setRowValue(Object[] rowArray, Object value);
-
+
public Object setRowValue(Map<String,Object> rowMap, Object value);
-
+
public Object getRowValue(Object[] rowArray);
-
+
public Object getRowValue(Map<String,?> rowMap);
}
diff --git a/src/main/java/com/healthmarketscience/jackcess/ColumnBuilder.java b/src/main/java/com/healthmarketscience/jackcess/ColumnBuilder.java
index 48fa1cf..e063448 100644
--- a/src/main/java/com/healthmarketscience/jackcess/ColumnBuilder.java
+++ b/src/main/java/com/healthmarketscience/jackcess/ColumnBuilder.java
@@ -17,7 +17,6 @@ limitations under the License.
package com.healthmarketscience.jackcess;
import java.io.IOException;
-import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
@@ -93,7 +92,7 @@ public class ColumnBuilder {
/**
* Sets the type for the new column based on the given SQL type.
*/
- public ColumnBuilder setSQLType(int type) throws SQLException {
+ public ColumnBuilder setSQLType(int type) throws IOException {
return setSQLType(type, 0, null);
}
@@ -102,7 +101,7 @@ public class ColumnBuilder {
* data length (in type specific units).
*/
public ColumnBuilder setSQLType(int type, int lengthInUnits)
- throws SQLException
+ throws IOException
{
return setSQLType(type, lengthInUnits, null);
}
@@ -113,7 +112,7 @@ public class ColumnBuilder {
*/
public ColumnBuilder setSQLType(int type, int lengthInUnits,
Database.FileFormat fileFormat)
- throws SQLException
+ throws IOException
{
return setType(DataType.fromSQLType(type, lengthInUnits, fileFormat));
}
diff --git a/src/main/java/com/healthmarketscience/jackcess/DataType.java b/src/main/java/com/healthmarketscience/jackcess/DataType.java
index 6070dbd..d191dc1 100644
--- a/src/main/java/com/healthmarketscience/jackcess/DataType.java
+++ b/src/main/java/com/healthmarketscience/jackcess/DataType.java
@@ -19,7 +19,6 @@ package com.healthmarketscience.jackcess;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
-import java.sql.SQLException;
import java.sql.Types;
import java.util.Date;
import java.util.HashMap;
@@ -28,6 +27,7 @@ import java.time.LocalDateTime;
import com.healthmarketscience.jackcess.impl.DatabaseImpl;
import com.healthmarketscience.jackcess.impl.JetFormat;
+import com.healthmarketscience.jackcess.impl.SqlHelper;
/**
* Supported access data types.
@@ -356,11 +356,11 @@ public enum DataType {
return _maxSize;
}
- public int getSQLType() throws SQLException {
+ public int getSQLType() throws IOException {
if (_sqlType != null) {
return _sqlType;
}
- throw new SQLException("Unsupported data type: " + toString());
+ throw new JackcessException("Unsupported data type: " + toString());
}
public int getMinScale() {
@@ -472,24 +472,24 @@ public enum DataType {
}
public static DataType fromSQLType(int sqlType)
- throws SQLException
+ throws IOException
{
return fromSQLType(sqlType, 0, null);
}
public static DataType fromSQLType(int sqlType, int lengthInUnits)
- throws SQLException
+ throws IOException
{
return fromSQLType(sqlType, lengthInUnits, null);
}
public static DataType fromSQLType(int sqlType, int lengthInUnits,
Database.FileFormat fileFormat)
- throws SQLException
+ throws IOException
{
DataType[] rtnArr = SQL_TYPES.get(sqlType);
if(rtnArr == null) {
- throw new SQLException("Unsupported SQL type: " + sqlType);
+ throw new JackcessException("Unsupported SQL type: " + sqlType);
}
JetFormat format =
((fileFormat != null) ?
@@ -533,8 +533,7 @@ public enum DataType {
DataType altType)
{
try {
- java.lang.reflect.Field sqlTypeField = Types.class.getField(typeName);
- Integer value = (Integer)sqlTypeField.get(null);
+ Integer value = SqlHelper.INSTANCE.getNewSqlType(typeName);
SQL_TYPES.put(value, new DataType[]{type});
if(altType != null) {
ALT_SQL_TYPES.put(value, altType);
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/CalculatedColumnUtil.java b/src/main/java/com/healthmarketscience/jackcess/impl/CalculatedColumnUtil.java
index 8e3802b..0ded048 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/CalculatedColumnUtil.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/CalculatedColumnUtil.java
@@ -423,10 +423,8 @@ class CalculatedColumnUtil
buffer.put(intValBytes);
} catch(ArithmeticException e) {
- throw (IOException)
- new IOException(withErrorContext(
- "Numeric value '" + inValue + "' out of range"))
- .initCause(e);
+ throw new IOException(
+ withErrorContext("Numeric value '" + inValue + "' out of range"), e);
}
}
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java b/src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java
index 07c798b..ff221a7 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java
@@ -29,9 +29,6 @@ import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
-import java.sql.Blob;
-import java.sql.Clob;
-import java.sql.SQLException;
import java.time.DateTimeException;
import java.time.Duration;
import java.time.Instant;
@@ -441,7 +438,7 @@ public class ColumnImpl implements Column, Comparable<ColumnImpl>, DateTimeConte
}
@Override
- public int getSQLType() throws SQLException {
+ public int getSQLType() throws IOException {
return _type.getSQLType();
}
@@ -860,10 +857,8 @@ public class ColumnImpl implements Column, Comparable<ColumnImpl>, DateTimeConte
// too big)
buffer.putLong(decVal.movePointRight(4).longValueExact());
} catch(ArithmeticException e) {
- throw (IOException)
- new IOException(withErrorContext(
- "Currency value '" + inValue + "' out of range"))
- .initCause(e);
+ throw new IOException(
+ withErrorContext("Currency value '" + inValue + "' out of range"), e);
}
}
@@ -936,10 +931,8 @@ public class ColumnImpl implements Column, Comparable<ColumnImpl>, DateTimeConte
}
buffer.put(intValBytes);
} catch(ArithmeticException e) {
- throw (IOException)
- new IOException(withErrorContext(
- "Numeric value '" + inValue + "' out of range"))
- .initCause(e);
+ throw new IOException(
+ withErrorContext("Numeric value '" + inValue + "' out of range"), e);
}
}
@@ -1836,14 +1829,8 @@ public class ColumnImpl implements Column, Comparable<ColumnImpl>, DateTimeConte
return null;
} else if(value instanceof CharSequence) {
return (CharSequence)value;
- } else if(value instanceof Clob) {
- try {
- Clob c = (Clob)value;
- // note, start pos is 1-based
- return c.getSubString(1L, (int)c.length());
- } catch(SQLException e) {
- throw (IOException)(new IOException(e.getMessage())).initCause(e);
- }
+ } else if(SqlHelper.INSTANCE.isClob(value)) {
+ return SqlHelper.INSTANCE.getClobString(value);
} else if(value instanceof Reader) {
char[] buf = new char[8 * 1024];
StringBuilder sout = new StringBuilder();
@@ -1869,18 +1856,10 @@ public class ColumnImpl implements Column, Comparable<ColumnImpl>, DateTimeConte
return null;
} else if(value instanceof byte[]) {
return (byte[])value;
- } else if(value instanceof OleUtil.OleBlobImpl) {
- return ((OleUtil.OleBlobImpl)value).getBytes();
- } else if(value instanceof Blob) {
- try {
- Blob b = (Blob)value;
- // note, start pos is 1-based
- return b.getBytes(1L, (int)b.length());
- } catch(SQLException e) {
- throw (IOException)(new IOException(e.getMessage())).initCause(e);
- }
- } else if(value instanceof RawData) {
- return ((RawData)value).getBytes();
+ } else if(value instanceof InMemoryBlob) {
+ return ((InMemoryBlob)value).getBytes();
+ } else if(SqlHelper.INSTANCE.isBlob(value)) {
+ return SqlHelper.INSTANCE.getBlobBytes(value);
}
ByteArrayOutputStream bout = new ByteArrayOutputStream();
@@ -2302,7 +2281,7 @@ public class ColumnImpl implements Column, Comparable<ColumnImpl>, DateTimeConte
/**
* Wrapper for raw column data which can be re-written.
*/
- private static class RawData implements Serializable
+ private static final class RawData implements Serializable, InMemoryBlob
{
private static final long serialVersionUID = 0L;
@@ -2312,7 +2291,8 @@ public class ColumnImpl implements Column, Comparable<ColumnImpl>, DateTimeConte
_bytes = bytes;
}
- private byte[] getBytes() {
+ @Override
+ public byte[] getBytes() {
return _bytes;
}
@@ -2788,4 +2768,9 @@ public class ColumnImpl implements Column, Comparable<ColumnImpl>, DateTimeConte
return LocalDateTime.ofInstant(inst, db.getZoneId());
}
}
+
+ /** internal interface for types which hold bytes in memory */
+ static interface InMemoryBlob {
+ public byte[] getBytes() throws IOException;
+ }
}
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java b/src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java
index 532eb65..1ff129e 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java
@@ -2149,8 +2149,9 @@ public class DatabaseImpl implements Database, DateTimeContext
/**
* Returns the password mask retrieved from the given header page and
* format, or {@code null} if this format does not use a password mask.
+ * @usage _advanced_method_
*/
- static byte[] getPasswordMask(ByteBuffer buffer, JetFormat format)
+ public static byte[] getPasswordMask(ByteBuffer buffer, JetFormat format)
{
// get extra password mask if necessary (the extra password mask is
// generated from the database creation date stored in the header)
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/JetFormat.java b/src/main/java/com/healthmarketscience/jackcess/impl/JetFormat.java
index 2d2f0af..8a3aa64 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/JetFormat.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/JetFormat.java
@@ -63,9 +63,9 @@ public abstract class JetFormat {
private static final byte CODE_VERSION_16 = 0x5;
/** location of the engine name in the header */
- static final int OFFSET_ENGINE_NAME = 0x4;
+ public static final int OFFSET_ENGINE_NAME = 0x4;
/** length of the engine name in the header */
- static final int LENGTH_ENGINE_NAME = 0xF;
+ public static final int LENGTH_ENGINE_NAME = 0xF;
/** amount of initial data to be read to determine database type */
private static final int HEADER_LENGTH = 21;
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/OleUtil.java b/src/main/java/com/healthmarketscience/jackcess/impl/OleUtil.java
index a67a54d..7708b11 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/OleUtil.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/OleUtil.java
@@ -463,7 +463,7 @@ public class OleUtil
}
- static final class OleBlobImpl implements OleBlob
+ static final class OleBlobImpl implements OleBlob, ColumnImpl.InMemoryBlob
{
private byte[] _bytes;
private ContentImpl _content;
@@ -502,6 +502,7 @@ public class OleUtil
return _bytes.length;
}
+ @Override
public byte[] getBytes() throws IOException {
if(_bytes == null) {
throw new IOException("blob is closed");
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/PageChannel.java b/src/main/java/com/healthmarketscience/jackcess/impl/PageChannel.java
index 101a3e0..efd8be2 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/PageChannel.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/PageChannel.java
@@ -32,7 +32,8 @@ public class PageChannel implements Channel, Flushable {
static final int INVALID_PAGE_NUMBER = -1;
- static final ByteOrder DEFAULT_BYTE_ORDER = ByteOrder.LITTLE_ENDIAN;
+ /** default byte order of access mdb files */
+ public static final ByteOrder DEFAULT_BYTE_ORDER = ByteOrder.LITTLE_ENDIAN;
/** invalid page header, used when deallocating old pages. data pages
generally have 4 interesting bytes at the beginning which we want to
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/SqlHelper.java b/src/main/java/com/healthmarketscience/jackcess/impl/SqlHelper.java
new file mode 100644
index 0000000..91fc4b6
--- /dev/null
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/SqlHelper.java
@@ -0,0 +1,71 @@
+/*
+Copyright (c) 2021 James Ahlborn
+
+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 com.healthmarketscience.jackcess.impl;
+
+import java.io.IOException;
+
+/**
+ * Helper class to isolate the java.sql module interactions from the core of
+ * jackcess (in java 9+ environments). If the module is enabled (indicating
+ * that the application is already using sql constructs), then jackcess will
+ * seamlessly interact with sql types. If the module is not enabled
+ * (indicating that the application is not using any sql constructs), then
+ * jackcess will not require the module in order to function otherwise
+ * normally.
+ *
+ * This base class is the "fallback" class if the java.sql module is not
+ * available.
+ *
+ * @author James Ahlborn
+ */
+public class SqlHelper {
+
+ public static final SqlHelper INSTANCE = loadInstance();
+
+ public SqlHelper() {}
+
+ public boolean isBlob(Object value) {
+ return false;
+ }
+
+ public byte[] getBlobBytes(Object value) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean isClob(Object value) {
+ return false;
+ }
+
+ public CharSequence getClobString(Object value) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ public Integer getNewSqlType(String typeName) throws Exception {
+ throw new UnsupportedOperationException();
+ }
+
+ private static final SqlHelper loadInstance() {
+ // attempt to load the implementation of this class which works with
+ // java.sql classes. if that fails, use this fallback instance instead.
+ try {
+ return (SqlHelper)
+ Class.forName("com.healthmarketscience.jackcess.impl.SqlHelperImpl")
+ .newInstance();
+ } catch(Throwable ignored) {}
+ return new SqlHelper();
+ }
+}
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/SqlHelperImpl.java b/src/main/java/com/healthmarketscience/jackcess/impl/SqlHelperImpl.java
new file mode 100644
index 0000000..079613f
--- /dev/null
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/SqlHelperImpl.java
@@ -0,0 +1,73 @@
+/*
+Copyright (c) 2021 James Ahlborn
+
+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 com.healthmarketscience.jackcess.impl;
+
+import java.io.IOException;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.SQLException;
+import java.sql.Types;
+
+/**
+ * Implementation of SqlHelperImpl which works with the java.sql modules
+ * classes. This class is used if the java.sql module is enabled in the
+ * application.
+ *
+ * @author James Ahlborn
+ */
+public class SqlHelperImpl extends SqlHelper {
+
+ public SqlHelperImpl() {}
+
+ @Override
+ public boolean isBlob(Object value) {
+ return (value instanceof Blob);
+ }
+
+ @Override
+ public byte[] getBlobBytes(Object value) throws IOException {
+ try {
+ Blob b = (Blob)value;
+ // note, start pos is 1-based
+ return b.getBytes(1L, (int)b.length());
+ } catch(SQLException e) {
+ throw new IOException(e.getMessage(), e);
+ }
+ }
+
+ @Override
+ public boolean isClob(Object value) {
+ return (value instanceof Clob);
+ }
+
+ @Override
+ public CharSequence getClobString(Object value) throws IOException {
+ try {
+ Clob c = (Clob)value;
+ // note, start pos is 1-based
+ return c.getSubString(1L, (int)c.length());
+ } catch(SQLException e) {
+ throw new IOException(e.getMessage(), e);
+ }
+ }
+
+ @Override
+ public Integer getNewSqlType(String typeName) throws Exception {
+ java.lang.reflect.Field sqlTypeField = Types.class.getField(typeName);
+ return (Integer)sqlTypeField.get(null);
+ }
+}
diff --git a/src/main/java/com/healthmarketscience/jackcess/util/ImportUtil.java b/src/main/java/com/healthmarketscience/jackcess/util/ImportUtil.java
index 2fd6455..c4c3625 100644
--- a/src/main/java/com/healthmarketscience/jackcess/util/ImportUtil.java
+++ b/src/main/java/com/healthmarketscience/jackcess/util/ImportUtil.java
@@ -16,6 +16,13 @@ limitations under the License.
package com.healthmarketscience.jackcess.util;
+import com.healthmarketscience.jackcess.ColumnBuilder;
+import com.healthmarketscience.jackcess.DataType;
+import com.healthmarketscience.jackcess.Database;
+import com.healthmarketscience.jackcess.Table;
+import com.healthmarketscience.jackcess.TableBuilder;
+import com.healthmarketscience.jackcess.impl.ByteUtil;
+import com.healthmarketscience.jackcess.impl.DatabaseImpl;
import java.io.BufferedReader;
import java.io.EOFException;
import java.io.File;
@@ -29,14 +36,6 @@ import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import com.healthmarketscience.jackcess.ColumnBuilder;
-import com.healthmarketscience.jackcess.DataType;
-import com.healthmarketscience.jackcess.Database;
-import com.healthmarketscience.jackcess.Table;
-import com.healthmarketscience.jackcess.TableBuilder;
-import com.healthmarketscience.jackcess.impl.ByteUtil;
-import com.healthmarketscience.jackcess.impl.DatabaseImpl;
-
/**
* Utility class for importing tables to an Access database from other
* sources. See the {@link Builder} for convenient configuration of the
@@ -64,7 +63,7 @@ public class ImportUtil
* @return a List of Columns
*/
public static List<ColumnBuilder> toColumns(ResultSetMetaData md)
- throws SQLException
+ throws SQLException, IOException
{
List<ColumnBuilder> columns = new ArrayList<ColumnBuilder>();
for (int i = 1; i <= md.getColumnCount(); i++) {
@@ -494,7 +493,7 @@ public class ImportUtil
return table.getName();
} catch(SQLException e) {
- throw (IOException)new IOException(e.getMessage()).initCause(e);
+ throw new IOException(e.getMessage(), e);
}
}
diff --git a/src/site/site.xml b/src/site/site.xml
index c7c64f7..b756593 100644
--- a/src/site/site.xml
+++ b/src/site/site.xml
@@ -15,9 +15,12 @@
<item name="Downloads" href="https://sourceforge.net/project/showfiles.php?group_id=134943"/>
<item name="SourceForge Project" href="https://sourceforge.net/projects/jackcess/"/>
<item name="Cookbook" href="cookbook.html"/>
- <item name="Upgrading to Jackcess 3.5.x" href="jackcess-3_5.html"/>
- <item name="Upgrading to Jackcess 3.x" href="jackcess-3.html"/>
- <item name="Upgrading to Jackcess 2.x" href="jackcess-2.html"/>
+ <item name="Upgrading to Jackcess 4.x" href="jackcess-4.html"/>
+ <item name="Upgrading to Older Versions" href="jackcess_upgrades.html" collapse="true">
+ <item name="Jackcess 3.5.x" href="jackcess-3_5.html"/>
+ <item name="Jackcess 3.x" href="jackcess-3.html"/>
+ <item name="Jackcess 2.x" href="jackcess-2.html"/>
+ </item>
<item name="FAQ" href="faq.html"/>
<item name="Support" href="https://sourceforge.net/projects/jackcess/support"/>
<item name="Jackcess Encrypt" href="https://jackcessencrypt.sourceforge.io/"/>
diff --git a/src/site/xdoc/index.xml b/src/site/xdoc/index.xml
index 9172845..fa803d3 100644
--- a/src/site/xdoc/index.xml
+++ b/src/site/xdoc/index.xml
@@ -19,6 +19,18 @@
Questions</a> for more info.
</p>
+ <subsection name="Java 9+ Compatibility (2021-TBD)">
+ <p>
+ While Jackcess <i>still only requires Java 8+</i>, as of the 4.0.0
+ release it now includes an Automatic-Module-Name of
+ <code>com.healthmarketscience.jackcess</code> in its manifest. This
+ allows it to be used safely in the module path for Java 9+ projects.
+ </p>
+ <p>
+ This release is binary compatible with the 3.x release series.
+ </p>
+ </subsection>
+
<subsection name="Java 8+ Support (2019-02-08)">
<p>
Jackcess now requires Java 8+ as of the 3.0.0 release. All third
@@ -77,10 +89,8 @@ if(row != null) {
<li>Creating a new table and writing data into it:
<source>Database db = DatabaseBuilder.create(Database.FileFormat.V2000, new File("new.mdb"));
Table newTable = new TableBuilder("NewTable")
- .addColumn(new ColumnBuilder("a")
- .setSQLType(Types.INTEGER))
- .addColumn(new ColumnBuilder("b")
- .setSQLType(Types.VARCHAR))
+ .addColumn(new ColumnBuilder("a", DataType.LONG))
+ .addColumn(new ColumnBuilder("b", DataType.TEXT))
.toTable(db);
newTable.addRow(1, "foo");
</source>
diff --git a/src/site/xdoc/jackcess-3_5.xml b/src/site/xdoc/jackcess-3_5.xml
index 0724c38..efff66f 100644
--- a/src/site/xdoc/jackcess-3_5.xml
+++ b/src/site/xdoc/jackcess-3_5.xml
@@ -15,7 +15,7 @@
behavior of Jackcess out of the box. The old behavior is still
available, but you must now configure it explicitly.
<ul>
- <li><b>DateTypeType default has been changed to
+ <li><b>DateTimeType default has been changed to
LOCAL_DATE_TIME.</b></li>
<ul>
<li>The Jackcess API was originally built using the Date type
diff --git a/src/site/xdoc/jackcess-4.xml b/src/site/xdoc/jackcess-4.xml
new file mode 100644
index 0000000..581aac4
--- /dev/null
+++ b/src/site/xdoc/jackcess-4.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0"?>
+
+<document>
+ <properties>
+ <author email="jahlborn@users.sf.net">James Ahlborn</author>
+ <title>Upgrading from Jackcess 3.x (or 3.5.x) to 4.x</title>
+ </properties>
+ <body>
+
+ <section name="Jackcess 4.0">
+ <subsection name="Just give it to me straight">
+ <p>
+ Jackcess 4.x is largely binary compatible with the previous 3.x (and
+ 3.5.x) versions. In order to be more "module friendly", the
+ exceptions thrown from a few infrequently used methods have changed
+ from <code>SQLException</code> to <code>IOException</code>. Other
+ than that, code compiled against the 3.x series should work fine
+ with the 4.x series.
+ </p>
+
+ <p>
+ Even though Jackcess is now Java 9+ module compatible, <i>it still
+ only requires Java 8+</i>. However, Jackcess can now be safely used
+ in the module path of a Java 9+ project (with the module name of
+ <code>com.healthmarketscience.jackcess</code>). There are a few
+ features which require additional core Java modules to be enabled
+ (but these modules are not required if the corresponding features
+ are not utilized).
+ <ul>
+ <li><b>java.sql</b></li>
+ <ul>
+ <li>This module is necessary if Jackcess will need to interact
+ with any of the classes from the <code>java.sql</code> package
+ (e.g. handling <code>Clob</code>/<code>Blob</code> or using
+ <code>ImportUtil</code>).</li>
+ </ul>
+ <li><b>java.scripting</b></li>
+ <ul>
+ <li>This module is necessary if expression evaluation is
+ enabled (the default) and the database includes expressions
+ (e.g. default values, calculated columns, validation
+ rules, etc.).</li>
+ </ul>
+ </ul>
+ </p>
+
+ <h4>Working with Jackcess Encrypt</h4>
+ <p>
+ If you are using the <a href="https://jackcessencrypt.sourceforge.io/">Jackcess Encrypt</a>
+ project, then you will need to use a version compatible with the
+ relevant Jackess API. Fortunately, the major versions match, so
+ it's pretty simple:
+ </p>
+ <ul>
+ <li>Jackcess 4.x -&gt; Jackcess Encrypt 4.y</li>
+ <li>Jackcess 3.x -&gt; Jackcess Encrypt 3.y</li>
+ <li>Jackcess 2.x -&gt; Jackcess Encrypt 2.y</li>
+ <li>Jackcess 1.x -&gt; Jackcess Encrypt 1.y</li>
+ </ul>
+ </subsection>
+ </section>
+
+ </body>
+</document>
diff --git a/src/site/xdoc/jackcess_upgrades.xml b/src/site/xdoc/jackcess_upgrades.xml
new file mode 100644
index 0000000..e6229c3
--- /dev/null
+++ b/src/site/xdoc/jackcess_upgrades.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+
+<document>
+ <properties>
+ <author email="jahlborn@users.sf.net">James Ahlborn</author>
+ <title>Upgrading to Older Versions</title>
+ </properties>
+ <body>
+
+ <section name="Upgrading to Older Versions">
+ <subsection name="Overview">
+ <table>
+ <tr><th>Document</th></tr>
+ <tr><td><a href="jackcess-3_5.html">Upgrading to Jackcess 3.5.x</a></td></tr>
+ <tr><td><a href="jackcess-3.html">Upgrading to Jackcess 3.x</a></td></tr>
+ <tr><td><a href="jackcess-2.html">Upgrading to Jackcess 2.x</a></td></tr>
+ </table>
+ </subsection>
+ </section>
+
+ </body>
+</document>
diff --git a/src/test/java/com/healthmarketscience/jackcess/TestUtil.java b/src/test/java/com/healthmarketscience/jackcess/TestUtil.java
index d4bccd8..e10fd39 100644
--- a/src/test/java/com/healthmarketscience/jackcess/TestUtil.java
+++ b/src/test/java/com/healthmarketscience/jackcess/TestUtil.java
@@ -415,7 +415,7 @@ public class TestUtil
Assert.assertEquals(expectedLdt, found);
}
- static void copyFile(File srcFile, File dstFile)
+ public static void copyFile(File srcFile, File dstFile)
throws IOException
{
// FIXME should really be using commons io FileUtils here, but don't want
@@ -441,7 +441,7 @@ public class TestUtil
}
}
- static File createTempFile(boolean keep) throws Exception {
+ public static File createTempFile(boolean keep) throws Exception {
File tmp = File.createTempFile("databaseTest", ".mdb");
if(keep) {
System.out.println("Created " + tmp);
diff --git a/src/test/java/com/healthmarketscience/jackcess/impl/JetFormatTest.java b/src/test/java/com/healthmarketscience/jackcess/impl/JetFormatTest.java
index 9257e5e..19d95f0 100644
--- a/src/test/java/com/healthmarketscience/jackcess/impl/JetFormatTest.java
+++ b/src/test/java/com/healthmarketscience/jackcess/impl/JetFormatTest.java
@@ -6,7 +6,6 @@ import java.io.InputStream;
import java.nio.charset.Charset;
import java.nio.channels.FileChannel;
import java.nio.channels.NonWritableChannelException;
-import java.sql.SQLException;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
@@ -14,6 +13,7 @@ import java.util.Set;
import com.healthmarketscience.jackcess.DataType;
import com.healthmarketscience.jackcess.Database;
+import com.healthmarketscience.jackcess.JackcessException;
import static com.healthmarketscience.jackcess.Database.*;
import com.healthmarketscience.jackcess.DatabaseBuilder;
import com.healthmarketscience.jackcess.PropertyMap;
@@ -292,7 +292,7 @@ public class JetFormatTest extends TestCase {
Integer sqlType = null;
try {
sqlType = dt.getSQLType();
- } catch(SQLException ignored) {}
+ } catch(JackcessException ignored) {}
if(sqlType != null) {
assertEquals(dt, DataType.fromSQLType(sqlType));