Now saves shops to a SQLite Database

This commit is contained in:
Eric 2015-09-06 11:58:25 +02:00
parent 477b6a4701
commit ae756f43e7
36 changed files with 6983 additions and 143 deletions

106
libs/org/sqlite/Codes.java Normal file
View File

@ -0,0 +1,106 @@
/*
* Copyright (c) 2007 David Crawshaw <david@zentus.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package org.sqlite;
interface Codes
{
/** Successful result */
public static final int SQLITE_OK = 0;
/** SQL error or missing database */
public static final int SQLITE_ERROR = 1;
/** An internal logic error in SQLite */
public static final int SQLITE_INTERNAL = 2;
/** Access permission denied */
public static final int SQLITE_PERM = 3;
/** Callback routine requested an abort */
public static final int SQLITE_ABORT = 4;
/** The database file is locked */
public static final int SQLITE_BUSY = 5;
/** A table in the database is locked */
public static final int SQLITE_LOCKED = 6;
/** A malloc() failed */
public static final int SQLITE_NOMEM = 7;
/** Attempt to write a readonly database */
public static final int SQLITE_READONLY = 8;
/** Operation terminated by sqlite_interrupt() */
public static final int SQLITE_INTERRUPT = 9;
/** Some kind of disk I/O error occurred */
public static final int SQLITE_IOERR = 10;
/** The database disk image is malformed */
public static final int SQLITE_CORRUPT = 11;
/** (Internal Only) Table or record not found */
public static final int SQLITE_NOTFOUND = 12;
/** Insertion failed because database is full */
public static final int SQLITE_FULL = 13;
/** Unable to open the database file */
public static final int SQLITE_CANTOPEN = 14;
/** Database lock protocol error */
public static final int SQLITE_PROTOCOL = 15;
/** (Internal Only) Database table is empty */
public static final int SQLITE_EMPTY = 16;
/** The database schema changed */
public static final int SQLITE_SCHEMA = 17;
/** Too much data for one row of a table */
public static final int SQLITE_TOOBIG = 18;
/** Abort due to constraint violation */
public static final int SQLITE_CONSTRAINT = 19;
/** Data type mismatch */
public static final int SQLITE_MISMATCH = 20;
/** Library used incorrectly */
public static final int SQLITE_MISUSE = 21;
/** Uses OS features not supported on host */
public static final int SQLITE_NOLFS = 22;
/** Authorization denied */
public static final int SQLITE_AUTH = 23;
/** sqlite_step() has another row ready */
public static final int SQLITE_ROW = 100;
/** sqlite_step() has finished executing */
public static final int SQLITE_DONE = 101;
// types returned by sqlite3_column_type()
public static final int SQLITE_INTEGER = 1;
public static final int SQLITE_FLOAT = 2;
public static final int SQLITE_TEXT = 3;
public static final int SQLITE_BLOB = 4;
public static final int SQLITE_NULL = 5;
}

440
libs/org/sqlite/Conn.java Normal file
View File

@ -0,0 +1,440 @@
/*
* Copyright (c) 2007 David Crawshaw <david@zentus.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package org.sqlite;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.Savepoint;
import java.sql.Statement;
import java.sql.Struct;
import java.util.Map;
import java.util.Properties;
class Conn implements Connection
{
private final String url;
private String fileName;
private DB db = null;
private MetaData meta = null;
private boolean autoCommit = true;
private int transactionIsolation = TRANSACTION_SERIALIZABLE;
private int timeout = 0;
public Conn(String url, String fileName) throws SQLException {
this(url, fileName, new Properties());
}
public Conn(String url, String fileName, Properties prop) throws SQLException {
this.url = url;
this.fileName = fileName;
SQLiteConfig config = new SQLiteConfig(prop);
open(config.getOpenModeFlags());
boolean enableSharedCache = config.isEnabledSharedCache();
boolean enableLoadExtension = config.isEnabledLoadExtension();
db.shared_cache(enableSharedCache);
db.enable_load_extension(enableLoadExtension);
// set pragmas
config.apply(this);
}
private static final String RESOURCE_NAME_PREFIX = ":resource:";
private void open(int openModeFlags) throws SQLException {
// check the path to the file exists
if (!":memory:".equals(fileName)) {
if (fileName.startsWith(RESOURCE_NAME_PREFIX)) {
String resourceName = fileName.substring(RESOURCE_NAME_PREFIX.length());
// search the class path
ClassLoader contextCL = Thread.currentThread().getContextClassLoader();
URL resourceAddr = contextCL.getResource(resourceName);
if (resourceAddr == null) {
try {
resourceAddr = new URL(resourceName);
}
catch (MalformedURLException e) {
throw new SQLException(String.format("resource %s not found: %s", resourceName, e));
}
}
try {
fileName = extractResource(resourceAddr).getAbsolutePath();
}
catch (IOException e) {
throw new SQLException(String.format("failed to load %s: %s", resourceName, e));
}
}
else {
File file = new File(fileName).getAbsoluteFile();
File parent = file.getParentFile();
if (parent != null && !parent.exists()) {
for (File up = parent; up != null && !up.exists();) {
parent = up;
up = up.getParentFile();
}
throw new SQLException("path to '" + fileName + "': '" + parent + "' does not exist");
}
// check write access if file does not exist
try {
// The extra check to exists() is necessary as createNewFile()
// does not follow the JavaDoc when used on read-only shares.
if (!file.exists() && file.createNewFile())
file.delete();
}
catch (Exception e) {
throw new SQLException("opening db: '" + fileName + "': " + e.getMessage());
}
fileName = file.getAbsolutePath();
}
}
// tries to load native library first
try {
Class< ? > nativedb = Class.forName("org.sqlite.NativeDB");
if (((Boolean) nativedb.getDeclaredMethod("load", (Class< ? >[]) null).invoke((Object) null,
(Object[]) null)).booleanValue())
db = (DB) nativedb.newInstance();
}
catch (Exception e) {} // fall through to nested library
// load nested library (pure-java SQLite)
if (db == null) {
try {
db = (DB) Class.forName("org.sqlite.NestedDB").newInstance();
}
catch (Exception e) {
throw new SQLException("no SQLite library found");
}
}
db.open(this, fileName, openModeFlags);
setTimeout(3000);
}
/**
* @param resourceAddr
* @return extracted file name
* @throws IOException
*/
private File extractResource(URL resourceAddr) throws IOException {
if (resourceAddr.getProtocol().equals("file")) {
try {
return new File(resourceAddr.toURI());
}
catch (URISyntaxException e) {
throw new IOException(e.getMessage());
}
}
String tempFolder = new File(System.getProperty("java.io.tmpdir")).getAbsolutePath();
String dbFileName = String.format("sqlite-jdbc-tmp-%d.db", resourceAddr.hashCode());
File dbFile = new File(tempFolder, dbFileName);
if (dbFile.exists()) {
long resourceLastModified = resourceAddr.openConnection().getLastModified();
long tmpFileLastModified = dbFile.lastModified();
if (resourceLastModified < tmpFileLastModified) {
return dbFile;
}
else {
// remove the old DB file
boolean deletionSucceeded = dbFile.delete();
if (!deletionSucceeded) {
throw new IOException("failed to remove existing DB file: " + dbFile.getAbsolutePath());
}
}
// String md5sum1 = SQLiteJDBCLoader.md5sum(resourceAddr.openStream());
// String md5sum2 = SQLiteJDBCLoader.md5sum(new FileInputStream(dbFile));
//
// if (md5sum1.equals(md5sum2))
// return dbFile; // no need to extract the DB file
// else
// {
// }
}
byte[] buffer = new byte[8192]; // 8K buffer
FileOutputStream writer = new FileOutputStream(dbFile);
InputStream reader = resourceAddr.openStream();
try {
int bytesRead = 0;
while ((bytesRead = reader.read(buffer)) != -1) {
writer.write(buffer, 0, bytesRead);
}
return dbFile;
}
finally {
writer.close();
reader.close();
}
}
int getTimeout() {
return timeout;
}
void setTimeout(int ms) throws SQLException {
timeout = ms;
db.busy_timeout(ms);
}
String url() {
return url;
}
String libversion() throws SQLException {
return db.libversion();
}
DB db() {
return db;
}
private void checkOpen() throws SQLException {
if (db == null)
throw new SQLException("database connection closed");
}
private void checkCursor(int rst, int rsc, int rsh) throws SQLException {
if (rst != ResultSet.TYPE_FORWARD_ONLY)
throw new SQLException("SQLite only supports TYPE_FORWARD_ONLY cursors");
if (rsc != ResultSet.CONCUR_READ_ONLY)
throw new SQLException("SQLite only supports CONCUR_READ_ONLY cursors");
if (rsh != ResultSet.CLOSE_CURSORS_AT_COMMIT)
throw new SQLException("SQLite only supports closing cursors at commit");
}
@Override
public void finalize() throws SQLException {
close();
}
public void close() throws SQLException {
if (db == null)
return;
if (meta != null)
meta.close();
db.close();
db = null;
}
public boolean isClosed() throws SQLException {
return db == null;
}
public String getCatalog() throws SQLException {
checkOpen();
return null;
}
public void setCatalog(String catalog) throws SQLException {
checkOpen();
}
public int getHoldability() throws SQLException {
checkOpen();
return ResultSet.CLOSE_CURSORS_AT_COMMIT;
}
public void setHoldability(int h) throws SQLException {
checkOpen();
if (h != ResultSet.CLOSE_CURSORS_AT_COMMIT)
throw new SQLException("SQLite only supports CLOSE_CURSORS_AT_COMMIT");
}
public int getTransactionIsolation() {
return transactionIsolation;
}
public void setTransactionIsolation(int level) throws SQLException {
switch (level) {
case TRANSACTION_SERIALIZABLE:
db.exec("PRAGMA read_uncommitted = false;");
break;
case TRANSACTION_READ_UNCOMMITTED:
db.exec("PRAGMA read_uncommitted = true;");
break;
default:
throw new SQLException("SQLite supports only TRANSACTION_SERIALIZABLE and TRANSACTION_READ_UNCOMMITTED.");
}
transactionIsolation = level;
}
public Map getTypeMap() throws SQLException {
throw new SQLException("not yet implemented");
}
public void setTypeMap(Map map) throws SQLException {
throw new SQLException("not yet implemented");
}
public boolean isReadOnly() throws SQLException {
return false;
} // FIXME
public void setReadOnly(boolean ro) throws SQLException {}
public DatabaseMetaData getMetaData() {
if (meta == null)
meta = new MetaData(this);
return meta;
}
public String nativeSQL(String sql) {
return sql;
}
public void clearWarnings() throws SQLException {}
public SQLWarning getWarnings() throws SQLException {
return null;
}
public boolean getAutoCommit() throws SQLException {
checkOpen();
return autoCommit;
}
public void setAutoCommit(boolean ac) throws SQLException {
checkOpen();
if (autoCommit == ac)
return;
autoCommit = ac;
db.exec(autoCommit ? "commit;" : "begin;");
}
public void commit() throws SQLException {
checkOpen();
if (autoCommit)
throw new SQLException("database in auto-commit mode");
db.exec("commit;");
db.exec("begin;");
}
public void rollback() throws SQLException {
checkOpen();
if (autoCommit)
throw new SQLException("database in auto-commit mode");
db.exec("rollback;");
db.exec("begin;");
}
public Statement createStatement() throws SQLException {
return createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,
ResultSet.CLOSE_CURSORS_AT_COMMIT);
}
public Statement createStatement(int rsType, int rsConcurr) throws SQLException {
return createStatement(rsType, rsConcurr, ResultSet.CLOSE_CURSORS_AT_COMMIT);
}
public Statement createStatement(int rst, int rsc, int rsh) throws SQLException {
checkCursor(rst, rsc, rsh);
return new Stmt(this);
}
public CallableStatement prepareCall(String sql) throws SQLException {
return prepareCall(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,
ResultSet.CLOSE_CURSORS_AT_COMMIT);
}
public CallableStatement prepareCall(String sql, int rst, int rsc) throws SQLException {
return prepareCall(sql, rst, rsc, ResultSet.CLOSE_CURSORS_AT_COMMIT);
}
public CallableStatement prepareCall(String sql, int rst, int rsc, int rsh) throws SQLException {
throw new SQLException("SQLite does not support Stored Procedures");
}
public PreparedStatement prepareStatement(String sql) throws SQLException {
return prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
}
public PreparedStatement prepareStatement(String sql, int autoC) throws SQLException {
return prepareStatement(sql);
}
public PreparedStatement prepareStatement(String sql, int[] colInds) throws SQLException {
return prepareStatement(sql);
}
public PreparedStatement prepareStatement(String sql, String[] colNames) throws SQLException {
return prepareStatement(sql);
}
public PreparedStatement prepareStatement(String sql, int rst, int rsc) throws SQLException {
return prepareStatement(sql, rst, rsc, ResultSet.CLOSE_CURSORS_AT_COMMIT);
}
public PreparedStatement prepareStatement(String sql, int rst, int rsc, int rsh) throws SQLException {
checkCursor(rst, rsc, rsh);
return new PrepStmt(this, sql);
}
/** Used to supply DatabaseMetaData.getDriverVersion(). */
String getDriverVersion() {
if (db != null) {
String dbname = db.getClass().getName();
if (dbname.indexOf("NestedDB") >= 0)
return "pure";
if (dbname.indexOf("NativeDB") >= 0)
return "native";
}
return "unloaded";
}
// UNUSED FUNCTIONS /////////////////////////////////////////////
public Savepoint setSavepoint() throws SQLException {
throw new SQLException("unsupported by SQLite: savepoints");
}
public Savepoint setSavepoint(String name) throws SQLException {
throw new SQLException("unsupported by SQLite: savepoints");
}
public void releaseSavepoint(Savepoint savepoint) throws SQLException {
throw new SQLException("unsupported by SQLite: savepoints");
}
public void rollback(Savepoint savepoint) throws SQLException {
throw new SQLException("unsupported by SQLite: savepoints");
}
public Struct createStruct(String t, Object[] attr) throws SQLException {
throw new SQLException("unsupported by SQLite");
}
}

444
libs/org/sqlite/DB.java Normal file
View File

@ -0,0 +1,444 @@
/*
* Copyright (c) 2007 David Crawshaw <david@zentus.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package org.sqlite;
import java.sql.BatchUpdateException;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/*
* This class is the interface to SQLite. It provides some helper functions
* used by other parts of the driver. The goal of the helper functions here
* are not only to provide functionality, but to handle contractual
* differences between the JDBC specification and the SQLite C API.
*
* The process of moving SQLite weirdness into this class is incomplete.
* You'll still find lots of code in Stmt and PrepStmt that are doing
* implicit contract conversions. Sorry.
*
* The two subclasses, NativeDB and NestedDB, provide the actual access to
* SQLite functions.
*/
abstract class DB implements Codes
{
/** The JDBC Connection that 'owns' this database instance. */
Conn conn = null;
/** The "begin;"and "commit;" statement handles. */
long begin = 0;
long commit = 0;
/** Tracer for statements to avoid unfinalized statements on db close. */
private final Map<Long, Stmt> stmts = new HashMap<Long, Stmt>();
// WRAPPER FUNCTIONS ////////////////////////////////////////////
abstract void interrupt() throws SQLException;
abstract void busy_timeout(int ms) throws SQLException;
abstract String errmsg() throws SQLException;
abstract String libversion() throws SQLException;
abstract int changes() throws SQLException;
abstract int shared_cache(boolean enable) throws SQLException;
abstract int enable_load_extension(boolean enable) throws SQLException;
final synchronized void exec(String sql) throws SQLException {
long pointer = 0;
try {
pointer = prepare(sql);
switch (step(pointer)) {
case SQLITE_DONE:
ensureAutoCommit();
return;
case SQLITE_ROW:
return;
default:
throwex();
}
}
finally {
finalize(pointer);
}
}
final synchronized void open(Conn conn, String file, int openFlags) throws SQLException {
this.conn = conn;
_open(file, openFlags);
}
final synchronized void close() throws SQLException {
// finalize any remaining statements before closing db
synchronized (stmts) {
Iterator i = stmts.entrySet().iterator();
while (i.hasNext()) {
Map.Entry entry = (Map.Entry) i.next();
Stmt stmt = (Stmt) entry.getValue();
finalize(((Long) entry.getKey()).longValue());
if (stmt != null) {
stmt.pointer = 0;
}
i.remove();
}
}
// remove memory used by user-defined functions
free_functions();
// clean up commit object
if (begin != 0) {
finalize(begin);
begin = 0;
}
if (commit != 0) {
finalize(commit);
commit = 0;
}
_close();
}
final synchronized void prepare(Stmt stmt) throws SQLException {
if (stmt.pointer != 0)
finalize(stmt);
stmt.pointer = prepare(stmt.sql);
stmts.put(new Long(stmt.pointer), stmt);
}
final synchronized int finalize(Stmt stmt) throws SQLException {
if (stmt.pointer == 0)
return 0;
int rc = SQLITE_ERROR;
try {
rc = finalize(stmt.pointer);
}
finally {
stmts.remove(new Long(stmt.pointer));
stmt.pointer = 0;
}
return rc;
}
protected abstract void _open(String filename, int openFlags) throws SQLException;
protected abstract void _close() throws SQLException;
protected abstract int _exec(String sql) throws SQLException;
protected abstract long prepare(String sql) throws SQLException;
protected abstract int finalize(long stmt) throws SQLException;
protected abstract int step(long stmt) throws SQLException;
protected abstract int reset(long stmt) throws SQLException;
abstract int clear_bindings(long stmt) throws SQLException; // TODO remove?
abstract int bind_parameter_count(long stmt) throws SQLException;
abstract int column_count(long stmt) throws SQLException;
abstract int column_type(long stmt, int col) throws SQLException;
abstract String column_decltype(long stmt, int col) throws SQLException;
abstract String column_table_name(long stmt, int col) throws SQLException;
abstract String column_name(long stmt, int col) throws SQLException;
abstract String column_text(long stmt, int col) throws SQLException;
abstract byte[] column_blob(long stmt, int col) throws SQLException;
abstract double column_double(long stmt, int col) throws SQLException;
abstract long column_long(long stmt, int col) throws SQLException;
abstract int column_int(long stmt, int col) throws SQLException;
abstract int bind_null(long stmt, int pos) throws SQLException;
abstract int bind_int(long stmt, int pos, int v) throws SQLException;
abstract int bind_long(long stmt, int pos, long v) throws SQLException;
abstract int bind_double(long stmt, int pos, double v) throws SQLException;
abstract int bind_text(long stmt, int pos, String v) throws SQLException;
abstract int bind_blob(long stmt, int pos, byte[] v) throws SQLException;
abstract void result_null(long context) throws SQLException;
abstract void result_text(long context, String val) throws SQLException;
abstract void result_blob(long context, byte[] val) throws SQLException;
abstract void result_double(long context, double val) throws SQLException;
abstract void result_long(long context, long val) throws SQLException;
abstract void result_int(long context, int val) throws SQLException;
abstract void result_error(long context, String err) throws SQLException;
abstract int value_bytes(Function f, int arg) throws SQLException;
abstract String value_text(Function f, int arg) throws SQLException;
abstract byte[] value_blob(Function f, int arg) throws SQLException;
abstract double value_double(Function f, int arg) throws SQLException;
abstract long value_long(Function f, int arg) throws SQLException;
abstract int value_int(Function f, int arg) throws SQLException;
abstract int value_type(Function f, int arg) throws SQLException;
abstract int create_function(String name, Function f) throws SQLException;
abstract int destroy_function(String name) throws SQLException;
abstract void free_functions() throws SQLException;
abstract int backup(String dbName, String destFileName, ProgressObserver observer) throws SQLException;
abstract int restore(String dbName, String sourceFileName, ProgressObserver observer) throws SQLException;
public static interface ProgressObserver
{
public void progress(int remaining, int pageCount);
}
/**
* Provides metadata for the columns of a statement. Returns: res[col][0] =
* true if column constrained NOT NULL res[col][1] = true if column is part
* of the primary key res[col][2] = true if column is auto-increment
*/
abstract boolean[][] column_metadata(long stmt) throws SQLException;
// COMPOUND FUNCTIONS ////////////////////////////////////////////
final synchronized String[] column_names(long stmt) throws SQLException {
String[] names = new String[column_count(stmt)];
for (int i = 0; i < names.length; i++)
names[i] = column_name(stmt, i);
return names;
}
final synchronized int sqlbind(long stmt, int pos, Object v) throws SQLException {
pos++;
if (v == null) {
return bind_null(stmt, pos);
}
else if (v instanceof Integer) {
return bind_int(stmt, pos, ((Integer) v).intValue());
}
else if (v instanceof Short) {
return bind_int(stmt, pos, ((Short) v).intValue());
}
else if (v instanceof Long) {
return bind_long(stmt, pos, ((Long) v).longValue());
}
else if (v instanceof Float) {
return bind_double(stmt, pos, ((Float) v).doubleValue());
}
else if (v instanceof Double) {
return bind_double(stmt, pos, ((Double) v).doubleValue());
}
else if (v instanceof String) {
return bind_text(stmt, pos, (String) v);
}
else if (v instanceof byte[]) {
return bind_blob(stmt, pos, (byte[]) v);
}
else {
throw new SQLException("unexpected param type: " + v.getClass());
}
}
final synchronized int[] executeBatch(long stmt, int count, Object[] vals) throws SQLException {
if (count < 1)
throw new SQLException("count (" + count + ") < 1");
final int params = bind_parameter_count(stmt);
int rc;
int[] changes = new int[count];
try {
for (int i = 0; i < count; i++) {
reset(stmt);
for (int j = 0; j < params; j++)
if (sqlbind(stmt, j, vals[(i * params) + j]) != SQLITE_OK)
throwex();
rc = step(stmt);
if (rc != SQLITE_DONE) {
reset(stmt);
if (rc == SQLITE_ROW)
throw new BatchUpdateException("batch entry " + i + ": query returns results", changes);
throwex();
}
changes[i] = changes();
}
}
finally {
ensureAutoCommit();
}
reset(stmt);
return changes;
}
final synchronized boolean execute(Stmt stmt, Object[] vals) throws SQLException {
if (vals != null) {
final int params = bind_parameter_count(stmt.pointer);
if (params != vals.length)
throw new SQLException("assertion failure: param count (" + params + ") != value count (" + vals.length
+ ")");
for (int i = 0; i < params; i++)
if (sqlbind(stmt.pointer, i, vals[i]) != SQLITE_OK)
throwex();
}
int statusCode = step(stmt.pointer);
switch (statusCode) {
case SQLITE_DONE:
reset(stmt.pointer);
ensureAutoCommit();
return false;
case SQLITE_ROW:
return true;
case SQLITE_BUSY:
case SQLITE_LOCKED:
case SQLITE_MISUSE:
throw newSQLException(statusCode);
default:
finalize(stmt);
throw newSQLException(statusCode);
}
}
final synchronized boolean execute(String sql) throws SQLException {
int statusCode = _exec(sql);
switch (statusCode) {
case SQLITE_OK:
return false;
case SQLITE_DONE:
ensureAutoCommit();
return false;
case SQLITE_ROW:
return true;
default:
throw newSQLException(statusCode);
}
}
final synchronized int executeUpdate(Stmt stmt, Object[] vals) throws SQLException {
if (execute(stmt, vals))
throw new SQLException("query returns results");
reset(stmt.pointer);
return changes();
}
final void throwex() throws SQLException {
throw new SQLException(errmsg());
}
final void throwex(int errorCode) throws SQLException {
throw newSQLException(errorCode);
}
final void throwex(int errorCode, String errorMessage) throws SQLException {
throw newSQLException(errorCode, errorMessage);
}
static SQLException newSQLException(int errorCode, String errorMessage) throws SQLException {
SQLiteErrorCode code = SQLiteErrorCode.getErrorCode(errorCode);
return new SQLException(String.format("%s (%s)", code, errorMessage));
}
private SQLException newSQLException(int errorCode) throws SQLException {
return newSQLException(errorCode, errmsg());
}
/*
* SQLite and the JDBC API have very different ideas about the meaning
* of auto-commit. Under JDBC, when executeUpdate() returns in
* auto-commit mode (the default), the programmer assumes the data has
* been written to disk. In SQLite however, a call to sqlite3_step()
* with an INSERT statement can return SQLITE_OK, and yet the data is
* still in limbo.
*
* This limbo appears when another statement on the database is active,
* e.g. a SELECT. SQLite auto-commit waits until the final read
* statement finishes, and then writes whatever updates have already
* been OKed. So if a program crashes before the reads are complete,
* data is lost. E.g:
*
* select begins
* insert
* select continues
* select finishes
*
* Works as expected, however
*
* select beings
* insert
* select continues
* crash
*
* Results in the data never being written to disk.
*
* As a solution, we call "commit" after every statement in auto-commit
* mode.
*/
final void ensureAutoCommit() throws SQLException {
if (!conn.getAutoCommit())
return;
if (begin == 0)
begin = prepare("begin;");
if (commit == 0)
commit = prepare("commit;");
try {
if (step(begin) != SQLITE_DONE)
return; // assume we are in a transaction
if (step(commit) != SQLITE_DONE) {
reset(commit);
throwex();
}
//throw new SQLException("unable to auto-commit");
}
finally {
reset(begin);
reset(commit);
}
}
}

