alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/* Copyright (c) 2001-2004, The HSQL Development Group
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * Neither the name of the HSQL Development Group nor the names of its
 * contributors may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG, 
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */


package org.hsqldb;

import java.io.IOException;
import java.io.UnsupportedEncodingException;

import org.hsqldb.lib.FileUtil;
import org.hsqldb.lib.HsqlByteArrayOutputStream;
import org.hsqldb.rowio.RowInputText;
import org.hsqldb.rowio.RowInputTextQuoted;
import org.hsqldb.rowio.RowOutputText;
import org.hsqldb.rowio.RowOutputTextQuoted;
import org.hsqldb.scriptio.ScriptWriterText;

// Ito Kazumitsu 20030328 - patch 1.7.2 - character encoding support

/** @todo fredt - file error messages to Trace */

/**
 * Acts as a buffer manager for a single TEXT table with respect its Row data.
 *
 * Handles read/write operations on the table's text format data file using a
 * compatible pair of org.hsqldb.rowio input/output class instances.
 *
 * @author sqlbob@users (RMP)
 * @version 1.7.2
 */
public class TextCache extends DataFileCache {

    //state of Cache
    protected boolean          isIndexingSource;
    public static final String NL = System.getProperty("line.separator");
    String                     fs;
    String                     vs;
    String                     lvs;
    String                     stringEncoding;
    protected boolean          readOnly;
    protected RowInputText     rowIn;
    protected boolean          isQuoted;
    protected boolean          isAllQuoted;
    protected boolean          ignoreFirst;
    protected String           ignoredFirst = NL;
    protected Table            table;

