]> source.dussan.org Git - jackcess.git/commitdiff
isolate java.sql usage so that the module is not required for core jackcess usage
authorJames Ahlborn <jtahlborn@yahoo.com>
Sun, 17 Jan 2021 23:32:53 +0000 (23:32 +0000)
committerJames Ahlborn <jtahlborn@yahoo.com>
Sun, 17 Jan 2021 23:32:53 +0000 (23:32 +0000)
git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/branches/modules@1350 f203690c-595d-4dc9-a70b-905162fa7fd2

src/main/java/com/healthmarketscience/jackcess/Column.java
src/main/java/com/healthmarketscience/jackcess/ColumnBuilder.java
src/main/java/com/healthmarketscience/jackcess/DataType.java
src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java
src/main/java/com/healthmarketscience/jackcess/impl/OleUtil.java
src/main/java/com/healthmarketscience/jackcess/impl/SqlHelper.java [new file with mode: 0644]
src/main/java/com/healthmarketscience/jackcess/impl/SqlHelperImpl.java [new file with mode: 0644]
src/main/java/com/healthmarketscience/jackcess/util/ImportUtil.java
src/test/java/com/healthmarketscience/jackcess/impl/JetFormatTest.java

index 333f977b4a9eff1441671b2754c3618da901d51a..d05fb2ad15f84e5a90550658477c8ff5add6d969 100644 (file)
@@ -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);
 }
index 48fa1cf64810d09b4ab9fc735a3d6eaefb88ac38..e063448081321a5a9d2ec51c34340caa92c9a38f 100644 (file)
@@ -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));
   }
index 6070dbd5c83920e086707379fbc4c3834ed6e7db..d191dc1612327ddd4884112a5265b8cf48704357 100644 (file)
@@ -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);
index 07c798b85e396033902cda82f80ff79b5ff84c11..de4d8e7bb676c15a23f8823be6bb91877826754f 100644 (file)
@@ -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();
   }
 
@@ -1836,14 +1833,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 +1860,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 +2285,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 +2295,8 @@ public class ColumnImpl implements Column, Comparable<ColumnImpl>, DateTimeConte
       _bytes = bytes;
     }
 
-    private byte[] getBytes() {
+    @Override
+    public byte[] getBytes() {
       return _bytes;
     }
 
@@ -2788,4 +2772,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;
+  }
 }
index a67a54db4b53a370421f33e22e8c734516f0f684..7708b11192c0240f84d8f3590ff0007c960e85d5 100644 (file)
@@ -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/SqlHelper.java b/src/main/java/com/healthmarketscience/jackcess/impl/SqlHelper.java
new file mode 100644 (file)
index 0000000..91fc4b6
--- /dev/null
@@ -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 (file)
index 0000000..142fb1f
--- /dev/null
@@ -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 (IOException)(new IOException(e.getMessage())).initCause(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 (IOException)(new IOException(e.getMessage())).initCause(e);
+    }
+  }
+
+  @Override
+  public Integer getNewSqlType(String typeName) throws Exception {
+    java.lang.reflect.Field sqlTypeField = Types.class.getField(typeName);
+    return (Integer)sqlTypeField.get(null);
+  }
+}
index 2fd64553369f777b07a2c1acfe4e9a0162b046fb..b68e448864d240e68add517ad1b028526bc1c16d 100644 (file)
@@ -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++) {
index 9257e5e0b03373cba3e3c7cc51de50121bc07f9a..19d95f0aef9771aabfd8f53cb8daa76c672a3371 100644 (file)
@@ -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));