View File

@ -0,0 +1,116 @@
//--------------------------------------
// sqlite-jdbc Project
//
// ExtendedCommand.java
// Since: Mar 12, 2010
//
// $URL$
// $Author$
//--------------------------------------
package org.sqlite;
import java.sql.SQLException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* parsing SQLite specific extension of SQL command
*
* @author leo
*
*/
public class ExtendedCommand
{
public static interface SQLExtension
{
public void execute(DB db) throws SQLException;
}
public static SQLExtension parse(String sql) throws SQLException {
if (sql == null)
return null;
if (sql.startsWith("backup"))
return BackupCommand.parse(sql);
else if (sql.startsWith("restore"))
return RestoreCommand.parse(sql);
return null;
}
public static String removeQuotation(String s) {
if (s == null)
return s;
if ((s.startsWith("\"") && s.endsWith("\"")) || (s.startsWith("'") && s.endsWith("'")))
return s.substring(1, s.length() - 1);
else
return s;
}
public static class BackupCommand implements SQLExtension
{
public final String srcDB;
public final String destFile;
public BackupCommand(String srcDB, String destFile) {
this.srcDB = srcDB;
this.destFile = destFile;
}
private static Pattern backupCmd = Pattern
.compile("backup(\\s+(\"[^\"]*\"|'[^\']*\'|\\S+))?\\s+to\\s+(\"[^\"]*\"|'[^\']*\'|\\S+)");
public static BackupCommand parse(String sql) throws SQLException {
if (sql != null) {
Matcher m = backupCmd.matcher(sql);
if (m.matches()) {
String dbName = removeQuotation(m.group(2));
String dest = removeQuotation(m.group(3));
if (dbName == null || dbName.length() == 0)
dbName = "main";
return new BackupCommand(dbName, dest);
}
}
throw new SQLException("syntax error: " + sql);
}
public void execute(DB db) throws SQLException {
db.backup(srcDB, destFile, null);
}
}
public static class RestoreCommand implements SQLExtension
{
public final String targetDB;
public final String srcFile;
private static Pattern restoreCmd = Pattern
.compile("restore(\\s+(\"[^\"]*\"|'[^\']*\'|\\S+))?\\s+from\\s+(\"[^\"]*\"|'[^\']*\'|\\S+)");
public RestoreCommand(String targetDB, String srcFile) {
this.targetDB = targetDB;
this.srcFile = srcFile;
}
public static RestoreCommand parse(String sql) throws SQLException {
if (sql != null) {
Matcher m = restoreCmd.matcher(sql);
if (m.matches()) {
String dbName = removeQuotation(m.group(2));
String dest = removeQuotation(m.group(3));
if (dbName == null || dbName.length() == 0)
dbName = "main";
return new RestoreCommand(dbName, dest);
}
}
throw new SQLException("syntax error: " + sql);
}
public void execute(DB db) throws SQLException {
db.restore(targetDB, srcFile, null);
}
}
}

View File

