diff options
21 files changed, 331 insertions, 90 deletions
@@ -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 -> Jackcess Encrypt 4.y</li> + <li>Jackcess 3.x -> Jackcess Encrypt 3.y</li> + <li>Jackcess 2.x -> Jackcess Encrypt 2.y</li> + <li>Jackcess 1.x -> 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)); |