    /**
     *  The source string for a cached table is evaluated and the parameters
     *  are used to open the source file.

* * Settings are used in this order: (1) settings specified in the * source string for the table (2) global database settings in * *.properties file (3) program defaults */ TextCache(String name, Table table) throws HsqlException { super(name, table.database); this.table = table; } protected void initParams() throws HsqlException { // fredt - write rows as soon as they are inserted storeOnInsert = true; HsqlProperties tableprops = HsqlProperties.delimitedArgPairsToProps(sName, "=", ";", null); //-- Get file name switch (tableprops.errorCodes.length) { case 0 : throw Trace.error(Trace.TEXT_TABLE_SOURCE, Trace.TEXT_TABLE_SOURCE_FILENAME); case 1 : // source file name is the only key without a value sName = tableprops.errorKeys[0].trim(); break; default : throw Trace.error(Trace.TEXT_TABLE_SOURCE, Trace.TEXT_TABLE_SOURCE_VALUE_MISSING, tableprops.errorKeys[1]); } //-- Get separators: fs = translateSep(tableprops.getProperty("fs", dbProps.getProperty("textdb.fs", ","))); vs = translateSep(tableprops.getProperty("vs", dbProps.getProperty("textdb.vs", fs))); lvs = translateSep(tableprops.getProperty("lvs", dbProps.getProperty("textdb.lvs", fs))); if (fs.length() == 0 || vs.length() == 0 || lvs.length() == 0) { throw Trace.error(Trace.TEXT_TABLE_SOURCE, Trace.TEXT_TABLE_SOURCE_SEPARATOR); } //-- Get booleans ignoreFirst = tableprops.isPropertyTrue("ignore_first", dbProps.isPropertyTrue("textdb.ignore_first", false)); isQuoted = tableprops.isPropertyTrue("quoted", dbProps.isPropertyTrue("textdb.quoted", true)); isAllQuoted = tableprops.isPropertyTrue("all_quoted", dbProps.isPropertyTrue("textdb.all_quoted", false)); //-- Get encoding stringEncoding = translateSep(tableprops.getProperty("encoding", dbProps.getProperty("textdb.encoding", "ASCII"))); //-- Get size and scale cacheScale = tableprops.getIntegerProperty("cache_scale", dbProps.getIntegerProperty("textdb.cache_scale", 10, 8, 16)); cacheSizeScale = tableprops.getIntegerProperty("cache_size_scale", dbProps.getIntegerProperty("textdb.cache_size_scale", 12, 8, 20)); try { if (isQuoted || isAllQuoted) { rowIn = new RowInputTextQuoted(fs, vs, lvs, isAllQuoted); rowOut = new RowOutputTextQuoted(fs, vs, lvs, isAllQuoted, stringEncoding); } else { rowIn = new RowInputText(fs, vs, lvs, false); rowOut = new RowOutputText(fs, vs, lvs, false, stringEncoding); } } catch (IOException e) { // no exception expected here the IOException is vestigial throw (Trace.error(Trace.TEXT_TABLE_SOURCE, "invalid file: " + e)); } } protected void initBuffers() throws HsqlException {} private String translateSep(String sep) { return translateSep(sep, false); } /** * Translates the escaped characters in a separator string and returns * the non-escaped string. */ private String translateSep(String sep, boolean isProperty) { if (sep == null) { return (null); } int next = 0; if ((next = sep.indexOf('\\')) != -1) { int start = 0; char sepArray[] = sep.toCharArray(); char ch = 0; int len = sep.length(); StringBuffer realSep = new StringBuffer(len); do { realSep.append(sepArray, start, next - start); start = ++next; if (next >= len) { realSep.append('\\'); break; } if (!isProperty) { ch = sepArray[next]; } if (ch == 'n') { realSep.append('\n'); start++; } else if (ch == 'r') { realSep.append('\r'); start++; } else if (ch == 't') { realSep.append('\t'); start++; } else if (ch == '\\') { realSep.append('\\'); start++; } else if (ch == 'u') { start++; realSep.append( (char) Integer.parseInt( sep.substring(start, start + 4), 16)); start += 4; } else if (sep.startsWith("semi", next)) { realSep.append(';'); start += 4; } else if (sep.startsWith("space", next)) { realSep.append(' '); start += 5; } else if (sep.startsWith("quote", next)) { realSep.append('\"'); start += 5; } else if (sep.startsWith("apos", next)) { realSep.append('\''); start += 4; } else { realSep.append('\\'); realSep.append(sepArray[next]); start++; } } while ((next = sep.indexOf('\\', start)) != -1); realSep.append(sepArray, start, len - start); sep = realSep.toString(); } return sep; } /** * Opens a data source file. */ void open(boolean readonly) throws HsqlException { try { rFile = ScaledRAFile.newScaledRAFile(sName, readonly, 1, ScaledRAFile.DATA_FILE_RAF); iFreePos = (int) rFile.length(); if ((iFreePos == 0) && ignoreFirst) { byte[] buf = null; try { buf = ignoredFirst.getBytes(stringEncoding); } catch (UnsupportedEncodingException e) { buf = ignoredFirst.getBytes(); } rFile.write(buf, 0, buf.length); iFreePos = ignoredFirst.length(); } } catch (Exception e) { throw Trace.error(Trace.FILE_IO_ERROR, Trace.TextCache_openning_file_error, new Object[] { sName, e }); } readOnly = readonly; } void reopen() throws HsqlException { open(readOnly); rowIn.reset(); } /** * Writes newly created rows to disk. In the current implentation, * such rows have already been saved, so this method just removes a * source file that has no rows. */ void close() throws HsqlException { if (rFile == null) { return; } try { saveAll(); boolean empty = (rFile.length() <= NL.length()); rFile.close(); rFile = null; if (empty &&!readOnly) { FileUtil.delete(sName); } } catch (Exception e) { throw Trace.error(Trace.FILE_IO_ERROR, Trace.TextCache_closing_file_error, new Object[] { sName, e }); } } /** * Closes the source file and deletes it if it is not read-only. */ void purge() throws HsqlException { if (rFile == null) { return; } try { if (readOnly) { close(); } else { rFile.close(); rFile = null; FileUtil.delete(sName); } } catch (Exception e) { throw Trace.error(Trace.FILE_IO_ERROR, Trace.TextCache_purging_file_error, new Object[] { sName, e }); } } /** * */ void free(CachedRow r) throws HsqlException { if (storeOnInsert &&!isIndexingSource) { int pos = r.iPos; int length = r.storageSize - ScriptWriterText.BYTES_LINE_SEP.length; rowOut.reset(); HsqlByteArrayOutputStream out = rowOut.getOutputStream(); try { out.fill(' ', length); out.write(ScriptWriterText.BYTES_LINE_SEP); rFile.seek(pos); rFile.write(out.getBuffer(), 0, out.size()); } catch (IOException e) { throw (Trace.error(Trace.FILE_IO_ERROR, e.toString())); } } remove(r); } protected void setStorageSize(CachedRow r) throws HsqlException { r.storageSize = rowOut.getSize(r); } protected CachedRow makeRow(int pos, Table t) throws HsqlException { CachedRow r = null; try { // HsqlStringBuffer buffer = new HsqlStringBuffer(80); ByteArray buffer = new ByteArray(80); boolean blank = true; boolean complete = false; try { // char c; int c; int next; rFile.seek(pos); //-- The following should work for DOS, MAC, and Unix line //-- separators regardless of host OS. while (true) { next = rFile.read(); if (next == -1) { break; } // c = (char) (next & 0xff); c = next; //-- Ensure line is complete. if (c == '\n') { buffer.append('\n'); //-- Store first line. if (ignoreFirst && pos == 0) { ignoredFirst = buffer.toString(); blank = true; } //-- Ignore blanks if (!blank) { complete = true; break; } else { pos += buffer.length(); buffer.setLength(0); blank = true; rowIn.skippedLine(); continue; } } if (c == '\r') { //-- Check for newline try { next = rFile.read(); if (next == -1) { break; } // c = (char) (next & 0xff); c = next; if (c == '\n') { buffer.append('\n'); } } catch (Exception e2) { ; } buffer.append('\n'); //-- Store first line. //-- Currently this is of no use as it is lost in // shutdown compact. We might want to store this in // the *.script file at that point to be reused for // reconstructing the data source file. // if (ignoreFirst && pos == 0) { ignoredFirst = buffer.toString(); blank = true; } //-- Ignore blanks. if (!blank) { complete = true; break; } else { pos += buffer.length(); buffer.setLength(0); blank = true; rowIn.skippedLine(); continue; } } if (c != ' ') { blank = false; } buffer.append(c); } } catch (Exception e) { complete = false; } if (complete) { // rowIn.setSource(buffer.toString(), pos); rowIn.setSource(buffer.toString(), pos, buffer.length()); if (isIndexingSource) { r = new PointerCachedDataRow(t, rowIn); } else { r = new CachedDataRow(t, rowIn); } } } catch (Exception e) { throw Trace.error(Trace.TEXT_FILE, e); } return r; } private class ByteArray { private byte[] buffer; private int buflen; public ByteArray(int n) { buffer = new byte[n]; buflen = 0; } public void append(int c) { if (buflen >= buffer.length) { byte[] newbuf = new byte[buflen + 80]; System.arraycopy(buffer, 0, newbuf, 0, buflen); buffer = newbuf; } buffer[buflen] = (byte) c; buflen++; } public int length() { return buflen; } public void setLength(int l) { buflen = l; } public String toString() { try { return new String(buffer, 0, buflen, stringEncoding); } catch (UnsupportedEncodingException e) { return new String(buffer, 0, buflen); } } } int getLineNumber() { return rowIn.getLineNumber(); } void setSourceIndexing(boolean mode) { isIndexingSource = mode; } }

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.