@ -0,0 +1,182 @@
/*
* Copyright (c) 2007 David Crawshaw <david@zentus.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package org.sqlite;
import java.sql.*;
/** Provides an interface for creating SQLite user-defined functions.
*
* <p>A subclass of <tt>org.sqlite.Function</tt> can be registered with
* <tt>Function.create()</tt> and called by the name it was given. All
* functions must implement <tt>xFunc()</tt>, which is called when SQLite
* runs the custom function.</p>
*
* Eg.
*
* <pre>
* Class.forName("org.sqlite.JDBC");
* Connection conn = DriverManager.getConnection("jdbc:sqlite:");
*
* Function.create(conn, "myFunc", new Function() {
* protected void xFunc() {
* System.out.println("myFunc called!");
* }
* });
*
* conn.createStatement().execute("select myFunc();");
* </pre>
*
* <p>Arguments passed to a custom function can be accessed using the
* <tt>protected</tt> functions provided. <tt>args()</tt> returns
* the number of arguments passed, while
* <tt>value_&lt;type&gt;(int)</tt> returns the value of the specific
* argument. Similarly a function can return a value using the
* <tt>result(&lt;type&gt;)</tt> function.</p>
*
* <p>Aggregate functions are not yet supported, but coming soon.</p>
*
*/
public abstract class Function
{
private Conn conn;
private DB db;
long context = 0; // pointer sqlite3_context*
long value = 0; // pointer sqlite3_value**
int args = 0;
/** Registers the given function with the Connection using the
* provided name. */
public static final void create(Connection conn, String name, Function f)
throws SQLException {
if (conn == null || !(conn instanceof Conn))
throw new SQLException("connection must be to an SQLite db");
if (conn.isClosed())
throw new SQLException("connection closed");
f.conn = (Conn)conn;
f.db = f.conn.db();
if (name == null || name.length() > 255)
throw new SQLException("invalid function name: '"+name+"'");
if (f.db.create_function(name, f) != Codes.SQLITE_OK)
throw new SQLException("error creating function");
}
/** Removes the named function form the Connection. */
public static final void destroy(Connection conn, String name)
throws SQLException {
if (conn == null || !(conn instanceof Conn))
throw new SQLException("connection must be to an SQLite db");
((Conn)conn).db().destroy_function(name);
}
/** Called by SQLite as a custom function. Should access arguments
* through <tt>value_*(int)</tt>, return results with
* <tt>result(*)</tt> and throw errors with <tt>error(String)</tt>. */
protected abstract void xFunc() throws SQLException;
/** Returns the number of arguments passed to the function.
* Can only be called from <tt>xFunc()</tt>. */
protected synchronized final int args()
throws SQLException { checkContext(); return args; }
/** Called by <tt>xFunc</tt> to return a value. */
protected synchronized final void result(byte[] value)
throws SQLException { checkContext(); db.result_blob(context, value); }
/** Called by <tt>xFunc</tt> to return a value. */
protected synchronized final void result(double value)
throws SQLException { checkContext(); db.result_double(context,value);}
/** Called by <tt>xFunc</tt> to return a value. */
protected synchronized final void result(int value)
throws SQLException { checkContext(); db.result_int(context, value); }
/** Called by <tt>xFunc</tt> to return a value. */
protected synchronized final void result(long value)
throws SQLException { checkContext(); db.result_long(context, value); }
/** Called by <tt>xFunc</tt> to return a value. */
protected synchronized final void result()
throws SQLException { checkContext(); db.result_null(context); }
/** Called by <tt>xFunc</tt> to return a value. */
protected synchronized final void result(String value)
throws SQLException { checkContext(); db.result_text(context, value); }
/** Called by <tt>xFunc</tt> to throw an error. */
protected synchronized final void error(String err)
throws SQLException { checkContext(); db.result_error(context, err); }
/** Called by <tt>xFunc</tt> to access the value of an argument. */
protected synchronized final int value_bytes(int arg)
throws SQLException {checkValue(arg); return db.value_bytes(this,arg);}
/** Called by <tt>xFunc</tt> to access the value of an argument. */
protected synchronized final String value_text(int arg)
throws SQLException {checkValue(arg); return db.value_text(this,arg);}
/** Called by <tt>xFunc</tt> to access the value of an argument. */
protected synchronized final byte[] value_blob(int arg)
throws SQLException {checkValue(arg); return db.value_blob(this,arg); }
/** Called by <tt>xFunc</tt> to access the value of an argument. */
protected synchronized final double value_double(int arg)
throws SQLException {checkValue(arg); return db.value_double(this,arg);}
/** Called by <tt>xFunc</tt> to access the value of an argument. */
protected synchronized final int value_int(int arg)
throws SQLException {checkValue(arg); return db.value_int(this, arg); }
/** Called by <tt>xFunc</tt> to access the value of an argument. */
protected synchronized final long value_long(int arg)
throws SQLException { checkValue(arg); return db.value_long(this,arg); }
/** Called by <tt>xFunc</tt> to access the value of an argument. */
protected synchronized final int value_type(int arg)
throws SQLException {checkValue(arg); return db.value_type(this,arg); }
private void checkContext() throws SQLException {
if (conn == null || conn.db() == null || context == 0)
throw new SQLException("no context, not allowed to read value");
}
private void checkValue(int arg) throws SQLException {
if (conn == null || conn.db() == null || value == 0)
throw new SQLException("not in value access state");
if (arg >= args)
throw new SQLException("arg "+arg+" out bounds [0,"+args+")");
}
public static abstract class Aggregate
extends Function
implements Cloneable
{
protected final void xFunc() {}
protected abstract void xStep() throws SQLException;
protected abstract void xFinal() throws SQLException;
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
}

79
libs/org/sqlite/JDBC.java Normal file
View File

@ -0,0 +1,79 @@
/*
* Copyright (c) 2007 David Crawshaw <david@zentus.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package org.sqlite;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.DriverPropertyInfo;
import java.sql.SQLException;
import java.util.Properties;
public class JDBC implements Driver
{
public static final String PREFIX = "jdbc:sqlite:";
static {
try {
DriverManager.registerDriver(new JDBC());
}
catch (SQLException e) {
e.printStackTrace();
}
}
public int getMajorVersion() {
return SQLiteJDBCLoader.getMajorVersion();
}
public int getMinorVersion() {
return SQLiteJDBCLoader.getMinorVersion();
}
public boolean jdbcCompliant() {
return false;
}
public boolean acceptsURL(String url) {
return isValidURL(url);
}
public static boolean isValidURL(String url) {
return url != null && url.toLowerCase().startsWith(PREFIX);
}
public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException {
return SQLiteConfig.getDriverPropertyInfo();
}
public Connection connect(String url, Properties info) throws SQLException {
return createConnection(url, info);
}
static String extractAddress(String url) {
// if no file name is given use a memory database
return PREFIX.equalsIgnoreCase(url) ? ":memory:" : url.substring(PREFIX.length());
}
public static Connection createConnection(String url, Properties prop) throws SQLException {
if (!isValidURL(url))
throw new SQLException("invalid database address: " + url);
url = url.trim();
return new Conn(url, extractAddress(url), prop);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,212 @@
/*
* Copyright (c) 2007 David Crawshaw <david@zentus.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package org.sqlite;
import java.sql.SQLException;
/** This class provides a thin JNI layer over the SQLite3 C API. */
final class NativeDB extends DB
{
/** SQLite connection handle. */
long pointer = 0;
private static boolean isLoaded = false;
private static boolean loadSucceeded = false;
static boolean load() {
if (isLoaded)
return loadSucceeded == true;
loadSucceeded = SQLiteJDBCLoader.initialize();
isLoaded = true;
return loadSucceeded;
}
/** linked list of all instanced UDFDatas */
private final long udfdatalist = 0;
// WRAPPER FUNCTIONS ////////////////////////////////////////////
@Override
protected native synchronized void _open(String file, int openFlags) throws SQLException;
@Override
protected native synchronized void _close() throws SQLException;
@Override
protected native synchronized int _exec(String sql) throws SQLException;
@Override
native synchronized int shared_cache(boolean enable);
@Override
native synchronized int enable_load_extension(boolean enable);
@Override
native synchronized void interrupt();
@Override
native synchronized void busy_timeout(int ms);
//native synchronized void exec(String sql) throws SQLException;
@Override
protected native synchronized long prepare(String sql) throws SQLException;
@Override
native synchronized String errmsg();
@Override
native synchronized String libversion();
@Override
native synchronized int changes();
@Override
protected native synchronized int finalize(long stmt);
@Override
protected native synchronized int step(long stmt);
@Override
protected native synchronized int reset(long stmt);
@Override
native synchronized int clear_bindings(long stmt);
@Override
native synchronized int bind_parameter_count(long stmt);
@Override
native synchronized int column_count(long stmt);
@Override
native synchronized int column_type(long stmt, int col);
@Override
native synchronized String column_decltype(long stmt, int col);
@Override
native synchronized String column_table_name(long stmt, int col);
@Override
native synchronized String column_name(long stmt, int col);
@Override
native synchronized String column_text(long stmt, int col);
@Override
native synchronized byte[] column_blob(long stmt, int col);
@Override
native synchronized double column_double(long stmt, int col);
@Override
native synchronized long column_long(long stmt, int col);
@Override
native synchronized int column_int(long stmt, int col);
@Override
native synchronized int bind_null(long stmt, int pos);
@Override
native synchronized int bind_int(long stmt, int pos, int v);
@Override
native synchronized int bind_long(long stmt, int pos, long v);
@Override
native synchronized int bind_double(long stmt, int pos, double v);
@Override
native synchronized int bind_text(long stmt, int pos, String v);
@Override
native synchronized int bind_blob(long stmt, int pos, byte[] v);
@Override
native synchronized void result_null(long context);
@Override
native synchronized void result_text(long context, String val);
@Override
native synchronized void result_blob(long context, byte[] val);
@Override
native synchronized void result_double(long context, double val);
@Override
native synchronized void result_long(long context, long val);
@Override
native synchronized void result_int(long context, int val);
@Override
native synchronized void result_error(long context, String err);
@Override
native synchronized int value_bytes(Function f, int arg);
@Override
native synchronized String value_text(Function f, int arg);
@Override
native synchronized byte[] value_blob(Function f, int arg);
@Override
native synchronized double value_double(Function f, int arg);
@Override
native synchronized long value_long(Function f, int arg);
@Override
native synchronized int value_int(Function f, int arg);
@Override
native synchronized int value_type(Function f, int arg);
@Override
native synchronized int create_function(String name, Function func);
@Override
native synchronized int destroy_function(String name);
@Override
native synchronized void free_functions();
@Override
native synchronized int backup(String dbName, String destFileName, ProgressObserver observer) throws SQLException;
@Override
native synchronized int restore(String dbName, String sourceFileName, ProgressObserver observer)
throws SQLException;
// COMPOUND FUNCTIONS (for optimisation) /////////////////////////
/**
* Provides metadata for the columns of a statement. Returns: res[col][0] =
* true if column constrained NOT NULL res[col][1] = true if column is part
* of the primary key res[col][2] = true if column is auto-increment
*/
@Override
native synchronized boolean[][] column_metadata(long stmt);
static void throwex(String msg) throws SQLException {
throw new SQLException(msg);
}
}

View File

@ -0,0 +1,662 @@
/*
* Copyright (c) 2007 David Crawshaw <david@zentus.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package org.sqlite;
import java.io.PrintWriter;
import java.sql.SQLException;
import org.ibex.nestedvm.Runtime;
// FEATURE: strdup is wasteful, SQLite interface will take unterminated char*
/** Communicates with the Java version of SQLite provided by NestedVM. */
final class NestedDB extends DB implements Runtime.CallJavaCB
{
/** database pointer */
int handle = 0;
/** sqlite binary embedded in nestedvm */
private Runtime rt = null;
/** user defined functions referenced by position (stored in used data) */
private Function[] functions = null;
private String[] funcNames = null;
// WRAPPER FUNCTIONS ////////////////////////////////////////////
@Override
protected synchronized void _open(String filename, int openFlags) throws SQLException {
if (handle != 0)
throw new SQLException("DB already open");
// handle silly windows drive letter mapping
if (filename.length() > 2) {
char drive = Character.toLowerCase(filename.charAt(0));
if (filename.charAt(1) == ':' && drive >= 'a' && drive <= 'z') {
// convert to nestedvm's "/c:/file" format
filename = filename.substring(2);
filename = filename.replace('\\', '/');
filename = "/" + drive + ":" + filename;
}
}
// start the nestedvm runtime
try {
rt = (Runtime) Class.forName("org.sqlite.SQLite").newInstance();
rt.start();
}
catch (Exception e) {
throw new CausedSQLException(e);
}
// callback for user defined functions
rt.setCallJavaCB(this);
// open the db and retrieve sqlite3_db* pointer
int passback = rt.xmalloc(4);
int str = rt.strdup(filename);
// if (call("sqlite3_open_v2", str, openFlags, 0, passback) != SQLITE_OK)
if (call("sqlite3_open_v2", str, passback, openFlags, 0) != SQLITE_OK)
throwex();
handle = deref(passback);
rt.free(str);
rt.free(passback);
}
/* callback for Runtime.CallJavaCB above */
public int call(int xType, int context, int args, int value) {
xUDF(xType, context, args, value);
return 0;
}
@Override
protected synchronized void _close() throws SQLException {
if (handle == 0)
return;
try {
if (call("sqlite3_close", handle) != SQLITE_OK)
throwex();
}
finally {
handle = 0;
rt.stop();
rt = null;
}
}
@Override
int shared_cache(boolean enable) throws SQLException {
// The shared cache is per-process, so it is useless as
// each nested connection is its own process.
return -1;
}
@Override
int enable_load_extension(boolean enable) throws SQLException {
// TODO enable_load_extension is not supported in pure-java mode
//return call("sqlite3_enable_load_extension", handle, enable ? 1 : 0);
return 1;
}
@Override
synchronized void interrupt() throws SQLException {
call("sqlite3_interrupt", handle);
}
@Override
synchronized void busy_timeout(int ms) throws SQLException {
call("sqlite3_busy_timeout", handle, ms);
}
@Override
protected synchronized long prepare(String sql) throws SQLException {
int passback = rt.xmalloc(4);
int str = rt.strdup(sql);
int ret = call("sqlite3_prepare_v2", handle, str, -1, passback, 0);
rt.free(str);
if (ret != SQLITE_OK) {
rt.free(passback);
throwex(ret);
}
int pointer = deref(passback);
rt.free(passback);
return pointer;
}
@Override
synchronized String errmsg() throws SQLException {
return cstring(call("sqlite3_errmsg", handle));
}
@Override
synchronized String libversion() throws SQLException {
return cstring(call("sqlite3_libversion", handle));
}
@Override
synchronized int changes() throws SQLException {
return call("sqlite3_changes", handle);
}
@Override
protected synchronized int _exec(String sql) throws SQLException {
if (rt == null)
throw DB.newSQLException(SQLiteErrorCode.SQLITE_MISUSE.code, "attempt to use the closed conection");
int passback = rt.xmalloc(4);
int str = rt.strdup(sql);
int status = call("sqlite3_exec", handle, str, 0, 0, passback);
if (status != SQLITE_OK) {
String errorMessage = cstring(passback);
call("sqlite3_free", deref(passback));
rt.free(passback);
throwex(status, errorMessage);
}
rt.free(passback);
return status;
}
@Override
protected synchronized int finalize(long stmt) throws SQLException {
return call("sqlite3_finalize", (int) stmt);
}
@Override
protected synchronized int step(long stmt) throws SQLException {
return call("sqlite3_step", (int) stmt);
}
@Override
protected synchronized int reset(long stmt) throws SQLException {
return call("sqlite3_reset", (int) stmt);
}
@Override
synchronized int clear_bindings(long stmt) throws SQLException {
return call("sqlite3_clear_bindings", (int) stmt);
}
@Override
synchronized int bind_parameter_count(long stmt) throws SQLException {
return call("sqlite3_bind_parameter_count", (int) stmt);
}
@Override
synchronized int column_count(long stmt) throws SQLException {
return call("sqlite3_column_count", (int) stmt);
}
@Override
synchronized int column_type(long stmt, int col) throws SQLException {
return call("sqlite3_column_type", (int) stmt, col);
}
@Override
synchronized String column_name(long stmt, int col) throws SQLException {
return utfstring(call("sqlite3_column_name", (int) stmt, col));
}
@Override
synchronized String column_text(long stmt, int col) throws SQLException {
return utfstring(call("sqlite3_column_text", (int) stmt, col));
}
@Override
synchronized byte[] column_blob(long stmt, int col) throws SQLException {
int addr = call("sqlite3_column_blob", (int) stmt, col);
if (addr == 0)
return null;
byte[] blob = new byte[call("sqlite3_column_bytes", (int) stmt, col)];
copyin(addr, blob, blob.length);
return blob;
}
@Override
synchronized double column_double(long stmt, int col) throws SQLException {
try {
return Double.parseDouble(column_text(stmt, col));
}
catch (NumberFormatException e) {
return Double.NaN;
} // TODO
}
@Override
synchronized long column_long(long stmt, int col) throws SQLException {
try {
return Long.parseLong(column_text(stmt, col));
}
catch (NumberFormatException e) {
return 0;
} // TODO
}
@Override
synchronized int column_int(long stmt, int col) throws SQLException {
return call("sqlite3_column_int", (int) stmt, col);
}
@Override
synchronized String column_decltype(long stmt, int col) throws SQLException {
return utfstring(call("sqlite3_column_decltype", (int) stmt, col));
}
@Override
synchronized String column_table_name(long stmt, int col) throws SQLException {
return utfstring(call("sqlite3_column_table_name", (int) stmt, col));
}
@Override
synchronized int bind_null(long stmt, int pos) throws SQLException {
return call("sqlite3_bind_null", (int) stmt, pos);
}
@Override
synchronized int bind_int(long stmt, int pos, int v) throws SQLException {
return call("sqlite3_bind_int", (int) stmt, pos, v);
}
@Override
synchronized int bind_long(long stmt, int pos, long v) throws SQLException {
return bind_text(stmt, pos, Long.toString(v)); // TODO
}
@Override
synchronized int bind_double(long stmt, int pos, double v) throws SQLException {
return bind_text(stmt, pos, Double.toString(v)); // TODO
}
@Override
synchronized int bind_text(long stmt, int pos, String v) throws SQLException {
if (v == null)
return bind_null(stmt, pos);
return call("sqlite3_bind_text", (int) stmt, pos, rt.strdup(v), -1, rt.lookupSymbol("free"));
}
@Override
synchronized int bind_blob(long stmt, int pos, byte[] buf) throws SQLException {
if (buf == null || buf.length < 1)
return bind_null(stmt, pos);
int len = buf.length;
int blob = rt.xmalloc(len); // free()ed by sqlite3_bind_blob
copyout(buf, blob, len);
return call("sqlite3_bind_blob", (int) stmt, pos, blob, len, rt.lookupSymbol("free"));
}
@Override
synchronized void result_null(long cxt) throws SQLException {
call("sqlite3_result_null", (int) cxt);
}
@Override
synchronized void result_text(long cxt, String val) throws SQLException {
call("sqlite3_result_text", (int) cxt, rt.strdup(val), -1, rt.lookupSymbol("free"));
}
@Override
synchronized void result_blob(long cxt, byte[] val) throws SQLException {
if (val == null || val.length == 0) {
result_null(cxt);
return;
}
int blob = rt.xmalloc(val.length);
copyout(val, blob, val.length);
call("sqlite3_result_blob", (int) cxt, blob, val.length, rt.lookupSymbol("free"));
}
@Override
synchronized void result_double(long cxt, double val) throws SQLException {
result_text(cxt, Double.toString(val));
} // TODO
@Override
synchronized void result_long(long cxt, long val) throws SQLException {
result_text(cxt, Long.toString(val));
} // TODO
@Override
synchronized void result_int(long cxt, int val) throws SQLException {
call("sqlite3_result_int", (int) cxt, val);
}
@Override
synchronized void result_error(long cxt, String err) throws SQLException {
int str = rt.strdup(err);
call("sqlite3_result_error", (int) cxt, str, -1);
rt.free(str);
}
@Override
synchronized int value_bytes(Function f, int arg) throws SQLException {
return call("sqlite3_value_bytes", value(f, arg));
}
@Override
synchronized String value_text(Function f, int arg) throws SQLException {
return utfstring(call("sqlite3_value_text", value(f, arg)));
}
@Override
synchronized byte[] value_blob(Function f, int arg) throws SQLException {
int addr = call("sqlite3_value_blob", value(f, arg));
if (addr == 0)
return null;
byte[] blob = new byte[value_bytes(f, arg)];
copyin(addr, blob, blob.length);
return blob;
}
@Override
synchronized double value_double(Function f, int arg) throws SQLException {
return Double.parseDouble(value_text(f, arg)); // TODO
}
@Override
synchronized long value_long(Function f, int arg) throws SQLException {
return Long.parseLong(value_text(f, arg)); // TODO
}
@Override
synchronized int value_int(Function f, int arg) throws SQLException {
return call("sqlite3_value_int", value(f, arg));
}
@Override
synchronized int value_type(Function f, int arg) throws SQLException {
return call("sqlite3_value_type", value(f, arg));
}
private int value(Function f, int arg) throws SQLException {
return deref((int) f.value + (arg * 4));
}
@Override
synchronized int create_function(String name, Function func) throws SQLException {
if (functions == null) {
functions = new Function[10];
funcNames = new String[10];
}
// find a position
int pos;
for (pos = 0; pos < functions.length; pos++)
if (functions[pos] == null)
break;
if (pos == functions.length) { // expand function arrays
Function[] fnew = new Function[functions.length * 2];
String[] nnew = new String[funcNames.length * 2];
System.arraycopy(functions, 0, fnew, 0, functions.length);
System.arraycopy(funcNames, 0, nnew, 0, funcNames.length);
functions = fnew;
funcNames = nnew;
}
// register function
functions[pos] = func;
funcNames[pos] = name;
int rc;
int str = rt.strdup(name);
rc = call("create_function_helper", handle, str, pos, func instanceof Function.Aggregate ? 1 : 0);
rt.free(str);
return rc;
}
@Override
synchronized int destroy_function(String name) throws SQLException {
if (name == null)
return 0;
// find function position number
int pos;
for (pos = 0; pos < funcNames.length; pos++)
if (name.equals(funcNames[pos]))
break;
if (pos == funcNames.length)
return 0;
functions[pos] = null;
funcNames[pos] = null;
// deregister function
int rc;
int str = rt.strdup(name);
rc = call("create_function_helper", handle, str, -1, 0);
rt.free(str);
return rc;
}
/* unused as we use the user_data pointer to store a single word */
@Override
synchronized void free_functions() {}
/** Callback used by xFunc (1), xStep (2) and xFinal (3). */
synchronized void xUDF(int xType, int context, int args, int value) {
Function func = null;
try {
int pos = call("sqlite3_user_data", context);
func = functions[pos];
if (func == null)
throw new SQLException("function state inconsistent");
func.context = context;
func.value = value;
func.args = args;
switch (xType) {
case 1:
func.xFunc();
break;
case 2:
((Function.Aggregate) func).xStep();
break;
case 3:
((Function.Aggregate) func).xFinal();
break;
}
}
catch (SQLException e) {
try {
String err = e.toString();
if (err == null)
err = "unknown error";
int str = rt.strdup(err);
call("sqlite3_result_error", context, str, -1);
rt.free(str);
}
catch (SQLException exp) {
exp.printStackTrace();//TODO
}
}
finally {
if (func != null) {
func.context = 0;
func.value = 0;
func.args = 0;
}
}
}
/** Calls support function found in upstream/sqlite-metadata.patch */
@Override
synchronized boolean[][] column_metadata(long stmt) throws SQLException {
int colCount = call("sqlite3_column_count", (int) stmt);
boolean[][] meta = new boolean[colCount][3];
int pass;
pass = rt.xmalloc(12); // struct metadata
for (int i = 0; i < colCount; i++) {
call("column_metadata_helper", handle, (int) stmt, i, pass);
meta[i][0] = deref(pass) == 1;
meta[i][1] = deref(pass + 4) == 1;
meta[i][2] = deref(pass + 8) == 1;
}
rt.free(pass);
return meta;
}
@Override
int backup(String dbName, String destFileName, ProgressObserver observer) throws SQLException {
throw new SQLException("backup command is not supported in pure-java mode");
}
@Override
int restore(String dbName, String sourceFileName, ProgressObserver observer) throws SQLException {
throw new SQLException("restore command is not supported in pure-java mode");
}
// HELPER FUNCTIONS /////////////////////////////////////////////
/** safe to reuse parameter arrays as all functions are syncrhonized */
private final int[] p0 = new int[] {}, p1 = new int[] { 0 }, p2 = new int[] { 0, 0 }, p3 = new int[] { 0, 0, 0 },
p4 = new int[] { 0, 0, 0, 0 }, p5 = new int[] { 0, 0, 0, 0, 0 };
private int call(String addr, int a0) throws SQLException {
p1[0] = a0;
return call(addr, p1);
}
private int call(String addr, int a0, int a1) throws SQLException {
p2[0] = a0;
p2[1] = a1;
return call(addr, p2);
}
private int call(String addr, int a0, int a1, int a2) throws SQLException {
p3[0] = a0;
p3[1] = a1;
p3[2] = a2;
return call(addr, p3);
}
private int call(String addr, int a0, int a1, int a2, int a3) throws SQLException {
p4[0] = a0;
p4[1] = a1;
p4[2] = a2;
p4[3] = a3;
return call(addr, p4);
}
private int call(String addr, int a0, int a1, int a2, int a3, int a4) throws SQLException {
p5[0] = a0;
p5[1] = a1;
p5[2] = a2;
p5[3] = a3;
p5[4] = a4;
return call(addr, p5);
}
private int call(String func, int[] args) throws SQLException {
try {
return rt.call(func, args);
}
catch (Runtime.CallException e) {
throw new CausedSQLException(e);
}
}
/** Dereferences a pointer, returning the word it points to. */
private int deref(int pointer) throws SQLException {
try {
return rt.memRead(pointer);
}
catch (Runtime.ReadFaultException e) {
throw new CausedSQLException(e);
}
}
private String utfstring(int str) throws SQLException {
try {
return rt.utfstring(str);
}
catch (Runtime.ReadFaultException e) {
throw new CausedSQLException(e);
}
}
private String cstring(int str) throws SQLException {
try {
return rt.cstring(str);
}
catch (Runtime.ReadFaultException e) {
throw new CausedSQLException(e);
}
}
private void copyin(int addr, byte[] buf, int count) throws SQLException {
try {
rt.copyin(addr, buf, count);
}
catch (Runtime.ReadFaultException e) {
throw new CausedSQLException(e);
}
}
private void copyout(byte[] buf, int addr, int count) throws SQLException {
try {
rt.copyout(buf, addr, count);
}
catch (Runtime.FaultException e) {
throw new CausedSQLException(e);
}
}
/** Maps any exception onto an SQLException. */
private static final class CausedSQLException extends SQLException
{
private final Exception cause;
CausedSQLException(Exception e) {
if (e == null)
throw new RuntimeException("null exception cause");
cause = e;
}
@Override
public Throwable getCause() {
return cause;
}
@Override
public void printStackTrace() {
cause.printStackTrace();
}
@Override
public void printStackTrace(PrintWriter s) {
cause.printStackTrace(s);
}
@Override
public Throwable fillInStackTrace() {
return cause.fillInStackTrace();
}
@Override
public StackTraceElement[] getStackTrace() {
return cause.getStackTrace();
}
@Override
public String getMessage() {
return cause.getMessage();
}
}
}

View File

@ -0,0 +1,80 @@
/*--------------------------------------------------------------------------
* Copyright 2008 Taro L. Saito
*
* 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.
*--------------------------------------------------------------------------*/
//--------------------------------------
// sqlite-jdbc Project
//
// OSInfo.java
// Since: May 20, 2008
//
// $URL$
// $Author$
//--------------------------------------
package org.sqlite;
/**
* Provides OS name and architecture name.
*
* @author leo
*
*/
public class OSInfo
{
public static void main(String[] args) {
if (args.length >= 1) {
if ("--os".equals(args[0])) {
System.out.print(getOSName());
return;
}
else if ("--arch".equals(args[0])) {
System.out.print(getArchName());
return;
}
}
System.out.print(getNativeLibFolderPathForCurrentOS());
}
public static String getNativeLibFolderPathForCurrentOS() {
return getOSName() + "/" + getArchName();
}
public static String getOSName() {
return translateOSNameToFolderName(System.getProperty("os.name"));
}
public static String getArchName() {
return translateArchNameToFolderName(System.getProperty("os.arch"));
}
public static String translateOSNameToFolderName(String osName) {
if (osName.contains("Windows")) {
return "Windows";
}
else if (osName.contains("Mac")) {
return "Mac";
}
else if (osName.contains("Linux")) {
return "Linux";
}
else {
return osName.replaceAll("\\W", "");
}
}
public static String translateArchNameToFolderName(String archName) {
return archName.replaceAll("\\W", "");
}
}

View File

@ -0,0 +1,330 @@
/*
* Copyright (c) 2007 David Crawshaw <david@zentus.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package org.sqlite;
import java.io.IOException;
import java.io.Reader;
import java.sql.Date;
import java.sql.ParameterMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Time;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.Calendar;
final class PrepStmt extends Stmt implements PreparedStatement, ParameterMetaData, Codes
{
private int columnCount;
private int paramCount;
PrepStmt(Conn conn, String sql) throws SQLException {
super(conn);
this.sql = sql;
db.prepare(this);
rs.colsMeta = db.column_names(pointer);
columnCount = db.column_count(pointer);
paramCount = db.bind_parameter_count(pointer);
batch = new Object[paramCount];
batchPos = 0;
}
public void clearParameters() throws SQLException {
checkOpen();
db.reset(pointer);
clearBatch();
}
@Override
protected void finalize() throws SQLException {
close();
}
public boolean execute() throws SQLException {
checkOpen();
rs.close();
db.reset(pointer);
resultsWaiting = db.execute(this, batch);
return columnCount != 0;
}
public ResultSet executeQuery() throws SQLException {
checkOpen();
if (columnCount == 0)
throw new SQLException("query does not return results");
rs.close();
db.reset(pointer);
resultsWaiting = db.execute(this, batch);
return getResultSet();
}
public int executeUpdate() throws SQLException {
checkOpen();
if (columnCount != 0)
throw new SQLException("query returns results");
rs.close();
db.reset(pointer);
return db.executeUpdate(this, batch);
}
@Override
public int[] executeBatch() throws SQLException {
if (batchPos == 0)
return new int[] {};
try {
return db.executeBatch(pointer, batchPos / paramCount, batch);
}
finally {
clearBatch();
}
}
@Override
public int getUpdateCount() throws SQLException {
checkOpen();
if (pointer == 0 || resultsWaiting)
return -1;
return db.changes();
}
public void addBatch() throws SQLException {
checkOpen();
batchPos += paramCount;
if (batchPos + paramCount > batch.length) {
Object[] nb = new Object[batch.length * 2];
System.arraycopy(batch, 0, nb, 0, batch.length);
batch = nb;
}
System.arraycopy(batch, batchPos - paramCount, batch, batchPos, paramCount);
}
// ParameterMetaData FUNCTIONS //////////////////////////////////
public ParameterMetaData getParameterMetaData() {
return this;
}
public int getParameterCount() throws SQLException {
checkOpen();
return paramCount;
}
public String getParameterClassName(int param) throws SQLException {
checkOpen();
return "java.lang.String";
}
public String getParameterTypeName(int pos) {
return "VARCHAR";
}
public int getParameterType(int pos) {
return Types.VARCHAR;
}
public int getParameterMode(int pos) {
return parameterModeIn;
}
public int getPrecision(int pos) {
return 0;
}
public int getScale(int pos) {
return 0;
}
public int isNullable(int pos) {
return parameterNullable;
}
public boolean isSigned(int pos) {
return true;
}
public Statement getStatement() {
return this;
}
// PARAMETER FUNCTIONS //////////////////////////////////////////
private void batch(int pos, Object value) throws SQLException {
checkOpen();
if (batch == null)
batch = new Object[paramCount];
batch[batchPos + pos - 1] = value;
}
public void setBoolean(int pos, boolean value) throws SQLException {
setInt(pos, value ? 1 : 0);
}
public void setByte(int pos, byte value) throws SQLException {
setInt(pos, value);
}
public void setBytes(int pos, byte[] value) throws SQLException {
batch(pos, value);
}
public void setDouble(int pos, double value) throws SQLException {
batch(pos, new Double(value));
}
public void setFloat(int pos, float value) throws SQLException {
batch(pos, new Float(value));
}
public void setInt(int pos, int value) throws SQLException {
batch(pos, new Integer(value));
}
public void setLong(int pos, long value) throws SQLException {
batch(pos, new Long(value));
}
public void setNull(int pos, int u1) throws SQLException {
setNull(pos, u1, null);
}
public void setNull(int pos, int u1, String u2) throws SQLException {
batch(pos, null);
}
public void setObject(int pos, Object value) throws SQLException {
if (value == null)
batch(pos, null);
else if (value instanceof java.util.Date)
batch(pos, new Long(((java.util.Date) value).getTime()));
else if (value instanceof Date)
batch(pos, new Long(((Date) value).getTime()));
else if (value instanceof Time)
batch(pos, new Long(((Time) value).getTime()));
else if (value instanceof Timestamp)
batch(pos, new Long(((Timestamp) value).getTime()));
else if (value instanceof Long)
batch(pos, value);
else if (value instanceof Integer)
batch(pos, value);
else if (value instanceof Short)
batch(pos, new Integer(((Short) value).intValue()));
else if (value instanceof Float)
batch(pos, value);
else if (value instanceof Double)
batch(pos, value);
else if (value instanceof Boolean)
setBoolean(pos, ((Boolean) value).booleanValue());
else if (value instanceof byte[])
batch(pos, value);
else
batch(pos, value.toString());
}
public void setObject(int p, Object v, int t) throws SQLException {
setObject(p, v);
}
public void setObject(int p, Object v, int t, int s) throws SQLException {
setObject(p, v);
}
public void setShort(int pos, short value) throws SQLException {
setInt(pos, value);
}
public void setString(int pos, String value) throws SQLException {
batch(pos, value);
}
public void setCharacterStream(int pos, Reader reader, int length) throws SQLException {
try {
// copy chars from reader to StringBuffer
StringBuffer sb = new StringBuffer();
char[] cbuf = new char[8192];
int cnt;
while ((cnt = reader.read(cbuf)) > 0) {
sb.append(cbuf, 0, cnt);
}
// set as string
setString(pos, sb.toString());
}
catch (IOException e) {
throw new SQLException("Cannot read from character stream, exception message: " + e.getMessage());
}
}
public void setDate(int pos, Date x) throws SQLException {
setObject(pos, x);
}
public void setDate(int pos, Date x, Calendar cal) throws SQLException {
setObject(pos, x);
}
public void setTime(int pos, Time x) throws SQLException {
setObject(pos, x);
}
public void setTime(int pos, Time x, Calendar cal) throws SQLException {
setObject(pos, x);
}
public void setTimestamp(int pos, Timestamp x) throws SQLException {
setObject(pos, x);
}
public void setTimestamp(int pos, Timestamp x, Calendar cal) throws SQLException {
setObject(pos, x);
}
public ResultSetMetaData getMetaData() throws SQLException {
checkOpen();
return rs;
}
// UNUSED ///////////////////////////////////////////////////////
@Override
public boolean execute(String sql) throws SQLException {
throw unused();
}
@Override
public int executeUpdate(String sql) throws SQLException {
throw unused();
}
@Override
public ResultSet executeQuery(String sql) throws SQLException {
throw unused();
}
@Override
public void addBatch(String sql) throws SQLException {
throw unused();
}
private SQLException unused() {
return new SQLException("not supported by PreparedStatment");
}
}

540
libs/org/sqlite/RS.java Normal file
View File

@ -0,0 +1,540 @@
/*
* Copyright (c) 2007 David Crawshaw <david@zentus.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package org.sqlite;
import java.io.Reader;
import java.io.StringReader;
import java.sql.Date;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.Statement;
import java.sql.Time;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.Calendar;
/**
* Implements a JDBC ResultSet.
*/
final class RS extends Unused implements ResultSet, ResultSetMetaData, Codes
{
private final Stmt stmt;
private final DB db;
boolean open = false; // true means have results and can iterate them
int maxRows; // max. number of rows as set by a Statement
String[] cols = null; // if null, the RS is closed()
String[] colsMeta = null; // same as cols, but used by Meta interface
boolean[][] meta = null;
private int limitRows; // 0 means no limit, must check against maxRows
private int row = 0; // number of current row, starts at 1 (0 is for before loading data)
private int lastCol; // last column accessed, for wasNull(). -1 if none
RS(Stmt stmt) {
this.stmt = stmt;
this.db = stmt.db;
}
// INTERNAL FUNCTIONS ///////////////////////////////////////////
boolean isOpen() {
return open;
}
/* Throws SQLException if ResultSet is not open. */
void checkOpen() throws SQLException {
if (!open)
throw new SQLException("ResultSet closed");
}
// takes col in [1,x] form, returns in [0,x-1] form
private int checkCol(int col) throws SQLException {
if (colsMeta == null)
throw new IllegalStateException("SQLite JDBC: inconsistent internal state");
if (col < 1 || col > colsMeta.length)
throw new SQLException("column " + col + " out of bounds [1," + colsMeta.length + "]");
return --col;
}
// takes col in [1,x] form, marks it as last accessed and returns [0,x-1]
private int markCol(int col) throws SQLException {
checkOpen();
checkCol(col);
lastCol = col;
return --col;
}
private void checkMeta() throws SQLException {
checkCol(1);
if (meta == null)
meta = db.column_metadata(stmt.pointer);
}
// ResultSet Functions //////////////////////////////////////////
public void close() throws SQLException {
cols = null;
colsMeta = null;
meta = null;
open = false;
limitRows = 0;
row = 0;
lastCol = -1;
if (stmt == null)
return;
if (stmt != null && stmt.pointer != 0)
db.reset(stmt.pointer);
}
// returns col in [1,x] form
public int findColumn(String col) throws SQLException {
checkOpen();
int c = -1;
for (int i = 0; i < cols.length; i++) {
if (col.equalsIgnoreCase(cols[i])
|| (cols[i].toUpperCase().endsWith(col.toUpperCase()) && cols[i].charAt(cols[i].length()
- col.length()) == '.')) {
if (c == -1)
c = i;
else
throw new SQLException("ambiguous column: '" + col + "'");
}
}
if (c == -1)
throw new SQLException("no such column: '" + col + "'");
else
return c + 1;
}
public boolean next() throws SQLException {
if (!open)
return false; // finished ResultSet
lastCol = -1;
// first row is loaded by execute(), so do not step() again
if (row == 0) {
row++;
return true;
}
// check if we are row limited by the statement or the ResultSet
if (maxRows != 0 && row > maxRows)
return false;
// do the real work
int statusCode = db.step(stmt.pointer);
switch (statusCode) {
case SQLITE_DONE:
close(); // agressive closing to avoid writer starvation
return false;
case SQLITE_ROW:
row++;
return true;
case SQLITE_BUSY:
default:
db.throwex(statusCode);
return false;
}
}
public int getType() throws SQLException {
return TYPE_FORWARD_ONLY;
}
public int getFetchSize() throws SQLException {
return limitRows;
}
public void setFetchSize(int rows) throws SQLException {
if (0 > rows || (maxRows != 0 && rows > maxRows))
throw new SQLException("fetch size " + rows + " out of bounds " + maxRows);
limitRows = rows;
}
public int getFetchDirection() throws SQLException {
checkOpen();
return ResultSet.FETCH_FORWARD;
}
public void setFetchDirection(int d) throws SQLException {
checkOpen();
if (d != ResultSet.FETCH_FORWARD)
throw new SQLException("only FETCH_FORWARD direction supported");
}
public boolean isAfterLast() throws SQLException {
return !open;
}
public boolean isBeforeFirst() throws SQLException {
return open && row == 0;
}
public boolean isFirst() throws SQLException {
return row == 1;
}
public boolean isLast() throws SQLException { // FIXME
throw new SQLException("function not yet implemented for SQLite");
}
@Override
protected void finalize() throws SQLException {
close();
}
public int getRow() throws SQLException {
return row;
}
public boolean wasNull() throws SQLException {
return db.column_type(stmt.pointer, markCol(lastCol)) == SQLITE_NULL;
}
// DATA ACCESS FUNCTIONS ////////////////////////////////////////
public boolean getBoolean(int col) throws SQLException {
return getInt(col) == 0 ? false : true;
}
public boolean getBoolean(String col) throws SQLException {
return getBoolean(findColumn(col));
}
public byte getByte(int col) throws SQLException {
return (byte) getInt(col);
}
public byte getByte(String col) throws SQLException {
return getByte(findColumn(col));
}
public byte[] getBytes(int col) throws SQLException {
return db.column_blob(stmt.pointer, markCol(col));
}
public byte[] getBytes(String col) throws SQLException {
return getBytes(findColumn(col));
}
public Reader getCharacterStream(int col) throws SQLException {
return new StringReader(getString(col));
}
public Reader getCharacterStream(String col) throws SQLException {
return getCharacterStream(findColumn(col));
}
public Date getDate(int col) throws SQLException {
if (db.column_type(stmt.pointer, markCol(col)) == SQLITE_NULL)
return null;
return new Date(db.column_long(stmt.pointer, markCol(col)));
}
public Date getDate(int col, Calendar cal) throws SQLException {
if (db.column_type(stmt.pointer, markCol(col)) == SQLITE_NULL)
return null;
if (cal == null)
return getDate(col);
cal.setTimeInMillis(db.column_long(stmt.pointer, markCol(col)));
return new Date(cal.getTime().getTime());
}
public Date getDate(String col) throws SQLException {
return getDate(findColumn(col), Calendar.getInstance());
}
public Date getDate(String col, Calendar cal) throws SQLException {
return getDate(findColumn(col), cal);
}
public double getDouble(int col) throws SQLException {
if (db.column_type(stmt.pointer, markCol(col)) == SQLITE_NULL)
return 0;
return db.column_double(stmt.pointer, markCol(col));
}
public double getDouble(String col) throws SQLException {
return getDouble(findColumn(col));
}
public float getFloat(int col) throws SQLException {
if (db.column_type(stmt.pointer, markCol(col)) == SQLITE_NULL)
return 0;
return (float) db.column_double(stmt.pointer, markCol(col));
}
public float getFloat(String col) throws SQLException {
return getFloat(findColumn(col));
}
public int getInt(int col) throws SQLException {
return db.column_int(stmt.pointer, markCol(col));
}
public int getInt(String col) throws SQLException {
return getInt(findColumn(col));
}
public long getLong(int col) throws SQLException {
return db.column_long(stmt.pointer, markCol(col));
}
public long getLong(String col) throws SQLException {
return getLong(findColumn(col));
}
public short getShort(int col) throws SQLException {
return (short) getInt(col);
}
public short getShort(String col) throws SQLException {
return getShort(findColumn(col));
}
public String getString(int col) throws SQLException {
return db.column_text(stmt.pointer, markCol(col));
}
public String getString(String col) throws SQLException {
return getString(findColumn(col));
}
public Time getTime(int col) throws SQLException {
if (db.column_type(stmt.pointer, markCol(col)) == SQLITE_NULL)
return null;
return new Time(db.column_long(stmt.pointer, markCol(col)));
}
public Time getTime(int col, Calendar cal) throws SQLException {
if (cal == null)
return getTime(col);
if (db.column_type(stmt.pointer, markCol(col)) == SQLITE_NULL)
return null;
cal.setTimeInMillis(db.column_long(stmt.pointer, markCol(col)));
return new Time(cal.getTime().getTime());
}
public Time getTime(String col) throws SQLException {
return getTime(findColumn(col));
}
public Time getTime(String col, Calendar cal) throws SQLException {
return getTime(findColumn(col), cal);
}
public Timestamp getTimestamp(int col) throws SQLException {
if (db.column_type(stmt.pointer, markCol(col)) == SQLITE_NULL)
return null;
return new Timestamp(db.column_long(stmt.pointer, markCol(col)));
}
public Timestamp getTimestamp(int col, Calendar cal) throws SQLException {
if (cal == null)
return getTimestamp(col);
if (db.column_type(stmt.pointer, markCol(col)) == SQLITE_NULL)
return null;
cal.setTimeInMillis(db.column_long(stmt.pointer, markCol(col)));
return new Timestamp(cal.getTime().getTime());
}
public Timestamp getTimestamp(String col) throws SQLException {
return getTimestamp(findColumn(col));
}
public Timestamp getTimestamp(String c, Calendar ca) throws SQLException {
return getTimestamp(findColumn(c), ca);
}
public Object getObject(int col) throws SQLException {
switch (db.column_type(stmt.pointer, checkCol(col))) {
case SQLITE_INTEGER:
long val = getLong(col);
if (val > Integer.MAX_VALUE || val < Integer.MIN_VALUE)
return new Long(val);
else
return new Integer((int) val);
case SQLITE_FLOAT:
return new Double(getDouble(col));
case SQLITE_BLOB:
return getBytes(col);
case SQLITE_NULL:
return null;
case SQLITE_TEXT:
default:
return getString(col);
}
}
public Object getObject(String col) throws SQLException {
return getObject(findColumn(col));
}
public Statement getStatement() {
return stmt;
}
public String getCursorName() throws SQLException {
return null;
}
public SQLWarning getWarnings() throws SQLException {
return null;
}
public void clearWarnings() throws SQLException {}
// ResultSetMetaData Functions //////////////////////////////////
// we do not need to check the RS is open, only that colsMeta
// is not null, done with checkCol(int).
public ResultSetMetaData getMetaData() throws SQLException {
return this;
}
public String getCatalogName(int col) throws SQLException {
return db.column_table_name(stmt.pointer, checkCol(col));
}
public String getColumnClassName(int col) throws SQLException {
checkCol(col);
return "java.lang.Object";
}
public int getColumnCount() throws SQLException {
checkCol(1);
return colsMeta.length;
}
public int getColumnDisplaySize(int col) throws SQLException {
return Integer.MAX_VALUE;
}
public String getColumnLabel(int col) throws SQLException {
return getColumnName(col);
}
public String getColumnName(int col) throws SQLException {
return db.column_name(stmt.pointer, checkCol(col));
}
public int getColumnType(int col) throws SQLException {
switch (db.column_type(stmt.pointer, checkCol(col))) {
case SQLITE_INTEGER:
return Types.INTEGER;
case SQLITE_FLOAT:
return Types.FLOAT;
case SQLITE_BLOB:
return Types.BLOB;
case SQLITE_NULL:
return Types.NULL;
case SQLITE_TEXT:
default:
return Types.VARCHAR;
}
}
public String getColumnTypeName(int col) throws SQLException {
switch (db.column_type(stmt.pointer, checkCol(col))) {
case SQLITE_INTEGER:
return "integer";
case SQLITE_FLOAT:
return "float";
case SQLITE_BLOB:
return "blob";
case SQLITE_NULL:
return "null";
case SQLITE_TEXT:
default:
return "text";
}
}
public int getPrecision(int col) throws SQLException {
return 0;
} // FIXME
public int getScale(int col) throws SQLException {
return 0;
}
public String getSchemaName(int col) throws SQLException {
return "";
}
public String getTableName(int col) throws SQLException {
return db.column_table_name(stmt.pointer, checkCol(col));
}
public int isNullable(int col) throws SQLException {
checkMeta();
return meta[checkCol(col)][1] ? columnNoNulls : columnNullable;
}
public boolean isAutoIncrement(int col) throws SQLException {
checkMeta();
return meta[checkCol(col)][2];
}
public boolean isCaseSensitive(int col) throws SQLException {
return true;
}
public boolean isCurrency(int col) throws SQLException {
return false;
}
public boolean isDefinitelyWritable(int col) throws SQLException {
return true;
} // FIXME: check db file constraints?
public boolean isReadOnly(int col) throws SQLException {
return false;
}
public boolean isSearchable(int col) throws SQLException {
return true;
}
public boolean isSigned(int col) throws SQLException {
return false;
}
public boolean isWritable(int col) throws SQLException {
return true;
}
public int getConcurrency() throws SQLException {
return CONCUR_READ_ONLY;
}
public boolean rowDeleted() throws SQLException {
return false;
}
public boolean rowInserted() throws SQLException {
return false;
}
public boolean rowUpdated() throws SQLException {
return false;
}
}

View File

@ -0,0 +1,102 @@
/*--------------------------------------------------------------------------
* Copyright 2009 Taro L. Saito
*
* 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.
*--------------------------------------------------------------------------*/
//--------------------------------------
// sqlite-jdbc Project
//
// ResourceFinder.java
// Since: Apr 28, 2009
//
// $URL$
// $Author$
//--------------------------------------
package org.sqlite;
import java.net.URL;
/**
* Resource address finder for files inside the jar file
*
* @author leo
*
*/
public class ResourceFinder
{
/**
* Gets the {@link URL} of the file resource
*
* @param referenceClass
* the base class for finding resources files. This method will
* search the package containing the given referenceClass.
* @param resourceFileName
* the resource file name relative to the package of the
* referenceClass
* @return the URL of the file resource
*/
public static URL find(Class< ? > referenceClass, String resourceFileName)
{
return find(referenceClass.getClassLoader(), referenceClass.getPackage(), resourceFileName);
}
/**
* Finds the {@link URL} of the resource
*
* @param basePackage
* the base package to find the resource
* @param resourceFileName
* the resource file name relative to the package folder
* @return the URL of the specified resource
*/
public static URL find(ClassLoader classLoader, Package basePackage, String resourceFileName)
{
return find(classLoader, basePackage.getName(), resourceFileName);
}
/**
* Finds the {@link URL} of the resource
*
* @param packageName
* the base package name to find the resource
* @param resourceFileName
* the resource file name relative to the package folder
* @return the URL of the specified resource
*/
public static URL find(ClassLoader classLoader, String packageName, String resourceFileName)
{
String packagePath = packagePath(packageName);
String resourcePath = packagePath + resourceFileName;
if (!resourcePath.startsWith("/"))
resourcePath = "/" + resourcePath;
return classLoader.getResource(resourcePath);
}
private static String packagePath(Class< ? > referenceClass)
{
return packagePath(referenceClass.getPackage());
}
private static String packagePath(Package basePackage)
{
return packagePath(basePackage.getName());
}
private static String packagePath(String packageName)
{
String packageAsPath = packageName.replaceAll("\\.", "/");
return packageAsPath.endsWith("/") ? packageAsPath : packageAsPath + "/";
}
}

View File

@ -0,0 +1,449 @@
/*--------------------------------------------------------------------------
* Copyright 2009 Taro L. Saito
*
* 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.
*--------------------------------------------------------------------------*/
//--------------------------------------
// sqlite-jdbc Project
//
// SQLiteConfig.java
// Since: Dec 8, 2009
//
// $URL$
// $Author$
//--------------------------------------
package org.sqlite;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.DriverPropertyInfo;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashSet;
import java.util.Properties;
/**
* SQLite Configuration
*
* See also http://www.sqlite.org/pragma.html
*
* @author leo
*
*/
public class SQLiteConfig
{
private final Properties pragmaTable;
private int openModeFlag = 0x00;
public SQLiteConfig() {
this(new Properties());
}
public SQLiteConfig(Properties prop) {
this.pragmaTable = prop;
String openMode = pragmaTable.getProperty(Pragma.OPEN_MODE.pragmaName);
if (openMode != null) {
openModeFlag = Integer.parseInt(openMode);
}
else {
// set the default open mode of SQLite3
setOpenMode(SQLiteOpenMode.READWRITE);
setOpenMode(SQLiteOpenMode.CREATE);
}
}
/**
* Create a new JDBC connection using the current configuration
*
* @return
* @throws SQLException
*/
public Connection createConnection(String url) throws SQLException {
return JDBC.createConnection(url, toProperties());
}
/**
* Apply the current configuration to connection
*
* @param conn
* @throws SQLException
*/
public void apply(Connection conn) throws SQLException {
HashSet<String> pragmaParams = new HashSet<String>();
for (Pragma each : Pragma.values()) {
pragmaParams.add(each.pragmaName);
}
pragmaParams.remove(Pragma.OPEN_MODE.pragmaName);
pragmaParams.remove(Pragma.SHARED_CACHE.pragmaName);
pragmaParams.remove(Pragma.LOAD_EXTENSION.pragmaName);
Statement stat = conn.createStatement();
try {
int count = 0;
for (Object each : pragmaTable.keySet()) {
String key = each.toString();
if (!pragmaParams.contains(key))
continue;
String value = pragmaTable.getProperty(key);
if (value != null) {
String sql = String.format("pragma %s=%s", key, value);
stat.addBatch(sql);
count++;
}
}
if (count > 0)
stat.executeBatch();
}
finally {
if (stat != null)
stat.close();
}
}
private void set(Pragma pragma, boolean flag) {
setPragma(pragma, Boolean.toString(flag));
}
private void set(Pragma pragma, int num) {
setPragma(pragma, Integer.toString(num));
}
private boolean getBoolean(Pragma pragma, String defaultValue) {
return Boolean.parseBoolean(pragmaTable.getProperty(pragma.pragmaName, defaultValue));
}
public boolean isEnabledSharedCache() {
return getBoolean(Pragma.SHARED_CACHE, "false");
}
public boolean isEnabledLoadExtension() {
return getBoolean(Pragma.LOAD_EXTENSION, "false");
}
public int getOpenModeFlags() {
return openModeFlag;
}
/**
* Set a pragma value. To take effect the pragma settings,
*
* @param pragma
* @param value
*/
public void setPragma(Pragma pragma, String value) {
pragmaTable.put(pragma.pragmaName, value);
}
/**
* Convert this SQLiteConfig settings into a Properties object, that can be
* passed to the {@link DriverManager#getConnection(String, Properties)}.
*
* @return properties representation of this configuration
*/
public Properties toProperties() {
pragmaTable.setProperty(Pragma.OPEN_MODE.pragmaName, Integer.toString(openModeFlag));
return pragmaTable;
}
static DriverPropertyInfo[] getDriverPropertyInfo() {
Pragma[] pragma = Pragma.values();
DriverPropertyInfo[] result = new DriverPropertyInfo[pragma.length];
int index = 0;
for (Pragma p : Pragma.values()) {
DriverPropertyInfo di = new DriverPropertyInfo(p.pragmaName, null);
di.choices = p.choices;
di.description = p.description;
di.required = false;
result[index++] = di;
}
return result;
}
private static final String[] OnOff = new String[] { "true", "false" };
private static enum Pragma {
// Parameters requiring SQLite3 API invocation
OPEN_MODE("open_mode", "Database open-mode flag", null),
SHARED_CACHE("shared_cache", "Enablse SQLite Shared-Cache mode, native driver only", OnOff),
LOAD_EXTENSION("enable_load_extension", "Enable SQLite load_extention() function, native driver only", OnOff),
// Pragmas that can be set after opening the database
CACHE_SIZE("cache_size"),
CASE_SENSITIVE_LIKE("case_sensitive_like", OnOff),
COUNT_CHANGES("count_changes", OnOff),
DEFAULT_CACHE_SIZE("default_cache_size"),
EMPTY_RESULT_CALLBACKS("empty_result_callback", OnOff),
ENCODING("encoding", toStringArray(Encoding.values())),
FOREIGN_KEYS("foreign_keys", OnOff),
FULL_COLUMN_NAMES("full_column_names", OnOff),
FULL_SYNC("fullsync", OnOff),
INCREMENTAL_VACUUM("incremental_vacuum"),
JOURNAL_MODE("journal_mode", toStringArray(JournalMode.values())),
JOURNAL_SIZE_LIMIT("journal_size_limit"),
LEGACY_FILE_FORMAT("legacy_file_format", OnOff),
LOCKING_MODE("locking_mode", toStringArray(LockingMode.values())),
PAGE_SIZE("page_size"),
MAX_PAGE_COUNT("max_page_count"),
READ_UNCOMMITED("read_uncommited", OnOff),
RECURSIVE_TRIGGERS("recursive_triggers", OnOff),
REVERSE_UNORDERED_SELECTS("reverse_unordered_selects", OnOff),
SHORT_COLUMN_NAMES("short_column_names", OnOff),
SYNCHRONOUS("synchronous", toStringArray(SynchronousMode.values())),
TEMP_STORE("temp_store", toStringArray(TempStore.values())),
TEMP_STORE_DIRECTORY("temp_store_directory"),
USER_VERSION("user_version");
public final String pragmaName;
public final String[] choices;
public final String description;
private Pragma(String pragmaName) {
this(pragmaName, null);
}
private Pragma(String pragmaName, String[] choices) {
this(pragmaName, null, null);
}
private Pragma(String pragmaName, String description, String[] choices) {
this.pragmaName = pragmaName;
this.description = description;
this.choices = choices;
}
}
/**
* Set the database open mode
*
* @param mode
*/
public void setOpenMode(SQLiteOpenMode mode) {
openModeFlag |= mode.flag;
}
/**
* Reset the specified database open mode flag
*
* @param mode
*/
public void resetOpenMode(SQLiteOpenMode mode) {
openModeFlag &= ~mode.flag;
}
public void setSharedCache(boolean enable) {
set(Pragma.SHARED_CACHE, enable);
}
public void enableLoadExtension(boolean enable) {
set(Pragma.LOAD_EXTENSION, enable);
}
public void setReadOnly(boolean readOnly) {
if (readOnly) {
setOpenMode(SQLiteOpenMode.READONLY);
resetOpenMode(SQLiteOpenMode.READWRITE);
}
else {
setOpenMode(SQLiteOpenMode.READWRITE);
resetOpenMode(SQLiteOpenMode.READONLY);
}
}
public void setCacheSize(int numberOfPages) {
set(Pragma.CACHE_SIZE, numberOfPages);
}
public void enableCaseSensitiveLike(boolean enable) {
set(Pragma.CASE_SENSITIVE_LIKE, enable);
}
public void enableCountChanges(boolean enable) {
set(Pragma.COUNT_CHANGES, enable);
}
/**
* Set the cache size persistently across database connections
*
* @param numberOfPages
*/
public void setDefaultCacheSize(int numberOfPages) {
set(Pragma.DEFAULT_CACHE_SIZE, numberOfPages);
}
public void enableEmptyResultCallBacks(boolean enable) {
set(Pragma.EMPTY_RESULT_CALLBACKS, enable);
}
/**
* The common interface for retrieving the available pragma parameter
* values.
*
* @author leo
*
*/
private static interface PragmaValue
{
public String getValue();
}
/**
* Convert the given Enum values to a string array
*
* @param list
* @return
*/
private static String[] toStringArray(PragmaValue[] list) {
String[] result = new String[list.length];
for (int i = 0; i < list.length; i++) {
result[i] = list[i].getValue();
}
return result;
}
public static enum Encoding implements PragmaValue {
UTF8("UTF-8"), UTF16("UTF-16"), UTF16_LITTLE_ENDIAN("UTF-16le"), UTF16_BIG_ENDIAN("UTF-16be");
public final String typeName;
private Encoding(String typeName) {
this.typeName = typeName;
}
public String getValue() {
return typeName;
}
}
public static enum JournalMode implements PragmaValue {
DELETE, TRUNCATE, PERSIST, MEMORY, OFF;
public String getValue() {
return name();
}
}
public void setEncoding(Encoding encoding) {
setPragma(Pragma.ENCODING, encoding.typeName);
}
public void enforceForeignKeys(boolean enforce) {
set(Pragma.FOREIGN_KEYS, enforce);
}
public void enableFullColumnNames(boolean enable) {
set(Pragma.FULL_COLUMN_NAMES, enable);
}
public void enableFullSync(boolean enable) {
set(Pragma.FULL_SYNC, enable);
}
public void incrementalVacuum(int numberOfPagesToBeRemoved) {
set(Pragma.INCREMENTAL_VACUUM, numberOfPagesToBeRemoved);
}
public void setJournalMode(JournalMode mode) {
setPragma(Pragma.JOURNAL_MODE, mode.name());
}
// public void setJournalMode(String databaseName, JournalMode mode) {
// setPragma(databaseName, Pragma.JOURNAL_MODE, mode.name());
// }
public void setJounalSizeLimit(int limit) {
set(Pragma.JOURNAL_SIZE_LIMIT, limit);
}
public void useLegacyFileFormat(boolean use) {
set(Pragma.LEGACY_FILE_FORMAT, use);
}
public static enum LockingMode implements PragmaValue {
NORMAL, EXCLUSIVE;
public String getValue() {
return name();
}
}
public void setLockingMode(LockingMode mode) {
setPragma(Pragma.LOCKING_MODE, mode.name());
}
// public void setLockingMode(String databaseName, LockingMode mode) {
// setPragma(databaseName, Pragma.LOCKING_MODE, mode.name());
// }
public void setPageSize(int numBytes) {
set(Pragma.PAGE_SIZE, numBytes);
}
public void setMaxPageCount(int numPages) {
set(Pragma.MAX_PAGE_COUNT, numPages);
}
public void setReadUncommited(boolean useReadUncommitedIsolationMode) {
set(Pragma.READ_UNCOMMITED, useReadUncommitedIsolationMode);
}
public void enableRecursiveTriggers(boolean enable) {
set(Pragma.RECURSIVE_TRIGGERS, enable);
}
public void enableReverseUnorderedSelects(boolean enable) {
set(Pragma.REVERSE_UNORDERED_SELECTS, enable);
}
public void enableShortColumnNames(boolean enable) {
set(Pragma.SHORT_COLUMN_NAMES, enable);
}
public static enum SynchronousMode implements PragmaValue {
OFF, NORMAL, FULL;
public String getValue() {
return name();
}
}
public void setSynchronous(SynchronousMode mode) {
setPragma(Pragma.SYNCHRONOUS, mode.name());
}
public static enum TempStore implements PragmaValue {
DEFAULT, FILE, MEMORY;
public String getValue() {
return name();
}
}
public void setTempStore(TempStore storeType) {
setPragma(Pragma.TEMP_STORE, storeType.name());
}
public void setTempStoreDirectory(String directoryName) {
setPragma(Pragma.TEMP_STORE_DIRECTORY, String.format("'%s'", directoryName));
}
public void setUserVersion(int version) {
set(Pragma.USER_VERSION, version);
}
}

View File

@ -0,0 +1,228 @@
/*--------------------------------------------------------------------------
* Copyright 2010 Taro L. Saito
*
* 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.
*--------------------------------------------------------------------------*/
//--------------------------------------
// sqlite-jdbc Project
//
// SQLiteDataSource.java
// Since: Mar 11, 2010
//
// $URL$
// $Author$
//--------------------------------------
package org.sqlite;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
import javax.sql.DataSource;
import org.sqlite.SQLiteConfig.Encoding;
import org.sqlite.SQLiteConfig.JournalMode;
import org.sqlite.SQLiteConfig.LockingMode;
import org.sqlite.SQLiteConfig.SynchronousMode;
import org.sqlite.SQLiteConfig.TempStore;
/**
* Provides {@link DataSource} API for configuring SQLite database connection
*
* @author leo
*
*/
public class SQLiteDataSource implements DataSource
{
private SQLiteConfig config;
private transient PrintWriter logger;
private int loginTimeout = 1;
private String url = JDBC.PREFIX; // use memory database in default
public SQLiteDataSource() {
this.config = new SQLiteConfig(); // default configuration
}
public SQLiteDataSource(SQLiteConfig config) {
this.config = config;
}
/**
* Set the configuration parameters via {@link SQLiteConfig} object
*
* @param config
*/
public void setConfig(SQLiteConfig config) {
this.config = config;
}
public SQLiteConfig getConfig() {
return config;
}
// configuration parameters
public void setUrl(String url) {
this.url = url;
}
public String getUrl() {
return url;
}
public void setSharedCache(boolean enable) {
config.setSharedCache(enable);
}
public void setLoadExtension(boolean enable) {
config.enableLoadExtension(enable);
}
public void setReadOnly(boolean readOnly) {
config.setReadOnly(readOnly);
}
public void setCacheSize(int numberOfPages) {
config.setCacheSize(numberOfPages);
}
public void setCaseSensitiveLike(boolean enable) {
config.enableCaseSensitiveLike(enable);
}
public void setCouncChanges(boolean enable) {
config.enableCountChanges(enable);
}
public void setDefaultCacheSize(int numberOfPages) {
config.setDefaultCacheSize(numberOfPages);
}
public void setEncoding(String encoding) {
config.setEncoding(Encoding.valueOf(encoding));
}
public void setEnforceForeinKeys(boolean enforce) {
config.enforceForeignKeys(enforce);
}
public void setFullColumnNames(boolean enable) {
config.enableFullColumnNames(enable);
}
public void setFullSync(boolean enable) {
config.enableFullSync(enable);
}
public void setIncrementalVacuum(int numberOfPagesToBeRemoved) {
config.incrementalVacuum(numberOfPagesToBeRemoved);
}
public void setJournalMode(String mode) {
config.setJournalMode(JournalMode.valueOf(mode));
}
public void setJournalSizeLimit(int limit) {
config.setJounalSizeLimit(limit);
}
public void setLegacyFileFormat(boolean use) {
config.useLegacyFileFormat(use);
}
public void setLockingMode(String mode) {
config.setLockingMode(LockingMode.valueOf(mode));
}
public void setPageSize(int numBytes) {
config.setPageSize(numBytes);
}
public void setMaxPageCount(int numPages) {
config.setMaxPageCount(numPages);
}
public void setReadUncommited(boolean useReadUncommitedIsolationMode) {
config.setReadUncommited(useReadUncommitedIsolationMode);
}
public void setRecursiveTriggers(boolean enable) {
config.enableRecursiveTriggers(enable);
}
public void setReverseUnorderedSelects(boolean enable) {
config.enableReverseUnorderedSelects(enable);
}
public void setShortColumnNames(boolean enable) {
config.enableShortColumnNames(enable);
}
public void setSynchronous(String mode) {
config.setSynchronous(SynchronousMode.valueOf(mode));
}
public void setTempStore(String storeType) {
config.setTempStore(TempStore.valueOf(storeType));
}
public void setTempStoreDirectory(String directoryName) {
config.setTempStoreDirectory(directoryName);
}
public void setUserVersion(int version) {
config.setUserVersion(version);
}
// codes for the DataSource interface
public Connection getConnection() throws SQLException {
return getConnection(null, null);
}
public Connection getConnection(String username, String password) throws SQLException {
Properties p = config.toProperties();
if (username != null)
p.put("user", username);
if (password != null)
p.put("pass", password);
return JDBC.createConnection(url, p);
}
public PrintWriter getLogWriter() throws SQLException {
return logger;
}
public int getLoginTimeout() throws SQLException {
return loginTimeout;
}
public void setLogWriter(PrintWriter out) throws SQLException {
this.logger = out;
}
public void setLoginTimeout(int seconds) throws SQLException {
loginTimeout = seconds;
}
public boolean isWrapperFor(Class< ? > iface) throws SQLException {
return iface.isInstance(this);
}
@SuppressWarnings("unchecked")
public <T> T unwrap(Class<T> iface) throws SQLException {
return (T) this;
}
}

View File

@ -0,0 +1,92 @@
/*--------------------------------------------------------------------------
* Copyright 2009 Taro L. Saito
*
* 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.
*--------------------------------------------------------------------------*/
//--------------------------------------
// sqlite-jdbc Project
//
// SQLiteErrorCode.java
// Since: Apr 21, 2009
//
// $URL$
// $Author$
//--------------------------------------
package org.sqlite;
/**
* SQLite3 error code
*
* @author leo
* @see http://www.sqlite.org/c3ref/c_abort.html
*
*/
public enum SQLiteErrorCode {
UNKNOWN_ERROR(-1, "unknown error"),
SQLITE_OK(0, "Successful result"),
/* beginning-of-error-codes */
SQLITE_ERROR(1, "SQL error or missing database"),
SQLITE_INTERNAL(2, "Internal logic error in SQLite"),
SQLITE_PERM(3, " Access permission denied"),
SQLITE_ABORT(4, " Callback routine requested an abort"),
SQLITE_BUSY(5, " The database file is locked"),
SQLITE_LOCKED(6, " A table in the database is locked"),
SQLITE_NOMEM(7, " A malloc() failed"),
SQLITE_READONLY(8, " Attempt to write a readonly database"),
SQLITE_INTERRUPT(9, " Operation terminated by sqlite3_interrupt()"),
SQLITE_IOERR(10, " Some kind of disk I/O error occurred"),
SQLITE_CORRUPT(11, " The database disk image is malformed"),
SQLITE_NOTFOUND(12, " NOT USED. Table or record not found"),
SQLITE_FULL(13, " Insertion failed because database is full"),
SQLITE_CANTOPEN(14, " Unable to open the database file"),
SQLITE_PROTOCOL(15, " NOT USED. Database lock protocol error"),
SQLITE_EMPTY(16, " Database is empty"),
SQLITE_SCHEMA(17, " The database schema changed"),
SQLITE_TOOBIG(18, " String or BLOB exceeds size limit"),
SQLITE_CONSTRAINT(19, " Abort due to constraint violation"),
SQLITE_MISMATCH(20, " Data type mismatch"),
SQLITE_MISUSE(21, " Library used incorrectly"),
SQLITE_NOLFS(22, " Uses OS features not supported on host"),
SQLITE_AUTH(23, " Authorization denied"),
SQLITE_FORMAT(24, " Auxiliary database format error"),
SQLITE_RANGE(25, " 2nd parameter to sqlite3_bind out of range"),
SQLITE_NOTADB(26, " File opened that is not a database file"),
SQLITE_ROW(100, " sqlite3_step() has another row ready"),
SQLITE_DONE(101, " sqlite3_step() has finished executing");
public final int code;
public final String message;
private SQLiteErrorCode(int code, String message)
{
this.code = code;
this.message = message;
}
public static SQLiteErrorCode getErrorCode(int errorCode)
{
for (SQLiteErrorCode each : SQLiteErrorCode.values())
{
if (errorCode == each.code)
return each;
}
return UNKNOWN_ERROR;
}
@Override
public String toString()
{
return String.format("[%s] %s", this.name(), message);
}
}

View File

@ -0,0 +1,271 @@
/*--------------------------------------------------------------------------
* Copyright 2007 Taro L. Saito
*
* 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.
*--------------------------------------------------------------------------*/
//--------------------------------------
// SQLite JDBC Project
//
// SQLite.java
// Since: 2007/05/10
//
// $URL$
// $Author$
//--------------------------------------
package org.sqlite;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Properties;
/**
* Set the system properties, org.sqlite.lib.path, org.sqlite.lib.name,
* appropriately so that the SQLite JDBC driver can find *.dll, *.jnilib and
* *.so files, according to the current OS (win, linux, mac).
*
* The library files are automatically extracted from this project's package
* (JAR).
*
* usage: call {@link #initialize()} before using SQLite JDBC driver.
*
* @author leo
*
*/
public class SQLiteJDBCLoader
{
private static boolean extracted = false;
public static boolean initialize() {
loadSQLiteNativeLibrary();
return extracted;
}
static boolean getPureJavaFlag() {
return Boolean.parseBoolean(System.getProperty("sqlite.purejava", "false"));
}
public static boolean isPureJavaMode() {
return !isNativeMode();
}
public static boolean isNativeMode() {
if (getPureJavaFlag())
return false;
// load the driver
initialize();
return extracted;
}
/**
* Computes the MD5 value of the input stream
*
* @param input
* @return
* @throws IOException
* @throws NoSuchAlgorithmException
*/
static String md5sum(InputStream input) throws IOException {
BufferedInputStream in = new BufferedInputStream(input);
try {
MessageDigest digest = java.security.MessageDigest.getInstance("MD5");
DigestInputStream digestInputStream = new DigestInputStream(in, digest);
for (; digestInputStream.read() >= 0;) {
}
ByteArrayOutputStream md5out = new ByteArrayOutputStream();
md5out.write(digest.digest());
return md5out.toString();
}
catch (NoSuchAlgorithmException e) {
throw new IllegalStateException("MD5 algorithm is not available: " + e);
}
finally {
in.close();
}
}
/**
* Extract the specified library file to the target folder
*
* @param libFolderForCurrentOS
* @param libraryFileName
* @param targetFolder
* @return
*/
private static boolean extractAndLoadLibraryFile(String libFolderForCurrentOS, String libraryFileName,
String targetFolder) {
String nativeLibraryFilePath = libFolderForCurrentOS + "/" + libraryFileName;
final String prefix = "sqlite-" + getVersion() + "-";
String extractedLibFileName = prefix + libraryFileName;
File extractedLibFile = new File(targetFolder, extractedLibFileName);
try {
if (extractedLibFile.exists()) {
// test md5sum value
String md5sum1 = md5sum(SQLiteJDBCLoader.class.getResourceAsStream(nativeLibraryFilePath));
String md5sum2 = md5sum(new FileInputStream(extractedLibFile));
if (md5sum1.equals(md5sum2)) {
return loadNativeLibrary(targetFolder, extractedLibFileName);
}
else {
// remove old native library file
boolean deletionSucceeded = extractedLibFile.delete();
if (!deletionSucceeded) {
throw new IOException("failed to remove existing native library file: "
+ extractedLibFile.getAbsolutePath());
}
}
}
// extract file into the current directory
InputStream reader = SQLiteJDBCLoader.class.getResourceAsStream(nativeLibraryFilePath);
FileOutputStream writer = new FileOutputStream(extractedLibFile);
byte[] buffer = new byte[1024];
int bytesRead = 0;
while ((bytesRead = reader.read(buffer)) != -1) {
writer.write(buffer, 0, bytesRead);
}
writer.close();
reader.close();
if (!System.getProperty("os.name").contains("Windows")) {
try {
Runtime.getRuntime().exec(new String[] { "chmod", "755", extractedLibFile.getAbsolutePath() })
.waitFor();
}
catch (Throwable e) {}
}
return loadNativeLibrary(targetFolder, extractedLibFileName);
}
catch (IOException e) {
System.err.println(e.getMessage());
return false;
}
}
private static synchronized boolean loadNativeLibrary(String path, String name) {
File libPath = new File(path, name);
if (libPath.exists()) {
try {
System.load(new File(path, name).getAbsolutePath());
return true;
}
catch (UnsatisfiedLinkError e) {
System.err.println(e);
return false;
}
}
else
return false;
}
private static void loadSQLiteNativeLibrary() {
if (extracted)
return;
boolean runInPureJavaMode = getPureJavaFlag();
if (runInPureJavaMode) {
extracted = false;
return;
}
// Try loading library from org.sqlite.lib.path library path */
String sqliteNativeLibraryPath = System.getProperty("org.sqlite.lib.path");
String sqliteNativeLibraryName = System.getProperty("org.sqlite.lib.name");
if (sqliteNativeLibraryName == null)
sqliteNativeLibraryName = System.mapLibraryName("sqlitejdbc");
if (sqliteNativeLibraryPath != null) {
if (loadNativeLibrary(sqliteNativeLibraryPath, sqliteNativeLibraryName)) {
extracted = true;
return;
}
}
// Load the os-dependent library from a jar file
sqliteNativeLibraryPath = "/native/" + OSInfo.getNativeLibFolderPathForCurrentOS();
if (SQLiteJDBCLoader.class.getResource(sqliteNativeLibraryPath + "/" + sqliteNativeLibraryName) == null) {
// use nested VM version
return;
}
// temporary library folder
String tempFolder = new File(System.getProperty("java.io.tmpdir")).getAbsolutePath();
// Try extracting the library from jar
if (extractAndLoadLibraryFile(sqliteNativeLibraryPath, sqliteNativeLibraryName, tempFolder)) {
extracted = true;
return;
}
extracted = false;
return;
}
private static void getNativeLibraryFolderForTheCurrentOS() {
String osName = OSInfo.getOSName();
String archName = OSInfo.getArchName();
}
public static int getMajorVersion() {
String[] c = getVersion().split("\\.");
return (c.length > 0) ? Integer.parseInt(c[0]) : 1;
}
public static int getMinorVersion() {
String[] c = getVersion().split("\\.");
return (c.length > 1) ? Integer.parseInt(c[1]) : 0;
}
public static String getVersion() {
URL versionFile = SQLiteJDBCLoader.class.getResource("/META-INF/maven/org.xerial/sqlite-jdbc/pom.properties");
if (versionFile == null)
versionFile = SQLiteJDBCLoader.class.getResource("/META-INF/maven/org.xerial/sqlite-jdbc/VERSION");
String version = "unknown";
try {
if (versionFile != null) {
Properties versionData = new Properties();
versionData.load(versionFile.openStream());
version = versionData.getProperty("version", version);
version = version.trim().replaceAll("[^0-9\\.]", "");
}
}
catch (IOException e) {
System.err.println(e);
}
return version;
}
}

View File

@ -0,0 +1,59 @@
/*--------------------------------------------------------------------------
* Copyright 2009 Taro L. Saito
*
* 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.
*--------------------------------------------------------------------------*/
//--------------------------------------
// sqlite-jdbc Project
//
// SQLiteOpenMode.java
// Since: Dec 8, 2009
//
// $URL$
// $Author$
//--------------------------------------
package org.sqlite;
/**
* Database file open modes of SQLite.
*
* See also http://sqlite.org/c3ref/open.html
*
* @author leo
*
*/
public enum SQLiteOpenMode {
READONLY(0x00000001), /* Ok for int SQLITE3_open_v2() */
READWRITE(0x00000002), /* Ok for int SQLITE3_open_v2() */
CREATE(0x00000004), /* Ok for int SQLITE3_open_v2() */
DELETEONCLOSE(0x00000008), /* VFS only */
EXCLUSIVE(0x00000010), /* VFS only */
MAIN_DB(0x00000100), /* VFS only */
TEMP_DB(0x00000200), /* VFS only */
TRANSIENT_DB(0x00000400), /* VFS only */
MAIN_JOURNAL(0x00000800), /* VFS only */
TEMP_JOURNAL(0x00001000), /* VFS only */
SUBJOURNAL(0x00002000), /* VFS only */
MASTER_JOURNAL(0x00004000), /* VFS only */
NOMUTEX(0x00008000), /* Ok for int SQLITE3_open_v2() */
FULLMUTEX(0x00010000), /* Ok for int SQLITE3_open_v2() */
SHAREDCACHE(0x00020000), /* Ok for int SQLITE3_open_v2() */
PRIVATECACHE(0x00040000) /* Ok for sqlite3_open_v2() */
;
public final int flag;
private SQLiteOpenMode(int flag) {
this.flag = flag;
}
}

337
libs/org/sqlite/Stmt.java Normal file
View File

@ -0,0 +1,337 @@
/*
* Copyright (c) 2007 David Crawshaw <david@zentus.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package org.sqlite;
import java.sql.BatchUpdateException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.Statement;
import org.sqlite.DB.ProgressObserver;
import org.sqlite.ExtendedCommand.SQLExtension;
class Stmt extends Unused implements Statement, Codes
{
final Conn conn;
final DB db;
final RS rs;
long pointer;
String sql = null;
int batchPos;
Object[] batch = null;
boolean resultsWaiting = false;
Stmt(Conn c) {
conn = c;
db = conn.db();
rs = new RS(this);
}
protected final void checkOpen() throws SQLException {
if (pointer == 0)
throw new SQLException("statement is not executing");
}
boolean isOpen() throws SQLException {
return (pointer != 0);
}
/** Calls sqlite3_step() and sets up results. Expects a clean stmt. */
protected boolean exec() throws SQLException {
if (sql == null)
throw new SQLException("SQLiteJDBC internal error: sql==null");
if (rs.isOpen())
throw new SQLException("SQLite JDBC internal error: rs.isOpen() on exec.");
boolean rc = false;
try {
rc = db.execute(this, null);
}
finally {
resultsWaiting = rc;
}
return db.column_count(pointer) != 0;
}
protected boolean exec(String sql) throws SQLException {
if (sql == null)
throw new SQLException("SQLiteJDBC internal error: sql==null");
if (rs.isOpen())
throw new SQLException("SQLite JDBC internal error: rs.isOpen() on exec.");
boolean rc = false;
try {
rc = db.execute(sql);
}
finally {
resultsWaiting = rc;
}
return db.column_count(pointer) != 0;
}
// PUBLIC INTERFACE /////////////////////////////////////////////
public void close() throws SQLException {
if (pointer == 0)
return;
rs.close();
batch = null;
batchPos = 0;
int resp = db.finalize(this);
if (resp != SQLITE_OK && resp != SQLITE_MISUSE)
db.throwex();
}
@Override
protected void finalize() throws SQLException {
close();
}
public boolean execute(String sql) throws SQLException {
close();
this.sql = sql;
db.prepare(this);
return exec();
}
public ResultSet executeQuery(String sql) throws SQLException {
close();
this.sql = sql;
db.prepare(this);
if (!exec()) {
close();
throw new SQLException("query does not return ResultSet");
}
return getResultSet();
}
static class BackupObserver implements ProgressObserver
{
public void progress(int remaining, int pageCount) {
System.out.println(String.format("remaining:%d, page count:%d", remaining, pageCount));
}
}
public int executeUpdate(String sql) throws SQLException {
close();
this.sql = sql;
int changes = 0;
SQLExtension ext = ExtendedCommand.parse(sql);
if (ext != null) {
// execute extended command
ext.execute(db);
}
else {
try {
//db.prepare(this);
//changes = db.executeUpdate(this, null);
// directly invokes the exec API to support multiple SQL statements
int statusCode = db._exec(sql);
if (statusCode != SQLITE_OK)
throw DB.newSQLException(statusCode, "");
changes = db.changes();
}
finally {
close();
}
}
return changes;
}
public ResultSet getResultSet() throws SQLException {
checkOpen();
if (rs.isOpen())
throw new SQLException("ResultSet already requested");
if (db.column_count(pointer) == 0)
throw new SQLException("no ResultSet available");
if (rs.colsMeta == null)
rs.colsMeta = db.column_names(pointer);
rs.cols = rs.colsMeta;
rs.open = resultsWaiting;
resultsWaiting = false;
return rs;
}
/*
* This function has a complex behaviour best understood by carefully
* reading the JavaDoc for getMoreResults() and considering the test
* StatementTest.execute().
*/
public int getUpdateCount() throws SQLException {
if (pointer != 0 && !rs.isOpen() && !resultsWaiting && db.column_count(pointer) == 0)
return db.changes();
return -1;
}
public void addBatch(String sql) throws SQLException {
close();
if (batch == null || batchPos + 1 >= batch.length) {
Object[] nb = new Object[Math.max(10, batchPos * 2)];
if (batch != null)
System.arraycopy(batch, 0, nb, 0, batch.length);
batch = nb;
}
batch[batchPos++] = sql;
}
public void clearBatch() throws SQLException {
batchPos = 0;
if (batch != null)
for (int i = 0; i < batch.length; i++)
batch[i] = null;
}
public int[] executeBatch() throws SQLException {
// TODO: optimize
close();
if (batch == null || batchPos == 0)
return new int[] {};
int[] changes = new int[batchPos];
synchronized (db) {
try {
for (int i = 0; i < changes.length; i++) {
try {
this.sql = (String) batch[i];
db.prepare(this);
changes[i] = db.executeUpdate(this, null);
}
catch (SQLException e) {
throw new BatchUpdateException("batch entry " + i + ": " + e.getMessage(), changes);
}
finally {
db.finalize(this);
}
}
}
finally {
clearBatch();
}
}
return changes;
}
public void setCursorName(String name) {}
public SQLWarning getWarnings() throws SQLException {
return null;
}
public void clearWarnings() throws SQLException {}
public Connection getConnection() throws SQLException {
return conn;
}
public void cancel() throws SQLException {
rs.checkOpen();
db.interrupt();
}
public int getQueryTimeout() throws SQLException {
return conn.getTimeout();
}
public void setQueryTimeout(int seconds) throws SQLException {
if (seconds < 0)
throw new SQLException("query timeout must be >= 0");
conn.setTimeout(1000 * seconds);
}
// TODO: write test
public int getMaxRows() throws SQLException {
//checkOpen();
return rs.maxRows;
}
public void setMaxRows(int max) throws SQLException {
//checkOpen();
if (max < 0)
throw new SQLException("max row count must be >= 0");
rs.maxRows = max;
}
public int getMaxFieldSize() throws SQLException {
return 0;
}
public void setMaxFieldSize(int max) throws SQLException {
if (max < 0)
throw new SQLException("max field size " + max + " cannot be negative");
}
public int getFetchSize() throws SQLException {
return rs.getFetchSize();
}
public void setFetchSize(int r) throws SQLException {
rs.setFetchSize(r);
}
public int getFetchDirection() throws SQLException {
return rs.getFetchDirection();
}
public void setFetchDirection(int d) throws SQLException {
rs.setFetchDirection(d);
}
/**
* As SQLite's last_insert_rowid() function is DB-specific not statement
* specific, this function introduces a race condition if the same
* connection is used by two threads and both insert.
*/
public ResultSet getGeneratedKeys() throws SQLException {
return ((MetaData) conn.getMetaData()).getGeneratedKeys();
}
/** SQLite does not support multiple results from execute(). */
public boolean getMoreResults() throws SQLException {
return getMoreResults(0);
}
public boolean getMoreResults(int c) throws SQLException {
checkOpen();
close(); // as we never have another result, clean up pointer
return false;
}
public int getResultSetConcurrency() throws SQLException {
return ResultSet.CONCUR_READ_ONLY;
}
public int getResultSetHoldability() throws SQLException {
return ResultSet.CLOSE_CURSORS_AT_COMMIT;
}
public int getResultSetType() throws SQLException {
return ResultSet.TYPE_FORWARD_ONLY;
}
}

