git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@1174 f203690c-595d-4dc9-a70b-905162fa7fd2tags/jackcess-2.2.0
@@ -17,6 +17,7 @@ limitations under the License. | |||
package com.healthmarketscience.jackcess.impl; | |||
import java.io.Closeable; | |||
import java.io.DataInputStream; | |||
import java.io.FileWriter; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
@@ -31,14 +32,14 @@ import java.util.Arrays; | |||
* @author Tim McCune | |||
*/ | |||
public final class ByteUtil { | |||
private static final String[] HEX_CHARS = new String[] { | |||
"0", "1", "2", "3", "4", "5", "6", "7", | |||
"8", "9", "A", "B", "C", "D", "E", "F"}; | |||
private static final int NUM_BYTES_PER_BLOCK = 4; | |||
private static final int NUM_BYTES_PER_LINE = 24; | |||
private ByteUtil() {} | |||
/** | |||
@@ -46,26 +47,26 @@ public final class ByteUtil { | |||
* integer. | |||
* @param buffer buffer into which to insert the int | |||
* @param val Int to convert | |||
*/ | |||
*/ | |||
public static void put3ByteInt(ByteBuffer buffer, int val) | |||
{ | |||
put3ByteInt(buffer, val, buffer.order()); | |||
} | |||
/** | |||
* Put an integer into the given buffer at the given offset as a 3-byte | |||
* integer. | |||
* @param buffer buffer into which to insert the int | |||
* @param val Int to convert | |||
* @param order the order to insert the bytes of the int | |||
*/ | |||
*/ | |||
public static void put3ByteInt(ByteBuffer buffer, int val, ByteOrder order) | |||
{ | |||
int pos = buffer.position(); | |||
put3ByteInt(buffer, val, pos, order); | |||
buffer.position(pos + 3); | |||
} | |||
/** | |||
* Put an integer into the given buffer at the given offset as a 3-byte | |||
* integer. | |||
@@ -73,7 +74,7 @@ public final class ByteUtil { | |||
* @param val Int to convert | |||
* @param offset offset at which to insert the int | |||
* @param order the order to insert the bytes of the int | |||
*/ | |||
*/ | |||
public static void put3ByteInt(ByteBuffer buffer, int val, int offset, | |||
ByteOrder order) { | |||
@@ -103,7 +104,7 @@ public final class ByteUtil { | |||
* @param order the order of the bytes of the int | |||
* @return The int | |||
*/ | |||
public static int get3ByteInt(ByteBuffer buffer, ByteOrder order) { | |||
public static int get3ByteInt(ByteBuffer buffer, ByteOrder order) { | |||
int pos = buffer.position(); | |||
int rtn = get3ByteInt(buffer, pos, order); | |||
buffer.position(pos + 3); | |||
@@ -119,7 +120,7 @@ public final class ByteUtil { | |||
public static int get3ByteInt(ByteBuffer buffer, int offset) { | |||
return get3ByteInt(buffer, offset, buffer.order()); | |||
} | |||
/** | |||
* Read a 3 byte int from a buffer | |||
* @param buffer Buffer containing the bytes | |||
@@ -135,7 +136,7 @@ public final class ByteUtil { | |||
offInc = -1; | |||
offset += 2; | |||
} | |||
int rtn = getUnsignedByte(buffer, offset); | |||
rtn += (getUnsignedByte(buffer, offset + (1 * offInc)) << 8); | |||
rtn += (getUnsignedByte(buffer, offset + (2 * offInc)) << 16); | |||
@@ -160,10 +161,10 @@ public final class ByteUtil { | |||
* @param offset Offset at which to read the byte | |||
* @return The unsigned byte as an int | |||
*/ | |||
public static int getUnsignedByte(ByteBuffer buffer, int offset) { | |||
public static int getUnsignedByte(ByteBuffer buffer, int offset) { | |||
return asUnsignedByte(buffer.get(offset)); | |||
} | |||
/** | |||
* Read an unsigned short from a buffer | |||
* @param buffer Buffer containing the short | |||
@@ -182,11 +183,11 @@ public final class ByteUtil { | |||
* @param offset Offset at which to read the short | |||
* @return The unsigned short as an int | |||
*/ | |||
public static int getUnsignedShort(ByteBuffer buffer, int offset) { | |||
public static int getUnsignedShort(ByteBuffer buffer, int offset) { | |||
return asUnsignedShort(buffer.getShort(offset)); | |||
} | |||
/** | |||
* @param buffer Buffer containing the bytes | |||
* @param order the order of the bytes of the int | |||
@@ -199,7 +200,7 @@ public final class ByteUtil { | |||
buffer.position(offset + 4); | |||
return rtn; | |||
} | |||
/** | |||
* @param buffer Buffer containing the bytes | |||
* @param offset Offset at which to start reading the int | |||
@@ -215,7 +216,7 @@ public final class ByteUtil { | |||
buffer.order(origOrder); | |||
} | |||
} | |||
/** | |||
* Writes an int at the current position in the given buffer, using the | |||
* given ByteOrder | |||
@@ -228,7 +229,7 @@ public final class ByteUtil { | |||
putInt(buffer, val, offset, order); | |||
buffer.position(offset + 4); | |||
} | |||
/** | |||
* Writes an int at the given position in the given buffer, using the | |||
* given ByteOrder | |||
@@ -266,8 +267,8 @@ public final class ByteUtil { | |||
* @param offset Offset at which to read the value | |||
* @return The unsigned int | |||
*/ | |||
public static int getUnsignedVarInt(ByteBuffer buffer, int offset, | |||
int numBytes) { | |||
public static int getUnsignedVarInt(ByteBuffer buffer, int offset, | |||
int numBytes) { | |||
switch(numBytes) { | |||
case 1: | |||
return getUnsignedByte(buffer, offset); | |||
@@ -292,7 +293,7 @@ public final class ByteUtil { | |||
public static byte[] getBytes(ByteBuffer buffer, int len) | |||
{ | |||
byte[] bytes = new byte[len]; | |||
buffer.get(bytes); | |||
buffer.get(bytes); | |||
return bytes; | |||
} | |||
@@ -324,7 +325,7 @@ public final class ByteUtil { | |||
System.arraycopy(b2, 0, out, b1.length, b2.length); | |||
return out; | |||
} | |||
/** | |||
* Sets all bits in the given remaining byte range to 0. | |||
*/ | |||
@@ -354,7 +355,7 @@ public final class ByteUtil { | |||
{ | |||
putRange(buffer, start, end, (byte)0xff); | |||
} | |||
/** | |||
* Sets all bytes in the given byte range to the given byte value. | |||
*/ | |||
@@ -412,7 +413,7 @@ public final class ByteUtil { | |||
Arrays.fill(buf, pos, pos + len, (byte)0); | |||
buffer.limit(limit + len); | |||
} | |||
/** | |||
* Convert a byte buffer to a hexadecimal string for display | |||
* @param buffer Buffer to display, starting at offset 0 | |||
@@ -422,7 +423,7 @@ public final class ByteUtil { | |||
public static String toHexString(ByteBuffer buffer, int size) { | |||
return toHexString(buffer, 0, size); | |||
} | |||
/** | |||
* Convert a byte array to a hexadecimal string for display | |||
* @param array byte array to display, starting at offset 0 | |||
@@ -431,7 +432,7 @@ public final class ByteUtil { | |||
public static String toHexString(byte[] array) { | |||
return toHexString(ByteBuffer.wrap(array), 0, array.length); | |||
} | |||
/** | |||
* Convert a byte buffer to a hexadecimal string for display | |||
* @param buffer Buffer to display, starting at offset 0 | |||
@@ -441,7 +442,7 @@ public final class ByteUtil { | |||
*/ | |||
public static String toHexString(ByteBuffer buffer, int offset, int size) { | |||
return toHexString(buffer, offset, size, true); | |||
} | |||
} | |||
/** | |||
* Convert a byte buffer to a hexadecimal string for display | |||
@@ -453,10 +454,10 @@ public final class ByteUtil { | |||
*/ | |||
public static String toHexString(ByteBuffer buffer, | |||
int offset, int size, boolean formatted) { | |||
int bufLen = size * 2; | |||
if(formatted) { | |||
bufLen += size + | |||
bufLen += size + | |||
(7 * ((size + NUM_BYTES_PER_LINE - 1) / NUM_BYTES_PER_LINE)); | |||
} | |||
StringBuilder rtn = new StringBuilder(bufLen); | |||
@@ -481,7 +482,7 @@ public final class ByteUtil { | |||
rtn.append("\n"); | |||
} else { | |||
rtn.append(" "); | |||
if ((next % NUM_BYTES_PER_BLOCK) == 0) { | |||
@@ -530,7 +531,7 @@ public final class ByteUtil { | |||
*/ | |||
public static void toHexFile( | |||
String fileName, | |||
ByteBuffer buffer, | |||
ByteBuffer buffer, | |||
int offset, int size) | |||
throws IOException | |||
{ | |||
@@ -546,14 +547,14 @@ public final class ByteUtil { | |||
/** | |||
* @return the byte value converted to an unsigned int value | |||
*/ | |||
public static int asUnsignedByte(byte b) { | |||
public static int asUnsignedByte(byte b) { | |||
return b & 0xFF; | |||
} | |||
/** | |||
* @return the short value converted to an unsigned int value | |||
*/ | |||
public static int asUnsignedShort(short s) { | |||
public static int asUnsignedShort(short s) { | |||
return s & 0xFFFF; | |||
} | |||
@@ -637,7 +638,7 @@ public final class ByteUtil { | |||
* Returns a copy of the given array of the given length starting at the | |||
* given position. | |||
*/ | |||
public static byte[] copyOf(byte[] arr, int offset, int newLength, | |||
public static byte[] copyOf(byte[] arr, int offset, int newLength, | |||
int dstOffset) | |||
{ | |||
byte[] newArr = new byte[newLength]; | |||
@@ -669,6 +670,18 @@ public final class ByteUtil { | |||
} | |||
} | |||
/** | |||
* Skips the given number of bytes in the given stream | |||
*/ | |||
public static void skipFully(DataInputStream din, int len) | |||
throws IOException | |||
{ | |||
do { | |||
int skipped = din.skipBytes(len); | |||
len -= skipped; | |||
} while(len > 0); | |||
} | |||
/** | |||
* Utility byte stream similar to ByteArrayOutputStream but with extended | |||
* accessibility to the bytes. |
@@ -50,7 +50,7 @@ public class ColValidatorEvalContext extends ColEvalContext | |||
@Override | |||
protected Object internalValidate(Column col, Object val) | |||
throws IOException { | |||
return ColValidatorEvalContext.this.validate(col, val); | |||
return ColValidatorEvalContext.this.validate(val); | |||
} | |||
@Override | |||
protected void appendToString(StringBuilder sb) { | |||
@@ -78,7 +78,7 @@ public class ColValidatorEvalContext extends ColEvalContext | |||
return getThisColumnValue(); | |||
} | |||
private Object validate(Column col, Object val) throws IOException { | |||
private Object validate(Object val) throws IOException { | |||
try { | |||
_val = val; | |||
Boolean result = (Boolean)eval(); |
@@ -41,14 +41,14 @@ import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; | |||
/** | |||
* Utility code for working with OLE data which is in the compound storage | |||
* format. This functionality relies on the optional POI library. | |||
* <p/> | |||
* <p/> | |||
* Note that all POI usage is restricted to this file so that the basic ole | |||
* support in OleUtil can be utilized without requiring POI. | |||
* | |||
* @author James Ahlborn | |||
* @usage _advanced_class_ | |||
*/ | |||
public class CompoundOleUtil implements OleUtil.CompoundPackageFactory | |||
public class CompoundOleUtil implements CompoundPackageFactory | |||
{ | |||
private static final String ENTRY_NAME_CHARSET = "UTF-8"; | |||
private static final String ENTRY_SEPARATOR = "/"; | |||
@@ -60,7 +60,7 @@ public class CompoundOleUtil implements OleUtil.CompoundPackageFactory | |||
NPOIFSFileSystem.class.getName(); | |||
} | |||
public CompoundOleUtil() | |||
public CompoundOleUtil() | |||
{ | |||
} | |||
@@ -87,8 +87,8 @@ public class CompoundOleUtil implements OleUtil.CompoundPackageFactory | |||
* @throws IOException if some other io error occurs | |||
*/ | |||
public static DocumentEntry getDocumentEntry(String entryName, | |||
DirectoryEntry dir) | |||
throws IOException | |||
DirectoryEntry dir) | |||
throws IOException | |||
{ | |||
// split entry name into individual components and decode them | |||
List<String> entryNames = new ArrayList<String>(); | |||
@@ -109,9 +109,9 @@ public class CompoundOleUtil implements OleUtil.CompoundPackageFactory | |||
entry = (DocumentEntry)tmpEntry; | |||
} else { | |||
break; | |||
} | |||
} | |||
} | |||
if(entry == null) { | |||
throw new FileNotFoundException("Could not find document " + entryName); | |||
} | |||
@@ -135,7 +135,7 @@ public class CompoundOleUtil implements OleUtil.CompoundPackageFactory | |||
} | |||
} | |||
private static final class CompoundContentImpl | |||
private static final class CompoundContentImpl | |||
extends EmbeddedPackageContentImpl | |||
implements CompoundContent | |||
{ | |||
@@ -143,10 +143,10 @@ public class CompoundOleUtil implements OleUtil.CompoundPackageFactory | |||
private CompoundContentImpl( | |||
OleBlobImpl blob, String prettyName, String className, | |||
String typeName, int position, int length) | |||
String typeName, int position, int length) | |||
{ | |||
super(blob, prettyName, className, typeName, position, length); | |||
} | |||
} | |||
public ContentType getType() { | |||
return ContentType.COMPOUND_STORAGE; | |||
@@ -169,7 +169,7 @@ public class CompoundOleUtil implements OleUtil.CompoundPackageFactory | |||
} | |||
public EntryImpl getEntry(String entryName) throws IOException { | |||
return new EntryImpl(entryName, | |||
return new EntryImpl(entryName, | |||
getDocumentEntry(entryName, getFileSystem().getRoot())); | |||
} | |||
@@ -181,7 +181,7 @@ public class CompoundOleUtil implements OleUtil.CompoundPackageFactory | |||
return getEntry(CONTENTS_ENTRY); | |||
} | |||
private List<Entry> getEntries(List<Entry> entries, DirectoryEntry dir, | |||
private List<Entry> getEntries(List<Entry> entries, DirectoryEntry dir, | |||
String prefix) { | |||
for(org.apache.poi.poifs.filesystem.Entry entry : dir) { | |||
if (entry instanceof DirectoryEntry) { | |||
@@ -210,10 +210,10 @@ public class CompoundOleUtil implements OleUtil.CompoundPackageFactory | |||
try { | |||
sb.append("hasContentsEntry", hasContentsEntry()); | |||
sb.append("entries", getEntries(new ArrayList<Entry>(), | |||
sb.append("entries", getEntries(new ArrayList<Entry>(), | |||
getFileSystem().getRoot(), | |||
ENTRY_SEPARATOR)); | |||
} catch(IOException e) { | |||
} catch(IOException e) { | |||
sb.append("entries", "<" + e + ">"); | |||
} | |||
@@ -270,7 +270,7 @@ public class CompoundOleUtil implements OleUtil.CompoundPackageFactory | |||
.append("length", length()) | |||
.toString(); | |||
} | |||
} | |||
} | |||
} | |||
} |
@@ -82,7 +82,7 @@ public class DBEvalContext implements Expressionator.ParseContext, EvalConfig | |||
_sdfs = new SimpleCache<String,SimpleDateFormat>(MAX_CACHE_SIZE); | |||
} | |||
SimpleDateFormat sdf = _sdfs.get(formatStr); | |||
if(formatStr == null) { | |||
if(sdf == null) { | |||
sdf = _db.createDateFormat(formatStr); | |||
_sdfs.put(formatStr, sdf); | |||
} |
@@ -54,7 +54,7 @@ public class AttachmentColumnInfoImpl extends ComplexColumnInfoImpl<Attachment> | |||
{ | |||
/** some file formats which may not be worth re-compressing */ | |||
private static final Set<String> COMPRESSED_FORMATS = new HashSet<String>( | |||
Arrays.asList("jpg", "zip", "gz", "bz2", "z", "7z", "cab", "rar", | |||
Arrays.asList("jpg", "zip", "gz", "bz2", "z", "7z", "cab", "rar", | |||
"mp3", "mpg")); | |||
private static final String FILE_NAME_COL_NAME = "FileName"; | |||
@@ -73,7 +73,7 @@ public class AttachmentColumnInfoImpl extends ComplexColumnInfoImpl<Attachment> | |||
private final Column _fileDataCol; | |||
private final Column _fileTimeStampCol; | |||
private final Column _fileFlagsCol; | |||
public AttachmentColumnInfoImpl(Column column, int complexId, | |||
Table typeObjTable, Table flatTable) | |||
throws IOException | |||
@@ -119,7 +119,7 @@ public class AttachmentColumnInfoImpl extends ComplexColumnInfoImpl<Attachment> | |||
// ignore | |||
} | |||
} | |||
_fileUrlCol = fileUrlCol; | |||
_fileNameCol = fileNameCol; | |||
_fileTypeCol = fileTypeCol; | |||
@@ -131,7 +131,7 @@ public class AttachmentColumnInfoImpl extends ComplexColumnInfoImpl<Attachment> | |||
public Column getFileUrlColumn() { | |||
return _fileUrlCol; | |||
} | |||
public Column getFileNameColumn() { | |||
return _fileNameCol; | |||
} | |||
@@ -139,19 +139,19 @@ public class AttachmentColumnInfoImpl extends ComplexColumnInfoImpl<Attachment> | |||
public Column getFileTypeColumn() { | |||
return _fileTypeCol; | |||
} | |||
public Column getFileDataColumn() { | |||
return _fileDataCol; | |||
} | |||
public Column getFileTimeStampColumn() { | |||
return _fileTimeStampCol; | |||
} | |||
public Column getFileFlagsColumn() { | |||
return _fileFlagsCol; | |||
} | |||
} | |||
@Override | |||
public ComplexDataType getType() | |||
{ | |||
@@ -168,14 +168,14 @@ public class AttachmentColumnInfoImpl extends ComplexColumnInfoImpl<Attachment> | |||
Integer flags = (Integer)getFileFlagsColumn().getRowValue(rawValue); | |||
Date ts = (Date)getFileTimeStampColumn().getRowValue(rawValue); | |||
byte[] data = (byte[])getFileDataColumn().getRowValue(rawValue); | |||
return new AttachmentImpl(id, complexValueFk, url, name, type, null, | |||
ts, flags, data); | |||
} | |||
@Override | |||
protected Object[] asRow(Object[] row, Attachment attachment) | |||
throws IOException | |||
protected Object[] asRow(Object[] row, Attachment attachment) | |||
throws IOException | |||
{ | |||
super.asRow(row, attachment); | |||
getFileUrlColumn().setRowValue(row, attachment.getFileUrl()); | |||
@@ -190,7 +190,7 @@ public class AttachmentColumnInfoImpl extends ComplexColumnInfoImpl<Attachment> | |||
public static Attachment newAttachment(byte[] data) { | |||
return newAttachment(INVALID_FK, data); | |||
} | |||
public static Attachment newAttachment(ComplexValueForeignKey complexValueFk, | |||
byte[] data) { | |||
return newAttachment(complexValueFk, null, null, null, data, null, null); | |||
@@ -203,7 +203,7 @@ public class AttachmentColumnInfoImpl extends ComplexColumnInfoImpl<Attachment> | |||
return newAttachment(INVALID_FK, url, name, type, data, | |||
timeStamp, flags); | |||
} | |||
public static Attachment newAttachment( | |||
ComplexValueForeignKey complexValueFk, String url, String name, | |||
String type, byte[] data, Date timeStamp, Integer flags) | |||
@@ -215,30 +215,30 @@ public class AttachmentColumnInfoImpl extends ComplexColumnInfoImpl<Attachment> | |||
public static Attachment newEncodedAttachment(byte[] encodedData) { | |||
return newEncodedAttachment(INVALID_FK, encodedData); | |||
} | |||
public static Attachment newEncodedAttachment( | |||
ComplexValueForeignKey complexValueFk, byte[] encodedData) { | |||
return newEncodedAttachment(complexValueFk, null, null, null, encodedData, | |||
null, null); | |||
} | |||
public static Attachment newEncodedAttachment( | |||
String url, String name, String type, byte[] encodedData, | |||
Date timeStamp, Integer flags) | |||
{ | |||
return newEncodedAttachment(INVALID_FK, url, name, type, | |||
return newEncodedAttachment(INVALID_FK, url, name, type, | |||
encodedData, timeStamp, flags); | |||
} | |||
public static Attachment newEncodedAttachment( | |||
ComplexValueForeignKey complexValueFk, String url, String name, | |||
String type, byte[] encodedData, Date timeStamp, Integer flags) | |||
{ | |||
return new AttachmentImpl(INVALID_ID, complexValueFk, url, name, type, | |||
null, timeStamp, flags, encodedData); | |||
} | |||
} | |||
private static class AttachmentImpl extends ComplexValueImpl | |||
implements Attachment | |||
{ | |||
@@ -263,7 +263,7 @@ public class AttachmentColumnInfoImpl extends ComplexColumnInfoImpl<Attachment> | |||
_flags = flags; | |||
_encodedData = encodedData; | |||
} | |||
public byte[] getFileData() throws IOException { | |||
if((_data == null) && (_encodedData != null)) { | |||
_data = decodeData(); | |||
@@ -295,7 +295,7 @@ public class AttachmentColumnInfoImpl extends ComplexColumnInfoImpl<Attachment> | |||
public void setFileName(String fileName) { | |||
_name = fileName; | |||
} | |||
public String getFileUrl() { | |||
return _url; | |||
} | |||
@@ -303,7 +303,7 @@ public class AttachmentColumnInfoImpl extends ComplexColumnInfoImpl<Attachment> | |||
public void setFileUrl(String fileUrl) { | |||
_url = fileUrl; | |||
} | |||
public String getFileType() { | |||
return _type; | |||
} | |||
@@ -311,7 +311,7 @@ public class AttachmentColumnInfoImpl extends ComplexColumnInfoImpl<Attachment> | |||
public void setFileType(String fileType) { | |||
_type = fileType; | |||
} | |||
public Date getFileTimeStamp() { | |||
return _timeStamp; | |||
} | |||
@@ -319,23 +319,23 @@ public class AttachmentColumnInfoImpl extends ComplexColumnInfoImpl<Attachment> | |||
public void setFileTimeStamp(Date fileTimeStamp) { | |||
_timeStamp = fileTimeStamp; | |||
} | |||
public Integer getFileFlags() { | |||
return _flags; | |||
} | |||
public void setFileFlags(Integer fileFlags) { | |||
_flags = fileFlags; | |||
} | |||
} | |||
public void update() throws IOException { | |||
getComplexValueForeignKey().updateAttachment(this); | |||
} | |||
public void delete() throws IOException { | |||
getComplexValueForeignKey().deleteAttachment(this); | |||
} | |||
@Override | |||
public String toString() { | |||
@@ -345,12 +345,12 @@ public class AttachmentColumnInfoImpl extends ComplexColumnInfoImpl<Attachment> | |||
} catch(IOException e) { | |||
dataStr = e.toString(); | |||
} | |||
return "Attachment(" + getComplexValueForeignKey() + "," + getId() + | |||
") " + getFileUrl() + ", " + getFileName() + ", " + getFileType() | |||
+ ", " + getFileTimeStamp() + ", " + getFileFlags() + ", " + | |||
dataStr; | |||
} | |||
} | |||
/** | |||
* Decodes the raw attachment file data to get the _actual_ content. | |||
@@ -361,7 +361,7 @@ public class AttachmentColumnInfoImpl extends ComplexColumnInfoImpl<Attachment> | |||
// nothing we can do | |||
throw new IOException("Unknown encoded attachment data format"); | |||
} | |||
// read initial header info | |||
ByteBuffer bb = PageChannel.wrap(_encodedData); | |||
int typeFlag = bb.getInt(); | |||
@@ -391,7 +391,7 @@ public class AttachmentColumnInfoImpl extends ComplexColumnInfoImpl<Attachment> | |||
byte[] tmpBytes = new byte[4]; | |||
contentStream.readFully(tmpBytes); | |||
int headerLen = PageChannel.wrap(tmpBytes).getInt(); | |||
contentStream.skipBytes(headerLen - 4); | |||
ByteUtil.skipFully(contentStream, headerLen - 4); | |||
// calculate actual data length and read it (note, header length | |||
// includes the bytes for the length) |
@@ -45,7 +45,6 @@ public class DefaultDateFunctions | |||
private static final long SECONDS_PER_HOUR = 60L * 60L; | |||
private static final long SECONDS_PER_MINUTE = 60L; | |||
private static final long MILLIS_PER_SECOND = 1000L; | |||
private DefaultDateFunctions() {} | |||
@@ -203,10 +202,12 @@ public class DefaultDateFunctions | |||
} | |||
private static Calendar nonNullToCalendar(EvalContext ctx, Value param) { | |||
Value origParam = param; | |||
param = nonNullToDateValue(ctx, param); | |||
if(param == null) { | |||
// not a date/time | |||
throw new EvalException("Invalid date/time expression '" + param + "'"); | |||
throw new EvalException("Invalid date/time expression '" + | |||
origParam + "'"); | |||
} | |||
Calendar cal = getDateValueFormat(ctx, param).getCalendar(); |