244
libs/org/sqlite/Unused.java Normal file
View File

@ -0,0 +1,244 @@
/*
* Copyright (c) 2007 David Crawshaw <david@zentus.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package org.sqlite;
import java.io.*;
import java.math.*;
import java.net.*;
import java.sql.*;
import java.util.Map;
/** Unused JDBC functions from Statement, PreparedStatement and ResultSet. */
abstract class Unused
{
private SQLException unused() {
return new SQLException("not implemented by SQLite JDBC driver");
}
// Statement ////////////////////////////////////////////////////
public void setEscapeProcessing(boolean enable)
throws SQLException { throw unused(); }
public boolean execute(String sql, int[] colinds)
throws SQLException { throw unused(); }
public boolean execute(String sql, String[] colnames)
throws SQLException { throw unused(); }
public int executeUpdate(String sql, int autoKeys)
throws SQLException { throw unused(); }
public int executeUpdate(String sql, int[] colinds)
throws SQLException { throw unused(); }
public int executeUpdate(String sql, String[] cols)
throws SQLException { throw unused(); }
public boolean execute(String sql, int autokeys)
throws SQLException { throw unused(); }
// PreparedStatement ////////////////////////////////////////////
public void setArray(int i, Array x)
throws SQLException { throw unused(); }
public void setAsciiStream(int parameterIndex, InputStream x, int length)
throws SQLException { throw unused(); }
public void setBigDecimal(int parameterIndex, BigDecimal x)
throws SQLException { throw unused(); }
public void setBinaryStream(int parameterIndex, InputStream x, int length)
throws SQLException { throw unused(); }
public void setBlob(int i, Blob x)
throws SQLException { throw unused(); }
public void setClob(int i, Clob x)
throws SQLException { throw unused(); }
public void setRef(int i, Ref x)
throws SQLException { throw unused(); }
public void setUnicodeStream(int pos, InputStream x, int length)
throws SQLException { throw unused(); }
public void setURL(int pos, URL x)
throws SQLException { throw unused(); }
// ResultSet ////////////////////////////////////////////////////
public Array getArray(int i)
throws SQLException { throw unused(); }
public Array getArray(String col)
throws SQLException { throw unused(); }
public InputStream getAsciiStream(int col)
throws SQLException { throw unused(); }
public InputStream getAsciiStream(String col)
throws SQLException { throw unused(); }
public BigDecimal getBigDecimal(int col)
throws SQLException { throw unused(); }
public BigDecimal getBigDecimal(int col, int s)
throws SQLException { throw unused(); }
public BigDecimal getBigDecimal(String col)
throws SQLException { throw unused(); }
public BigDecimal getBigDecimal(String col, int s)
throws SQLException { throw unused(); }
public InputStream getBinaryStream(int col)
throws SQLException { throw unused(); }
public InputStream getBinaryStream(String col)
throws SQLException { throw unused(); }
public Blob getBlob(int col)
throws SQLException { throw unused(); }
public Blob getBlob(String col)
throws SQLException { throw unused(); }
public Clob getClob(int col)
throws SQLException { throw unused(); }
public Clob getClob(String col)
throws SQLException { throw unused(); }
public Object getObject(int col, Map map)
throws SQLException { throw unused(); }
public Object getObject(String col, Map map)
throws SQLException { throw unused(); }
public Ref getRef(int i)
throws SQLException { throw unused(); }
public Ref getRef(String col)
throws SQLException { throw unused(); }
public InputStream getUnicodeStream(int col)
throws SQLException { throw unused(); }
public InputStream getUnicodeStream(String col)
throws SQLException { throw unused(); }
public URL getURL(int col)
throws SQLException { throw unused(); }
public URL getURL(String col)
throws SQLException { throw unused(); }
public void insertRow() throws SQLException {
throw new SQLException("ResultSet is TYPE_FORWARD_ONLY"); }
public void moveToCurrentRow() throws SQLException {
throw new SQLException("ResultSet is TYPE_FORWARD_ONLY"); }
public void moveToInsertRow() throws SQLException {
throw new SQLException("ResultSet is TYPE_FORWARD_ONLY"); }
public boolean last() throws SQLException {
throw new SQLException("ResultSet is TYPE_FORWARD_ONLY"); }
public boolean previous() throws SQLException {
throw new SQLException("ResultSet is TYPE_FORWARD_ONLY"); }
public boolean relative(int rows) throws SQLException {
throw new SQLException("ResultSet is TYPE_FORWARD_ONLY"); }
public boolean absolute(int row) throws SQLException {
throw new SQLException("ResultSet is TYPE_FORWARD_ONLY"); }
public void afterLast() throws SQLException {
throw new SQLException("ResultSet is TYPE_FORWARD_ONLY"); }
public void beforeFirst() throws SQLException {
throw new SQLException("ResultSet is TYPE_FORWARD_ONLY"); }
public boolean first() throws SQLException {
throw new SQLException("ResultSet is TYPE_FORWARD_ONLY"); }
public void cancelRowUpdates()
throws SQLException { throw unused(); }
public void deleteRow()
throws SQLException { throw unused(); }
public void updateArray(int col, Array x)
throws SQLException { throw unused(); }
public void updateArray(String col, Array x)
throws SQLException { throw unused(); }
public void updateAsciiStream(int col, InputStream x, int l)
throws SQLException { throw unused(); }
public void updateAsciiStream(String col, InputStream x, int l)
throws SQLException { throw unused(); }
public void updateBigDecimal(int col, BigDecimal x)
throws SQLException { throw unused(); }
public void updateBigDecimal(String col, BigDecimal x)
throws SQLException { throw unused(); }
public void updateBinaryStream(int c, InputStream x, int l)
throws SQLException { throw unused(); }
public void updateBinaryStream(String c, InputStream x, int l)
throws SQLException { throw unused(); }
public void updateBlob(int col, Blob x)
throws SQLException { throw unused(); }
public void updateBlob(String col, Blob x)
throws SQLException { throw unused(); }
public void updateBoolean(int col, boolean x)
throws SQLException { throw unused(); }
public void updateBoolean(String col, boolean x)
throws SQLException { throw unused(); }
public void updateByte(int col, byte x)
throws SQLException { throw unused(); }
public void updateByte(String col, byte x)
throws SQLException { throw unused(); }
public void updateBytes(int col, byte[] x)
throws SQLException { throw unused(); }
public void updateBytes(String col, byte[] x)
throws SQLException { throw unused(); }
public void updateCharacterStream(int c, Reader x, int l)
throws SQLException { throw unused(); }
public void updateCharacterStream(String c, Reader r, int l)
throws SQLException { throw unused(); }
public void updateClob(int col, Clob x)
throws SQLException { throw unused(); }
public void updateClob(String col, Clob x)
throws SQLException { throw unused(); }
public void updateDate(int col, Date x)
throws SQLException { throw unused(); }
public void updateDate(String col, Date x)
throws SQLException { throw unused(); }
public void updateDouble(int col, double x)
throws SQLException { throw unused(); }
public void updateDouble(String col, double x)
throws SQLException { throw unused(); }
public void updateFloat(int col, float x)
throws SQLException { throw unused(); }
public void updateFloat(String col, float x)
throws SQLException { throw unused(); }
public void updateInt(int col, int x)
throws SQLException { throw unused(); }
public void updateInt(String col, int x)
throws SQLException { throw unused(); }
public void updateLong(int col, long x)
throws SQLException { throw unused(); }
public void updateLong(String col, long x)
throws SQLException { throw unused(); }
public void updateNull(int col)
throws SQLException { throw unused(); }
public void updateNull(String col)
throws SQLException { throw unused(); }
public void updateObject(int c, Object x)
throws SQLException { throw unused(); }
public void updateObject(int c, Object x, int s)
throws SQLException { throw unused(); }
public void updateObject(String col, Object x)
throws SQLException { throw unused(); }
public void updateObject(String c, Object x, int s)
throws SQLException { throw unused(); }
public void updateRef(int col, Ref x)
throws SQLException { throw unused(); }
public void updateRef(String c, Ref x)
throws SQLException { throw unused(); }
public void updateRow()
throws SQLException { throw unused(); }
public void updateShort(int c, short x)
throws SQLException { throw unused(); }
public void updateShort(String c, short x)
throws SQLException { throw unused(); }
public void updateString(int c, String x)
throws SQLException { throw unused(); }
public void updateString(String c, String x)
throws SQLException { throw unused(); }
public void updateTime(int c, Time x)
throws SQLException { throw unused(); }
public void updateTime(String c, Time x)
throws SQLException { throw unused(); }
public void updateTimestamp(int c, Timestamp x)
throws SQLException { throw unused(); }
public void updateTimestamp(String c, Timestamp x)
throws SQLException { throw unused(); }
public void refreshRow()
throws SQLException { throw unused(); }
}

View File

@ -2,7 +2,7 @@
name: ShopChest name: ShopChest
main: de.epiceric.shopchest.ShopChest main: de.epiceric.shopchest.ShopChest
version: 1.5.0 version: 1.5.1
author: EpicEric author: EpicEric
website: https://www.spigotmc.org/resources/shopchest.11431/ website: https://www.spigotmc.org/resources/shopchest.11431/
depend: [Vault] depend: [Vault]

View File

@ -1,16 +1,22 @@
package de.epiceric.shopchest; package de.epiceric.shopchest;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList; import java.nio.file.Files;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.Set;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.OfflinePlayer; import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.command.defaults.BukkitCommand; import org.bukkit.command.defaults.BukkitCommand;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.enchantments.Enchantment; import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
@ -28,7 +34,6 @@ import de.epiceric.shopchest.utils.ClickType;
import de.epiceric.shopchest.utils.ClickType.EnumClickType; import de.epiceric.shopchest.utils.ClickType.EnumClickType;
import de.epiceric.shopchest.utils.ShopUtils; import de.epiceric.shopchest.utils.ShopUtils;
import de.epiceric.shopchest.utils.UpdateChecker; import de.epiceric.shopchest.utils.UpdateChecker;
import net.md_5.bungee.api.ChatColor;
import net.milkbowl.vault.permission.Permission; import net.milkbowl.vault.permission.Permission;
public class Commands extends BukkitCommand { public class Commands extends BukkitCommand {
@ -156,6 +161,12 @@ public class Commands extends BukkitCommand {
p.sendMessage(Config.noPermission_limits()); p.sendMessage(Config.noPermission_limits());
} }
} else if (args[0].equalsIgnoreCase("compile")){
if (perm.has(p, "shopchest.compile")) {
compile(p);
}
} else { } else {
sendBasicHelpMessage(p); sendBasicHelpMessage(p);
return true; return true;
@ -175,6 +186,65 @@ public class Commands extends BukkitCommand {
} }
private void compile(Player player) {
player.sendMessage(" ");
player.sendMessage(ChatColor.RED + "" + ChatColor.BOLD + "Starting Compilation...");
player.sendMessage(ChatColor.GOLD + "This command will be removed in the next update. Be sure to compile the shops in this version!");
player.sendMessage(ChatColor.GOLD + "Please execute this command only once or the whole plugin will get messed up and all shops must be deleted!");
File shopChestDataFolder = new File(plugin.getDataFolder(), "data");
if (!shopChestDataFolder.exists()) {
player.sendMessage(ChatColor.RED + "Cannot find shops.yml file.");
player.sendMessage(ChatColor.RED + "Be sure it's located in \"/plugins/ShopChest/data/shops.yml\"");
player.sendMessage(" ");
return;
}
File shopChestsFile = new File(shopChestDataFolder, "shops.yml");
if (!shopChestsFile.exists()) {
player.sendMessage(ChatColor.RED + "Cannot find shops.yml file.");
player.sendMessage(ChatColor.RED + "Be sure it's located in \"/plugins/ShopChest/data/shops.yml\"");
player.sendMessage(" ");
return;
}
YamlConfiguration shopChests = YamlConfiguration.loadConfiguration(shopChestsFile);
Set<String> keys = shopChests.getKeys(false);
for (String key : keys) {
OfflinePlayer vendor = shopChests.getOfflinePlayer(key + ".vendor");
int locationX = shopChests.getInt(key + ".location.x");
int locationY = shopChests.getInt(key + ".location.y");
int locationZ = shopChests.getInt(key + ".location.z");
World locationWorld = plugin.getServer().getWorld(shopChests.getString(key + ".location.world"));
Location location = new Location(locationWorld, locationX, locationY, locationZ);
ItemStack product = shopChests.getItemStack(key + ".product");
double buyPrice = shopChests.getDouble(key + ".price.buy");
double sellPrice = shopChests.getDouble(key + ".price.sell");
boolean infinite = shopChests.getBoolean(key + ".infinite");
ShopChest.sqlite.addShop(new Shop(plugin, vendor, product, location, buyPrice, sellPrice, infinite));
}
player.sendMessage(ChatColor.GREEN + "Successfully compiled " + String.valueOf(keys.size()) + " Shops.");
try {
Files.delete(shopChestsFile.toPath());
Files.delete(shopChestDataFolder.toPath());
player.sendMessage(ChatColor.GREEN + "Successfully deleted data folder.");
} catch (IOException e) {
player.sendMessage(ChatColor.RED + "Could not delete data folder. You may delete it yourself.");
}
player.sendMessage(" ");
}
private void checkUpdates(Player player) { private void checkUpdates(Player player) {
player.sendMessage(Config.checking_update()); player.sendMessage(Config.checking_update());
@ -205,8 +275,7 @@ public class Commands extends BukkitCommand {
private void reload(Player player) { private void reload(Player player) {
ShopChest.utils.reload(); ShopChest.utils.reload(player);
player.sendMessage(Config.reloaded_shops(ShopChest.getInstance().shopChests.getKeys(false).size()));
} }

View File

@ -5,22 +5,16 @@ import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.sql.Statement;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.logging.Logger; import java.util.logging.Logger;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.RegisteredServiceProvider; import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import org.yi.acru.bukkit.Lockette.Lockette;
import com.griefcraft.lwc.LWC; import com.griefcraft.lwc.LWC;
import com.griefcraft.lwc.LWCPlugin; import com.griefcraft.lwc.LWCPlugin;
@ -36,6 +30,7 @@ import de.epiceric.shopchest.interfaces.utils.Utils_R1;
import de.epiceric.shopchest.interfaces.utils.Utils_R2; import de.epiceric.shopchest.interfaces.utils.Utils_R2;
import de.epiceric.shopchest.interfaces.utils.Utils_R3; import de.epiceric.shopchest.interfaces.utils.Utils_R3;
import de.epiceric.shopchest.shop.Shop; import de.epiceric.shopchest.shop.Shop;
import de.epiceric.shopchest.sql.SQLite;
import de.epiceric.shopchest.interfaces.JsonBuilder; import de.epiceric.shopchest.interfaces.JsonBuilder;
import de.epiceric.shopchest.interfaces.JsonBuilder.ClickAction; import de.epiceric.shopchest.interfaces.JsonBuilder.ClickAction;
import de.epiceric.shopchest.interfaces.JsonBuilder.HoverAction; import de.epiceric.shopchest.interfaces.JsonBuilder.HoverAction;
@ -52,14 +47,13 @@ public class ShopChest extends JavaPlugin{
private static ShopChest instance; private static ShopChest instance;
public File shopChestsFile; public static Statement statement;
public YamlConfiguration shopChests; public static Logger logger;
public static Logger logger = Logger.getLogger("Minecraft");
public static Economy econ = null; public static Economy econ = null;
public static Permission perm = null; public static Permission perm = null;
public static LWC lwc = null; public static LWC lwc = null;
public static boolean lockette = false; public static boolean lockette = false;
public static SQLite sqlite;
public static boolean isUpdateNeeded = false; public static boolean isUpdateNeeded = false;
public static String latestVersion = ""; public static String latestVersion = "";
@ -92,14 +86,16 @@ public class ShopChest extends JavaPlugin{
@Override @Override
public void onEnable() { public void onEnable() {
logger = getLogger();
if (getServer().getPluginManager().getPlugin("Vault") == null) { if (getServer().getPluginManager().getPlugin("Vault") == null) {
logger.severe("[ShopChest] Could not find plugin 'Vault'!"); logger.severe("Could not find plugin 'Vault'!");
getServer().getPluginManager().disablePlugin(this); getServer().getPluginManager().disablePlugin(this);
return; return;
} }
if (!setupEconomy() ) { if (!setupEconomy() ) {
logger.severe("[ShopChest] Could not find any Vault dependency!"); logger.severe("Could not find any Vault dependency!");
getServer().getPluginManager().disablePlugin(this); getServer().getPluginManager().disablePlugin(this);
return; return;
} }
@ -108,16 +104,19 @@ public class ShopChest extends JavaPlugin{
Metrics metrics = new Metrics(this); Metrics metrics = new Metrics(this);
metrics.start(); metrics.start();
} catch (IOException e) { } catch (IOException e) {
logger.severe("[ShopChest] [PluginMetrics] Could not submit stats."); logger.severe("Could not submit stats.");
} }
sqlite = new SQLite(this);
sqlite.load();
switch (Utils.getVersion(getServer())) { switch (Utils.getVersion(getServer())) {
case "v1_8_R1": utils = new Utils_R1(); break; case "v1_8_R1": utils = new Utils_R1(); break;
case "v1_8_R2": utils = new Utils_R2(); break; case "v1_8_R2": utils = new Utils_R2(); break;
case "v1_8_R3": utils = new Utils_R3(); break; case "v1_8_R3": utils = new Utils_R3(); break;
default: default:
logger.severe("[ShopChest] Incompatible Server Version!"); logger.severe("Incompatible Server Version!");
getServer().getPluginManager().disablePlugin(this); getServer().getPluginManager().disablePlugin(this);
return; return;
} }
@ -142,14 +141,14 @@ public class ShopChest extends JavaPlugin{
saveDefaultConfig(); saveDefaultConfig();
UpdateChecker uc = new UpdateChecker(this, getDescription().getWebsite()); UpdateChecker uc = new UpdateChecker(this, getDescription().getWebsite());
logger.info("[ShopChest] Checking for Updates"); logger.info("Checking for Updates");
if(uc.updateNeeded()) { if(uc.updateNeeded()) {
latestVersion = uc.getVersion(); latestVersion = uc.getVersion();
downloadLink = uc.getLink(); downloadLink = uc.getLink();
isUpdateNeeded = true; isUpdateNeeded = true;
Bukkit.getConsoleSender().sendMessage("[ShopChest] " + ChatColor.GOLD + "New version available: " + ChatColor.RED + latestVersion); Bukkit.getConsoleSender().sendMessage("[ShopChest] " + ChatColor.GOLD + "New version available: " + ChatColor.RED + latestVersion);
} else { } else {
logger.info("[ShopChest] No new version available"); logger.info("No new version available");
isUpdateNeeded = false; isUpdateNeeded = false;
} }
@ -167,15 +166,7 @@ public class ShopChest extends JavaPlugin{
} }
} }
} }
File shopChestDataFolder = new File(getDataFolder(), "data");
shopChestDataFolder.mkdirs();
shopChestsFile = new File(getDataFolder(), "/data/shops.yml");
if (!shopChestsFile.exists())
try {shopChestsFile.createNewFile();} catch (IOException e) {e.printStackTrace();}
File itemNamesFile = new File(getDataFolder(), "item_names.txt"); File itemNamesFile = new File(getDataFolder(), "item_names.txt");
@ -183,9 +174,7 @@ public class ShopChest extends JavaPlugin{
try {itemNamesFile.createNewFile();} catch (IOException e) {e.printStackTrace();} try {itemNamesFile.createNewFile();} catch (IOException e) {e.printStackTrace();}
copy(getResource("item_names.txt"), itemNamesFile); copy(getResource("item_names.txt"), itemNamesFile);
shopChests = YamlConfiguration.loadConfiguration(shopChestsFile);
try { try {
Commands.registerCommand(new Commands(this, Config.main_command_name(), "Manage Shops.", "", new ArrayList<String>()), this); Commands.registerCommand(new Commands(this, Config.main_command_name(), "Manage Shops.", "", new ArrayList<String>()), this);
@ -214,26 +203,26 @@ public class ShopChest extends JavaPlugin{
} }
private void initializeShops() { private void initializeShops() {
int count = 0;
Bukkit.getConsoleSender().sendMessage("[ShopChest] Found " + String.valueOf(shopChests.getKeys(false).size()) + " Shops"); for (int id = 1; id < sqlite.getCount() + 1; id++) {
for (String key : shopChests.getKeys(false)) {
OfflinePlayer vendor = shopChests.getOfflinePlayer(key + ".vendor"); try {
int locationX = shopChests.getInt(key + ".location.x"); Shop shop = sqlite.getShop(id);
int locationY = shopChests.getInt(key + ".location.y"); shop.createHologram();
int locationZ = shopChests.getInt(key + ".location.z"); shop.createItem();
World locationWorld = getServer().getWorld(shopChests.getString(key + ".location.world")); ShopUtils.addShop(shop);
Location location = new Location(locationWorld, locationX, locationY, locationZ); } catch (NullPointerException e) {
ItemStack product = shopChests.getItemStack(key + ".product"); continue;
double buyPrice = shopChests.getDouble(key + ".price.buy"); }
double sellPrice = shopChests.getDouble(key + ".price.sell");
boolean infinite = shopChests.getBoolean(key + ".infinite");
ShopUtils.addShop(new Shop(this, vendor, product, location, buyPrice, sellPrice, infinite)); count++;
} }
logger.info("Initialized " + String.valueOf(count) + " Shops");
} }
public static void copy(InputStream in, File file) { public static void copy(InputStream in, File file) {

View File

@ -15,7 +15,7 @@ public class Config {
public static boolean buy_greater_or_equal_sell() {return plugin.getConfig().getBoolean("buy-greater-or-equal-sell");} public static boolean buy_greater_or_equal_sell() {return plugin.getConfig().getBoolean("buy-greater-or-equal-sell");}
public static double maximal_distance() {return plugin.getConfig().getDouble("maximal-distance");} public static double maximal_distance() {return plugin.getConfig().getDouble("maximal-distance");}
public static int default_limit() {return plugin.getConfig().getInt("shop-limits.default");} public static int default_limit() {return plugin.getConfig().getInt("shop-limits.default");}
public static String main_command_name() { return plugin.getConfig().getString("main-command-name");} public static String main_command_name() { return plugin.getConfig().getString("main-command-name");}
public static String currency_symbol() { return plugin.getConfig().getString("currency-symbol").replaceAll("(&([a-f0-9k-or]))", "\u00A7$2");} public static String currency_symbol() { return plugin.getConfig().getString("currency-symbol").replaceAll("(&([a-f0-9k-or]))", "\u00A7$2");}

View File

@ -1,6 +1,5 @@
package de.epiceric.shopchest.event; package de.epiceric.shopchest.event;
import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -9,11 +8,9 @@ import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.Chest; import org.bukkit.block.Chest;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.enchantments.Enchantment; import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.block.Action; import org.bukkit.event.block.Action;
import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerInteractEvent;
@ -22,18 +19,17 @@ import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.yi.acru.bukkit.Lockette.Lockette; import org.yi.acru.bukkit.Lockette.Lockette;
import com.griefcraft.lwc.LWC;
import com.griefcraft.model.Protection; import com.griefcraft.model.Protection;
import de.epiceric.shopchest.ShopChest; import de.epiceric.shopchest.ShopChest;
import de.epiceric.shopchest.config.Config; import de.epiceric.shopchest.config.Config;
import de.epiceric.shopchest.shop.Shop; import de.epiceric.shopchest.shop.Shop;
import de.epiceric.shopchest.sql.SQLite;
import de.epiceric.shopchest.utils.ClickType; import de.epiceric.shopchest.utils.ClickType;
import de.epiceric.shopchest.utils.EnchantmentNames; import de.epiceric.shopchest.utils.EnchantmentNames;
import de.epiceric.shopchest.utils.ItemNames; import de.epiceric.shopchest.utils.ItemNames;
import de.epiceric.shopchest.utils.ShopUtils; import de.epiceric.shopchest.utils.ShopUtils;
import de.epiceric.shopchest.interfaces.Utils; import de.epiceric.shopchest.interfaces.Utils;
import net.md_5.bungee.api.ChatColor;
import net.milkbowl.vault.economy.Economy; import net.milkbowl.vault.economy.Economy;
import net.milkbowl.vault.economy.EconomyResponse; import net.milkbowl.vault.economy.EconomyResponse;
import net.milkbowl.vault.permission.Permission; import net.milkbowl.vault.permission.Permission;
@ -43,11 +39,10 @@ public class InteractShop implements Listener{
private ShopChest plugin; private ShopChest plugin;
private Permission perm = ShopChest.perm; private Permission perm = ShopChest.perm;
private Economy econ = ShopChest.econ; private Economy econ = ShopChest.econ;
private YamlConfiguration shopChests; private SQLite sqlite = ShopChest.sqlite;
public InteractShop(ShopChest plugin) { public InteractShop(ShopChest plugin) {
this.plugin = plugin; this.plugin = plugin;
shopChests = plugin.shopChests;
} }
@EventHandler @EventHandler
@ -231,18 +226,10 @@ public class InteractShop implements Listener{
private void create(Player executor, Location location, ItemStack product, double buyPrice, double sellPrice, boolean infinite) { private void create(Player executor, Location location, ItemStack product, double buyPrice, double sellPrice, boolean infinite) {
Shop shop = new Shop(plugin, executor, product, location, buyPrice, sellPrice, infinite); Shop shop = new Shop(plugin, executor, product, location, buyPrice, sellPrice, infinite);
shop.createHologram();
shop.createItem();
shopChests.set(ShopUtils.getConfigTitle(location) + ".vendor", executor); sqlite.addShop(shop);
shopChests.set(ShopUtils.getConfigTitle(location) + ".location.world", location.getWorld().getName());
shopChests.set(ShopUtils.getConfigTitle(location) + ".location.x", location.getBlockX());
shopChests.set(ShopUtils.getConfigTitle(location) + ".location.y", location.getBlockY());
shopChests.set(ShopUtils.getConfigTitle(location) + ".location.z", location.getBlockZ());
shopChests.set(ShopUtils.getConfigTitle(location) + ".product", product);
shopChests.set(ShopUtils.getConfigTitle(location) + ".price.buy", buyPrice);
shopChests.set(ShopUtils.getConfigTitle(location) + ".price.sell", sellPrice);
shopChests.set(ShopUtils.getConfigTitle(location) + ".infinite", infinite);
try {shopChests.save(plugin.shopChestsFile);} catch (IOException ex) {ex.printStackTrace();}
ShopUtils.addShop(shop); ShopUtils.addShop(shop);
executor.sendMessage(Config.shop_created()); executor.sendMessage(Config.shop_created());
@ -255,12 +242,10 @@ public class InteractShop implements Listener{
private void remove(Player executor, Shop shop) { private void remove(Player executor, Shop shop) {
shop.getItem().remove();
ShopUtils.removeShop(shop); ShopUtils.removeShop(shop);
shopChests.set(ShopUtils.getConfigTitle(shop.getLocation()), null); sqlite.removeShop(shop);
try {shopChests.save(plugin.shopChestsFile);} catch (IOException ex) {ex.printStackTrace();}
for (Player player : plugin.getServer().getOnlinePlayers()) { for (Player player : plugin.getServer().getOnlinePlayers()) {
shop.getHologram().hidePlayer(player); shop.getHologram().hidePlayer(player);
} }

View File

@ -19,7 +19,7 @@ public class RegenerateShopItemAfterRemove implements Listener {
} }
} }
if (containsShopItem) ShopChest.utils.reload(); if (containsShopItem) ShopChest.utils.reload(null);
} }

View File

@ -1,14 +1,17 @@
package de.epiceric.shopchest.interfaces; package de.epiceric.shopchest.interfaces;
import org.apache.commons.codec.binary.Base64;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.Server; import org.bukkit.Server;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory; import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.ItemMeta;
public abstract class Utils { public abstract class Utils {
public abstract void reload(); public abstract void reload(Player p);
public abstract void removeShops(); public abstract void removeShops();
@ -33,4 +36,29 @@ public abstract class Utils {
return string.matches("[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[34][0-9a-fA-F]{3}-[89ab][0-9a-fA-F]{3}-[0-9a-fA-F]{12}"); return string.matches("[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[34][0-9a-fA-F]{3}-[89ab][0-9a-fA-F]{3}-[0-9a-fA-F]{12}");
} }
public static String encode(ItemStack itemStack) {
YamlConfiguration config = new YamlConfiguration();
config.set("i", itemStack);
return new String(Base64.encodeBase64(config.saveToString().getBytes()));
}
public static String toString(ItemStack itemStack) {
YamlConfiguration config = new YamlConfiguration();
config.set("i", itemStack);
return config.saveToString();
}
public static ItemStack decode(String string) {
YamlConfiguration config = new YamlConfiguration();
try {
config.loadFromString(new String(Base64.decodeBase64(string.getBytes())));
} catch (Exception e) {
e.printStackTrace();
return null;
}
return config.getItemStack("i", null);
}
} }

View File

@ -1,13 +1,10 @@
package de.epiceric.shopchest.interfaces.utils; package de.epiceric.shopchest.interfaces.utils;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerMoveEvent; import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.inventory.ItemStack;
import de.epiceric.shopchest.ShopChest; import de.epiceric.shopchest.ShopChest;
import de.epiceric.shopchest.config.Config;
import de.epiceric.shopchest.interfaces.Utils; import de.epiceric.shopchest.interfaces.Utils;
import de.epiceric.shopchest.interfaces.Hologram; import de.epiceric.shopchest.interfaces.Hologram;
import de.epiceric.shopchest.shop.Shop; import de.epiceric.shopchest.shop.Shop;
@ -17,7 +14,7 @@ import net.minecraft.server.v1_8_R1.EntityArmorStand;
public class Utils_R1 extends Utils { public class Utils_R1 extends Utils {
@Override @Override
public void reload() { public void reload(Player player) {
for (Shop shop : ShopUtils.getShops()) { for (Shop shop : ShopUtils.getShops()) {
Hologram hologram = shop.getHologram(); Hologram hologram = shop.getHologram();
@ -37,23 +34,25 @@ public class Utils_R1 extends Utils {
} }
for (String key : ShopChest.getInstance().shopChests.getKeys(false)) { int count = 0;
for (int id = 1; id < ShopChest.sqlite.getCount() + 1; id++) {
OfflinePlayer vendor = ShopChest.getInstance().shopChests.getOfflinePlayer(key + ".vendor"); try {
int locationX = ShopChest.getInstance().shopChests.getInt(key + ".location.x"); Shop shop = ShopChest.sqlite.getShop(id);
int locationY = ShopChest.getInstance().shopChests.getInt(key + ".location.y"); shop.createHologram();
int locationZ = ShopChest.getInstance().shopChests.getInt(key + ".location.z"); shop.createItem();
World locationWorld = ShopChest.getInstance().getServer().getWorld(ShopChest.getInstance().shopChests.getString(key + ".location.world")); ShopUtils.addShop(shop);
Location location = new Location(locationWorld, locationX, locationY, locationZ); } catch (NullPointerException e) {
ItemStack product = ShopChest.getInstance().shopChests.getItemStack(key + ".product"); continue;
double buyPrice = ShopChest.getInstance().shopChests.getDouble(key + ".price.buy"); }
double sellPrice = ShopChest.getInstance().shopChests.getDouble(key + ".price.sell");
boolean infinite = ShopChest.getInstance().shopChests.getBoolean(key + ".infinite");
ShopUtils.addShop(new Shop(ShopChest.getInstance(), vendor, product, location, buyPrice, sellPrice, infinite)); count++;
} }
if (player != null) player.sendMessage(Config.reloaded_shops(count));
for (Player p : Bukkit.getOnlinePlayers()) { for (Player p : Bukkit.getOnlinePlayers()) {
Bukkit.getPluginManager().callEvent(new PlayerMoveEvent(p, p.getLocation(), p.getLocation())); Bukkit.getPluginManager().callEvent(new PlayerMoveEvent(p, p.getLocation(), p.getLocation()));
} }

View File

@ -1,15 +1,13 @@
package de.epiceric.shopchest.interfaces.utils; package de.epiceric.shopchest.interfaces.utils;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerMoveEvent; import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.inventory.ItemStack;
import de.epiceric.shopchest.ShopChest; import de.epiceric.shopchest.ShopChest;
import de.epiceric.shopchest.interfaces.Utils; import de.epiceric.shopchest.config.Config;
import de.epiceric.shopchest.interfaces.Hologram; import de.epiceric.shopchest.interfaces.Hologram;
import de.epiceric.shopchest.interfaces.Utils;
import de.epiceric.shopchest.shop.Shop; import de.epiceric.shopchest.shop.Shop;
import de.epiceric.shopchest.utils.ShopUtils; import de.epiceric.shopchest.utils.ShopUtils;
import net.minecraft.server.v1_8_R2.EntityArmorStand; import net.minecraft.server.v1_8_R2.EntityArmorStand;
@ -17,7 +15,7 @@ import net.minecraft.server.v1_8_R2.EntityArmorStand;
public class Utils_R2 extends Utils { public class Utils_R2 extends Utils {
@Override @Override
public void reload() { public void reload(Player player) {
for (Shop shop : ShopUtils.getShops()) { for (Shop shop : ShopUtils.getShops()) {
Hologram hologram = shop.getHologram(); Hologram hologram = shop.getHologram();
@ -37,23 +35,25 @@ public class Utils_R2 extends Utils {
} }
for (String key : ShopChest.getInstance().shopChests.getKeys(false)) { int count = 0;
for (int id = 1; id < ShopChest.sqlite.getCount() + 1; id++) {
OfflinePlayer vendor = ShopChest.getInstance().shopChests.getOfflinePlayer(key + ".vendor"); try {
int locationX = ShopChest.getInstance().shopChests.getInt(key + ".location.x"); Shop shop = ShopChest.sqlite.getShop(id);
int locationY = ShopChest.getInstance().shopChests.getInt(key + ".location.y"); shop.createHologram();
int locationZ = ShopChest.getInstance().shopChests.getInt(key + ".location.z"); shop.createItem();
World locationWorld = ShopChest.getInstance().getServer().getWorld(ShopChest.getInstance().shopChests.getString(key + ".location.world")); ShopUtils.addShop(shop);
Location location = new Location(locationWorld, locationX, locationY, locationZ); } catch (NullPointerException e) {
ItemStack product = ShopChest.getInstance().shopChests.getItemStack(key + ".product"); continue;
double buyPrice = ShopChest.getInstance().shopChests.getDouble(key + ".price.buy"); }
double sellPrice = ShopChest.getInstance().shopChests.getDouble(key + ".price.sell");
boolean infinite = ShopChest.getInstance().shopChests.getBoolean(key + ".infinite");
ShopUtils.addShop(new Shop(ShopChest.getInstance(), vendor, product, location, buyPrice, sellPrice, infinite)); count++;
} }
if (player != null) player.sendMessage(Config.reloaded_shops(count));
for (Player p : Bukkit.getOnlinePlayers()) { for (Player p : Bukkit.getOnlinePlayers()) {
Bukkit.getPluginManager().callEvent(new PlayerMoveEvent(p, p.getLocation(), p.getLocation())); Bukkit.getPluginManager().callEvent(new PlayerMoveEvent(p, p.getLocation(), p.getLocation()));
} }

View File

@ -1,13 +1,10 @@
package de.epiceric.shopchest.interfaces.utils; package de.epiceric.shopchest.interfaces.utils;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerMoveEvent; import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.inventory.ItemStack;
import de.epiceric.shopchest.ShopChest; import de.epiceric.shopchest.ShopChest;
import de.epiceric.shopchest.config.Config;
import de.epiceric.shopchest.interfaces.Utils; import de.epiceric.shopchest.interfaces.Utils;
import de.epiceric.shopchest.interfaces.Hologram; import de.epiceric.shopchest.interfaces.Hologram;
import de.epiceric.shopchest.shop.Shop; import de.epiceric.shopchest.shop.Shop;
@ -17,7 +14,7 @@ import net.minecraft.server.v1_8_R3.EntityArmorStand;
public class Utils_R3 extends Utils { public class Utils_R3 extends Utils {
@Override @Override
public void reload() { public void reload(Player player) {
for (Shop shop : ShopUtils.getShops()) { for (Shop shop : ShopUtils.getShops()) {
Hologram hologram = shop.getHologram(); Hologram hologram = shop.getHologram();
@ -37,23 +34,25 @@ public class Utils_R3 extends Utils {
} }
for (String key : ShopChest.getInstance().shopChests.getKeys(false)) { int count = 0;
for (int id = 1; id < ShopChest.sqlite.getCount() + 1; id++) {
OfflinePlayer vendor = ShopChest.getInstance().shopChests.getOfflinePlayer(key + ".vendor"); try {
int locationX = ShopChest.getInstance().shopChests.getInt(key + ".location.x"); Shop shop = ShopChest.sqlite.getShop(id);
int locationY = ShopChest.getInstance().shopChests.getInt(key + ".location.y"); shop.createHologram();
int locationZ = ShopChest.getInstance().shopChests.getInt(key + ".location.z"); shop.createItem();
World locationWorld = ShopChest.getInstance().getServer().getWorld(ShopChest.getInstance().shopChests.getString(key + ".location.world")); ShopUtils.addShop(shop);
Location location = new Location(locationWorld, locationX, locationY, locationZ); } catch (NullPointerException e) {
ItemStack product = ShopChest.getInstance().shopChests.getItemStack(key + ".product"); continue;
double buyPrice = ShopChest.getInstance().shopChests.getDouble(key + ".price.buy"); }
double sellPrice = ShopChest.getInstance().shopChests.getDouble(key + ".price.sell");
boolean infinite = ShopChest.getInstance().shopChests.getBoolean(key + ".infinite");
ShopUtils.addShop(new Shop(ShopChest.getInstance(), vendor, product, location, buyPrice, sellPrice, infinite)); count++;
} }
if (player != null) player.sendMessage(Config.reloaded_shops(count));
for (Player p : Bukkit.getOnlinePlayers()) { for (Player p : Bukkit.getOnlinePlayers()) {
Bukkit.getPluginManager().callEvent(new PlayerMoveEvent(p, p.getLocation(), p.getLocation())); Bukkit.getPluginManager().callEvent(new PlayerMoveEvent(p, p.getLocation(), p.getLocation()));
} }

View File

@ -45,11 +45,9 @@ public class Shop {
this.buyPrice = buyPrice; this.buyPrice = buyPrice;
this.sellPrice = sellPrice; this.sellPrice = sellPrice;
this.infinite = infinite; this.infinite = infinite;
this.hologram = createHologram(product, location, buyPrice, sellPrice);
this.item = createItem(product, location);
} }
public Item createItem(ItemStack product, Location location) { public void createItem() {
Item item; Item item;
Location itemLocation; Location itemLocation;
@ -70,19 +68,16 @@ public class Shop {
item.setVelocity(new Vector(0, 0, 0)); item.setVelocity(new Vector(0, 0, 0));
item.setMetadata("shopItem", new FixedMetadataValue(plugin, true)); item.setMetadata("shopItem", new FixedMetadataValue(plugin, true));
return item; this.item = item;
} }
public Hologram createHologram(ItemStack product, Location shopLocation, double buyPrice, double sellPrice) { public void createHologram() {
boolean doubleChest; boolean doubleChest;
Hologram hologram;
Chest[] chests = new Chest[2]; Chest[] chests = new Chest[2];
Block b = shopLocation.getBlock(); Block b = location.getBlock();
if (b.getType().equals(Material.CHEST) || b.getType().equals(Material.TRAPPED_CHEST)) { if (b.getType().equals(Material.CHEST) || b.getType().equals(Material.TRAPPED_CHEST)) {
@ -106,7 +101,7 @@ public class Shop {
} }
} else { } else {
return null; return;
} }
Location holoLocation; Location holoLocation;
@ -145,11 +140,9 @@ public class Shop {
case "v1_8_R1": hologram = new Hologram_R1(holoText, holoLocation); break; case "v1_8_R1": hologram = new Hologram_R1(holoText, holoLocation); break;
case "v1_8_R2": hologram = new Hologram_R2(holoText, holoLocation); break; case "v1_8_R2": hologram = new Hologram_R2(holoText, holoLocation); break;
case "v1_8_R3": hologram = new Hologram_R3(holoText, holoLocation); break; case "v1_8_R3": hologram = new Hologram_R3(holoText, holoLocation); break;
default: return null; default: return;
} }
return hologram;
} }
public OfflinePlayer getVendor() { public OfflinePlayer getVendor() {

View File

@ -0,0 +1,487 @@
package de.epiceric.shopchest.sql;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.UUID;
import java.util.logging.Level;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import org.bukkit.inventory.ItemStack;
import de.epiceric.shopchest.ShopChest;
import de.epiceric.shopchest.interfaces.Utils;
import de.epiceric.shopchest.shop.Shop;
import de.epiceric.shopchest.utils.ShopUtils;
public abstract class Database {
ShopChest plugin;
Connection connection;
// The name of the table we created back in SQLite class.
public String table = "shop_list";
public String world = "";
public String vendor = "";
public ItemStack product = null;
public Location location = null;
public double buyPrice = 0;
public double sellPrice = 0;
public boolean infinite = false;
public Database(ShopChest instance){
plugin = instance;
}
public abstract Connection getSQLConnection();
public abstract void load();
public void initialize(){
connection = getSQLConnection();
try{
PreparedStatement ps = connection.prepareStatement("SELECT * FROM " + table + " WHERE id = ?");
ResultSet rs = ps.executeQuery();
close(ps,rs);
} catch (SQLException ex) {
plugin.getLogger().log(Level.SEVERE, "Unable to retreive connection", ex);
}
}
public int getNextFreeID() {
for (int i = 1; i <= getCount(); i++) {
if (getProduct(i) == null) {
return i;
} else {
if (i == getCount()) {
return i + 1;
}
}
}
return 0;
}
public int getCount() {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
int highestID = 0;
try {
conn = getSQLConnection();
ps = conn.prepareStatement("SELECT * FROM " + table + ";");
rs = ps.executeQuery();
while(rs.next()){
if(rs.getInt("id") > highestID) {
highestID = rs.getInt("id");
}
}
return highestID;
} catch (SQLException ex) {
plugin.getLogger().log(Level.SEVERE, Errors.sqlConnectionExecute(), ex);
} finally {
try {
if (ps != null)
ps.close();
if (conn != null)
conn.close();
} catch (SQLException ex) {
plugin.getLogger().log(Level.SEVERE, Errors.sqlConnectionClose(), ex);
}
}
return -1;
}
public int getShopID(Shop shop) {
for (int i = 1; i < getCount() + 1; i++) {
try {
Shop s = getShop(i);
if (s.getLocation().equals(shop.getLocation())) {
return i;
}
} catch (NullPointerException ex) {
continue;
}
}
return 0;
}
public void removeShop(Shop shop) {
int id = getShopID(shop);
if (id == 0) return;
shop.getItem().remove();
Connection conn = null;
PreparedStatement ps = null;
try {
conn = getSQLConnection();
ps = conn.prepareStatement("DELETE FROM " + table + " where id = " + id + ";");
} catch (SQLException ex) {
plugin.getLogger().log(Level.SEVERE, Errors.sqlConnectionExecute(), ex);
} finally {
try {
if (ps != null)
ps.close();
if (conn != null)
conn.close();
} catch (SQLException ex) {
plugin.getLogger().log(Level.SEVERE, Errors.sqlConnectionClose(), ex);
}
}
}
public void removeShop(int id) {
if (id == 0) return;
removeShop(getShop(id));
}
private World getWorld(int id) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = getSQLConnection();
ps = conn.prepareStatement("SELECT * FROM " + table + " WHERE id = " + id + ";");
rs = ps.executeQuery();
while(rs.next()){
if(rs.getInt("id") == id) {
return Bukkit.getWorld(rs.getString("world"));
}
}
} catch (SQLException ex) {
plugin.getLogger().log(Level.SEVERE, Errors.sqlConnectionExecute(), ex);
} finally {
try {
if (ps != null)
ps.close();
if (conn != null)
conn.close();
} catch (SQLException ex) {
plugin.getLogger().log(Level.SEVERE, Errors.sqlConnectionClose(), ex);
}
}
return null;
}
@SuppressWarnings("deprecation")
public OfflinePlayer getVendor(int id) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = getSQLConnection();
ps = conn.prepareStatement("SELECT * FROM " + table + " WHERE id = " + id + ";");
rs = ps.executeQuery();
while(rs.next()){
if(rs.getInt("id") == id){
return (Utils.isUUID(rs.getString("vendor"))) ? Bukkit.getOfflinePlayer(UUID.fromString(rs.getString("vendor"))) : Bukkit.getOfflinePlayer(rs.getString("vendor"));
}
}
} catch (SQLException ex) {
plugin.getLogger().log(Level.SEVERE, Errors.sqlConnectionExecute(), ex);
} finally {
try {
if (ps != null)
ps.close();
if (conn != null)
conn.close();
} catch (SQLException ex) {
plugin.getLogger().log(Level.SEVERE, Errors.sqlConnectionClose(), ex);
}
}
return null;
}
public ItemStack getProduct(int id) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = getSQLConnection();
ps = conn.prepareStatement("SELECT * FROM " + table + " WHERE id = " + id + ";");
rs = ps.executeQuery();
while(rs.next()){
if(rs.getInt("id") == id){
return Utils.decode(rs.getString("product"));
}
}
} catch (SQLException ex) {
plugin.getLogger().log(Level.SEVERE, Errors.sqlConnectionExecute(), ex);
} finally {
try {
if (ps != null)
ps.close();
if (conn != null)
conn.close();
} catch (SQLException ex) {
plugin.getLogger().log(Level.SEVERE, Errors.sqlConnectionClose(), ex);
}
}
return null;
}
private int getX(int id) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = getSQLConnection();
ps = conn.prepareStatement("SELECT * FROM " + table + " WHERE id = " + id + ";");
rs = ps.executeQuery();
while(rs.next()){
if(rs.getInt("id") == id){
return rs.getInt("x");
}
}
} catch (SQLException ex) {
plugin.getLogger().log(Level.SEVERE, Errors.sqlConnectionExecute(), ex);
} finally {
try {
if (ps != null)
ps.close();
if (conn != null)
conn.close();
} catch (SQLException ex) {
plugin.getLogger().log(Level.SEVERE, Errors.sqlConnectionClose(), ex);
}
}
return 0;
}
private int getY(int id) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = getSQLConnection();
ps = conn.prepareStatement("SELECT * FROM " + table + " WHERE id = " + id + ";");
rs = ps.executeQuery();
while(rs.next()){
if(rs.getInt("id") == id){
return rs.getInt("y");
}
}
} catch (SQLException ex) {
plugin.getLogger().log(Level.SEVERE, Errors.sqlConnectionExecute(), ex);
} finally {
try {
if (ps != null)
ps.close();
if (conn != null)
conn.close();
} catch (SQLException ex) {
plugin.getLogger().log(Level.SEVERE, Errors.sqlConnectionClose(), ex);
}
}
return 0;
}
private int getZ(int id) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = getSQLConnection();
ps = conn.prepareStatement("SELECT * FROM " + table + " WHERE id = " + id + ";");
rs = ps.executeQuery();
while(rs.next()){
if(rs.getInt("id") == id){
return rs.getInt("z");
}
}
} catch (SQLException ex) {
plugin.getLogger().log(Level.SEVERE, Errors.sqlConnectionExecute(), ex);
} finally {
try {
if (ps != null)
ps.close();
if (conn != null)
conn.close();
} catch (SQLException ex) {
plugin.getLogger().log(Level.SEVERE, Errors.sqlConnectionClose(), ex);
}
}
return 0;
}
public Location getLocation(int id) {
return new Location(getWorld(id), getX(id), getY(id), getZ(id));
}
public double getBuyPrice(int id) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = getSQLConnection();
ps = conn.prepareStatement("SELECT * FROM " + table + " WHERE id = " + id + ";");
rs = ps.executeQuery();
while(rs.next()){
if(rs.getInt("id") == id){
return rs.getDouble("buyprice");
}
}
} catch (SQLException ex) {
plugin.getLogger().log(Level.SEVERE, Errors.sqlConnectionExecute(), ex);
} finally {
try {
if (ps != null)
ps.close();
if (conn != null)
conn.close();
} catch (SQLException ex) {
plugin.getLogger().log(Level.SEVERE, Errors.sqlConnectionClose(), ex);
}
}
return 0;
}
public double getSellPrice(int id) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = getSQLConnection();
ps = conn.prepareStatement("SELECT * FROM " + table + " WHERE id = " + id + ";");
rs = ps.executeQuery();
while(rs.next()){
if(rs.getInt("id") == id){
return rs.getDouble("sellprice");
}
}
} catch (SQLException ex) {
plugin.getLogger().log(Level.SEVERE, Errors.sqlConnectionExecute(), ex);
} finally {
try {
if (ps != null)
ps.close();
if (conn != null)
conn.close();
} catch (SQLException ex) {
plugin.getLogger().log(Level.SEVERE, Errors.sqlConnectionClose(), ex);
}
}
return 0;
}
public boolean isInfinite(int id) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = getSQLConnection();
ps = conn.prepareStatement("SELECT * FROM " + table + " WHERE id = " + id + ";");
rs = ps.executeQuery();
while(rs.next()){
if(rs.getInt("id") == id){
return rs.getBoolean("infinite");
}
}
} catch (SQLException ex) {
plugin.getLogger().log(Level.SEVERE, Errors.sqlConnectionExecute(), ex);
} finally {
try {
if (ps != null)
ps.close();
if (conn != null)
conn.close();
} catch (SQLException ex) {
plugin.getLogger().log(Level.SEVERE, Errors.sqlConnectionClose(), ex);
}
}
return false;
}
public Shop getShop(int id) {
OfflinePlayer vendor = getVendor(id);
Location location = getLocation(id);
ItemStack product = getProduct(id);
double buyPrice = getBuyPrice(id);
double sellPrice = getSellPrice(id);
boolean infinite = isInfinite(id);
if (ShopUtils.isShop(location)) return ShopUtils.getShop(location);
else return new Shop(plugin, vendor, product, location, buyPrice, sellPrice, infinite);
}
public void setShop(int id, Shop shop) {
Connection conn = null;
PreparedStatement ps = null;
try {
conn = getSQLConnection();
ps = conn.prepareStatement("REPLACE INTO " + table + " (id,vendor,product,world,x,y,z,buyprice,sellprice,infinite) VALUES(?,?,?,?,?,?,?,?,?,?)");
ps.setInt(1, id);
ps.setString(2, shop.getVendor().getUniqueId().toString());
ps.setString(3, Utils.encode(shop.getProduct()));
ps.setString(4, shop.getLocation().getWorld().getName());
ps.setInt(5, shop.getLocation().getBlockX());
ps.setInt(6, shop.getLocation().getBlockY());
ps.setInt(7, shop.getLocation().getBlockZ());
ps.setDouble(8, shop.getBuyPrice());
ps.setDouble(9, shop.getSellPrice());
ps.setBoolean(10, shop.isInfinite());
ps.executeUpdate();
return;
} catch (SQLException ex) {
plugin.getLogger().log(Level.SEVERE, Errors.sqlConnectionExecute(), ex);
} finally {
try {
if (ps != null)
ps.close();
if (conn != null)
conn.close();
} catch (SQLException ex) {
plugin.getLogger().log(Level.SEVERE, Errors.sqlConnectionClose(), ex);
}
}
return;
}
public void addShop(Shop shop) {
int id = getNextFreeID();
setShop(id, shop);
}
public void close(PreparedStatement ps,ResultSet rs){
try {
if (ps != null)
ps.close();
if (rs != null)
rs.close();
} catch (SQLException ex) {
Error.close(plugin, ex);
}
}
}

View File

@ -0,0 +1,14 @@
package de.epiceric.shopchest.sql;
import java.util.logging.Level;
import de.epiceric.shopchest.ShopChest;
public class Error {
public static void execute(ShopChest plugin, Exception ex){
plugin.getLogger().log(Level.SEVERE, "Couldn't execute MySQL statement: ", ex);
}
public static void close(ShopChest plugin, Exception ex){
plugin.getLogger().log(Level.SEVERE, "Failed to close MySQL connection: ", ex);
}
}

View File

@ -0,0 +1,16 @@
package de.epiceric.shopchest.sql;
public class Errors {
public static String sqlConnectionExecute(){
return "Couldn't execute MySQL statement: ";
}
public static String sqlConnectionClose(){
return "Failed to close MySQL connection: ";
}
public static String noSQLConnection(){
return "Unable to retreive MYSQL connection: ";
}
public static String noTableFound(){
return "Database Error: No Table Found";
}
}

View File

@ -0,0 +1,73 @@
package de.epiceric.shopchest.sql;
import java.io.File;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.logging.Level;
import de.epiceric.shopchest.ShopChest;
public class SQLite extends Database {
String dbname;
public SQLite(ShopChest instance){
super(instance);
dbname = "shops";
}
public String SQLiteCreateTokensTable = "CREATE TABLE IF NOT EXISTS shop_list (" +
"`id` int(11) NOT NULL," +
"`vendor` varchar(32) NOT NULL," +
"`product` varchar(32) NOT NULL," +
"`world` varchar(32) NOT NULL," +
"`x` int(11) NOT NULL," +
"`y` int(11) NOT NULL," +
"`z` int(11) NOT NULL," +
"`buyprice` float(32) NOT NULL," +
"`sellprice` float(32) NOT NULL," +
"`infinite` boolean NOT NULL," +
"PRIMARY KEY (`id`)" +
");";
// SQL creation stuff, You can leave the below stuff untouched.
public Connection getSQLConnection() {
File dataFolder = new File(plugin.getDataFolder(), dbname+".db");
if (!dataFolder.exists()){
try {
dataFolder.createNewFile();
} catch (IOException e) {
plugin.getLogger().log(Level.SEVERE, "File write error: "+dbname+".db");
}
}
try {
if(connection!=null&&!connection.isClosed()){
return connection;
}
Class.forName("org.sqlite.JDBC");
connection = DriverManager.getConnection("jdbc:sqlite:" + dataFolder);
return connection;
} catch (SQLException ex) {
plugin.getLogger().log(Level.SEVERE,"SQLite exception on initialize", ex);
} catch (ClassNotFoundException ex) {
plugin.getLogger().log(Level.SEVERE, "You need the SQLite JBDC library. Google it. Put it in /lib folder.");
}
return null;
}
public void load() {
connection = getSQLConnection();
try {
Statement s = connection.createStatement();
s.executeUpdate(SQLiteCreateTokensTable);
s.close();
} catch (SQLException e) {
e.printStackTrace();
}
initialize();
}
}

View File

@ -91,6 +91,7 @@ public class ShopUtils {
Chest r = (Chest) dc.getRightSide(); Chest r = (Chest) dc.getRightSide();
Chest l = (Chest) dc.getLeftSide(); Chest l = (Chest) dc.getLeftSide();
shop.getItem().remove();
shopLocation.remove(r.getLocation()); shopLocation.remove(r.getLocation());
shopLocation.remove(l.getLocation()); shopLocation.remove(l.getLocation());
return; return;