提交 77fe8768 authored 作者: Thomas Mueller's avatar Thomas Mueller

--no commit message

--no commit message
上级 f509ff65
差异被折叠。
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.result;
import java.io.IOException;
import org.h2.value.Transfer;
/**
* @author Thomas
*/
public class ResultColumn {
String alias;
String schemaName;
String tableName;
String columnName;
int columnType;
long precision;
int scale;
int displaySize;
boolean autoIncrement;
int nullable;
ResultColumn(Transfer in) throws IOException {
alias = in.readString();
schemaName = in.readString();
tableName = in.readString();
columnName = in.readString();
columnType = in.readInt();
precision = in.readLong();
scale = in.readInt();
displaySize = in.readInt();
autoIncrement = in.readBoolean();
nullable = in.readInt();
}
public static void writeColumn(Transfer out, ResultInterface result, int i) throws IOException {
out.writeString(result.getAlias(i));
out.writeString(result.getSchemaName(i));
out.writeString(result.getTableName(i));
out.writeString(result.getColumnName(i));
out.writeInt(result.getColumnType(i));
out.writeLong(result.getColumnPrecision(i));
out.writeInt(result.getColumnScale(i));
out.writeInt(result.getDisplaySize(i));
out.writeBoolean(result.isAutoIncrement(i));
out.writeInt(result.getNullable(i));
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.result;
import java.sql.SQLException;
import org.h2.engine.Constants;
import org.h2.engine.Database;
import org.h2.engine.Session;
import org.h2.store.DataPage;
import org.h2.store.FileStore;
import org.h2.util.ObjectArray;
import org.h2.value.Value;
class ResultDiskBuffer {
private static final int READ_AHEAD = 128;
private DataPage rowBuff;
private FileStore file;
private ObjectArray tapes;
private ResultDiskTape mainTape;
private SortOrder sort;
private int columnCount;
public ResultDiskBuffer(Session session, SortOrder sort, int columnCount) throws SQLException {
this.sort = sort;
this.columnCount = columnCount;
Database db = session.getDatabase();
rowBuff = DataPage.create(db, Constants.DEFAULT_DATA_PAGE_SIZE);
String fileName = session.getDatabase().createTempFile();
file = session.getDatabase().openFile(fileName, false);
file.autoDelete();
file.seek(FileStore.HEADER_LENGTH);
if (sort != null) {
tapes = new ObjectArray();
} else {
mainTape = new ResultDiskTape();
mainTape.pos = FileStore.HEADER_LENGTH;
}
}
public void addRows(ObjectArray rows) throws SQLException {
if (sort != null) {
sort.sort(rows);
}
DataPage buff = rowBuff;
long start = file.getFilePointer();
for (int i = 0; i < rows.size(); i++) {
buff.reset();
buff.writeInt(0);
Value[] row = (Value[]) rows.get(i);
for (int j = 0; j < columnCount; j++) {
buff.writeValue(row[j]);
}
buff.fillAligned();
int len = buff.length();
buff.setInt(0, len);
buff.updateChecksum();
file.write(buff.getBytes(), 0, len);
}
if (sort != null) {
ResultDiskTape tape = new ResultDiskTape();
tape.start = start;
tape.end = file.getFilePointer();
tapes.add(tape);
} else {
mainTape.end = file.getFilePointer();
}
}
public void done() throws SQLException {
file.seek(FileStore.HEADER_LENGTH);
}
public void reset() {
if (sort != null) {
for (int i = 0; i < tapes.size(); i++) {
ResultDiskTape tape = getTape(i);
tape.pos = tape.start;
tape.buffer = new ObjectArray();
}
} else {
mainTape.pos = FileStore.HEADER_LENGTH;
}
}
private void readRow(ResultDiskTape tape) throws SQLException {
int min = Constants.FILE_BLOCK_SIZE;
DataPage buff = rowBuff;
buff.reset();
file.readFully(buff.getBytes(), 0, min);
int len = buff.readInt();
buff.checkCapacity(len);
if(len-min > 0) {
file.readFully(buff.getBytes(), min, len - min);
}
buff.check(len);
tape.pos += len;
Value[] row = new Value[columnCount];
for (int k = 0; k < columnCount; k++) {
row[k] = buff.readValue();
}
tape.buffer.add(row);
}
public Value[] next() throws SQLException {
return sort != null ? nextSorted() : nextUnsorted();
}
private Value[] nextUnsorted() throws SQLException {
file.seek(mainTape.pos);
if (mainTape.buffer.size() == 0) {
for (int j = 0; mainTape.pos < mainTape.end && j < READ_AHEAD; j++) {
readRow(mainTape);
}
}
Value[] row = (Value[]) mainTape.buffer.get(0);
mainTape.buffer.remove(0);
return row;
}
private Value[] nextSorted() throws SQLException {
int next = -1;
for (int i = 0; i < tapes.size(); i++) {
ResultDiskTape tape = getTape(i);
if (tape.buffer.size() == 0 && tape.pos < tape.end) {
file.seek(tape.pos);
for (int j = 0; tape.pos < tape.end && j < READ_AHEAD; j++) {
readRow(tape);
}
}
if (tape.buffer.size() > 0) {
if (next == -1) {
next = i;
} else if (compareTapes(tape, getTape(next)) < 0) {
next = i;
}
}
}
ResultDiskTape t = getTape(next);
Value[] row = (Value[]) t.buffer.get(0);
t.buffer.remove(0);
return row;
}
private ResultDiskTape getTape(int i) {
return (ResultDiskTape) tapes.get(i);
}
private int compareTapes(ResultDiskTape a, ResultDiskTape b) throws SQLException {
Value[] va = (Value[]) a.buffer.get(0);
Value[] vb = (Value[]) b.buffer.get(0);
return sort.compare(va, vb);
}
public void finalize() {
if(!Constants.RUN_FINALIZERS) {
return;
}
close();
}
public void close() {
if (file != null) {
file.closeAndDeleteSilently();
file = null;
}
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.result;
import org.h2.util.ObjectArray;
class ResultDiskTape {
long start, end, pos;
ObjectArray buffer = new ObjectArray();
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.result;
import java.sql.SQLException;
import org.h2.value.Value;
public interface ResultInterface {
void reset() throws SQLException;
Value[] currentRow();
boolean next() throws SQLException;
int getRowId();
int getVisibleColumnCount();
int getRowCount();
void close();
String getAlias(int i);
String getSchemaName(int i);
String getTableName(int i);
String getColumnName(int i);
int getColumnType(int i);
long getColumnPrecision(int i);
int getColumnScale(int i);
int getDisplaySize(int i);
boolean isAutoIncrement(int i);
int getNullable(int i);
boolean isUpdateCount();
int getUpdateCount();
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.result;
import java.io.IOException;
import java.sql.SQLException;
import org.h2.engine.Constants;
import org.h2.engine.SessionRemote;
import org.h2.message.Message;
import org.h2.util.ObjectArray;
import org.h2.value.Transfer;
import org.h2.value.Value;
public class ResultRemote implements ResultInterface {
private SessionRemote session;
private Transfer transfer;
private int id;
private ResultColumn[] columns;
private Value[] currentRow;
private int rowId, rowCount;
private ObjectArray result;
private boolean isUpdateCount;
private int updateCount;
public ResultRemote(int updateCount) {
this.isUpdateCount = true;
this.updateCount = updateCount;
}
public boolean isUpdateCount() {
return isUpdateCount;
}
public int getUpdateCount() {
return updateCount;
}
public ResultRemote(SessionRemote session, Transfer transfer, int id, int columnCount, int readRows) throws IOException, SQLException {
this.session = session;
this.transfer = transfer;
this.id = id;
this.columns = new ResultColumn[columnCount];
rowCount = transfer.readInt();
for (int i = 0; i < columnCount; i++) {
columns[i] = new ResultColumn(transfer);
}
rowId = -1;
if(rowCount < readRows) {
result = new ObjectArray();
readFully();
sendClose();
}
}
private void readFully() throws SQLException {
while(true) {
Value[] values = fetchRow(false);
if(values == null) {
break;
}
result.add(values);
}
}
public String getAlias(int i) {
return columns[i].alias;
}
public String getSchemaName(int i) {
return columns[i].schemaName;
}
public String getTableName(int i) {
return columns[i].tableName;
}
public String getColumnName(int i) {
return columns[i].columnName;
}
public int getColumnType(int i) {
return columns[i].columnType;
}
public long getColumnPrecision(int i) {
return columns[i].precision;
}
public int getColumnScale(int i) {
return columns[i].scale;
}
public int getDisplaySize(int i) {
return columns[i].displaySize;
}
public boolean isAutoIncrement(int i) {
return columns[i].autoIncrement;
}
public int getNullable(int i) {
return columns[i].nullable;
}
public void reset() throws SQLException {
rowId = -1;
currentRow = null;
if(session == null) {
return;
}
synchronized (session) {
session.checkClosed();
try {
session.traceOperation("RESULT_RESET", id);
transfer.writeInt(SessionRemote.RESULT_RESET).writeInt(id).flush();
} catch (IOException e) {
throw Message.convert(e);
}
}
}
public Value[] currentRow() {
return currentRow;
}
public boolean next() throws SQLException {
// TODO optimization: don't need rowCount and fetchRow setting
if (rowId < rowCount) {
rowId++;
if (rowId < rowCount) {
if(session == null) {
currentRow = (Value[]) result.get(rowId);
} else {
currentRow = fetchRow(true);
}
return true;
}
currentRow = null;
}
return false;
}
public int getRowId() {
return rowId;
}
public int getVisibleColumnCount() {
return columns.length;
}
public int getRowCount() {
return rowCount;
}
private void sendClose() {
if (session == null) {
return;
}
// TODO result sets: no reset possible for larger remote resultsets
synchronized (session) {
try {
session.traceOperation("RESULT_CLOSE", id);
transfer.writeInt(SessionRemote.RESULT_CLOSE).writeInt(id);
} catch (IOException e) {
session.getTrace().error("close", e);
} finally {
transfer = null;
session = null;
}
}
}
public void close() {
result = null;
sendClose();
}
// public void finalize() {
// if(!Database.RUN_FINALIZERS) {
// return;
// }
// close();
// }
private Value[] fetchRow(boolean sendFetch) throws SQLException {
synchronized (session) {
session.checkClosed();
try {
if(id <= session.getCurrentId() - Constants.SERVER_CACHED_OBJECTS / 2) {
// object is too old - we need to map it to a new id
int newId = session.getNextId();
session.traceOperation("CHANGE_ID", id);
transfer.writeInt(SessionRemote.CHANGE_ID).writeInt(id).writeInt(newId);
id = newId;
// TODO remote result set: very old result sets may be already removed on the server (theoretically) - how to solve this?
}
if(sendFetch) {
session.traceOperation("RESULT_FETCH_ROW", id);
transfer.writeInt(SessionRemote.RESULT_FETCH_ROW).writeInt(id);
session.done(transfer);
}
boolean row = transfer.readBoolean();
if (row) {
int len = columns.length;
Value[] values = new Value[len];
for (int i = 0; i < len; i++) {
values[i] = transfer.readValue();
}
return values;
} else {
sendClose();
return null;
}
} catch (IOException e) {
throw Message.convert(e);
}
}
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.result;
import java.sql.SQLException;
import org.h2.store.DataPage;
import org.h2.store.Record;
import org.h2.value.Value;
/**
* @author Thomas
*/
public class Row extends Record implements SearchRow {
private Value[] data;
public Row(Value[] data) {
this.data = data;
}
public Row(Row old) {
this.data = old.data;
}
public Row() {
// empty constructor
}
public Value getValue(int i) {
return data[i];
}
public void write(DataPage buff) throws SQLException {
buff.writeInt(data.length);
for (int i = 0; i < data.length; i++) {
Value v = data[i];
buff.writeValue(v);
}
}
public int getByteCount(DataPage dummy) throws SQLException {
int len = data.length;
int size = dummy.getIntLen();
for (int i = 0; i < len; i++) {
Value v = data[i];
size += dummy.getValueLen(v);
}
return size;
}
public void setValue(int i, Value v) {
data[i] = v;
}
public boolean isEmpty() {
return data == null;
}
public int getColumnCount() {
return data.length;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.result;
import org.h2.value.Value;
public interface SearchRow {
int getPos();
Value getValue(int index);
int getColumnCount();
void setValue(int idx, Value v);
void setPos(int pos);
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.result;
import org.h2.value.Value;
public class SimpleRow implements SearchRow {
private int pos;
private Value[] data;
public SimpleRow(Value[] data) {
this.data = data;
}
public int getColumnCount() {
return data.length;
}
public int getPos() {
return pos;
}
public void setPos(int pos) {
this.pos = pos;
}
public void setValue(int i, Value v) {
data[i] = v;
}
public Value getValue(int i) {
return data[i];
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.result;
import org.h2.value.Value;
public class SimpleRowValue implements SearchRow {
private int pos;
private int virtualColumnCount;
private Value data;
public SimpleRowValue(int columnCount) {
this.virtualColumnCount = columnCount;
}
public int getColumnCount() {
return virtualColumnCount;
}
public int getPos() {
return pos;
}
public Value getValue(int index) {
return data;
}
public void setPos(int pos) {
this.pos = pos;
}
public void setValue(int idx, Value v) {
data = v;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.result;
import java.sql.SQLException;
import org.h2.engine.Constants;
import org.h2.engine.Database;
import org.h2.expression.Expression;
import org.h2.util.ObjectArray;
import org.h2.util.StringUtils;
import org.h2.value.Value;
import org.h2.value.ValueNull;
/**
* @author Thomas
*/
public class SortOrder {
public static final int ASCENDING = 0, DESCENDING = 1;
public static final int NULLS_FIRST = 2, NULLS_LAST = 4;
private Database database;
private int len;
private int[] indexes;
private int[] sortTypes;
public SortOrder(Database database, int[] index, int[] sortType) {
this.database = database;
this.indexes = index;
this.sortTypes = sortType;
len = index.length;
}
public String getSQL(Expression[] list, int visible) {
StringBuffer buff = new StringBuffer();
for (int i = 0; i < len; i++) {
if (i > 0) {
buff.append(", ");
}
int idx = indexes[i];
if (idx < visible) {
buff.append(idx + 1);
} else {
buff.append("=");
buff.append(StringUtils.unEnclose(list[idx].getSQL()));
}
int type = sortTypes[i];
if ((type & DESCENDING) != 0) {
buff.append(" DESC");
}
if ((type & NULLS_FIRST) != 0) {
buff.append(" NULLS FIRST");
} else if ((type & NULLS_LAST) != 0) {
buff.append(" NULLS LAST");
}
}
return buff.toString();
}
public int compare(Value[] a, Value[] b) throws SQLException {
for (int i = 0; i < len; i++) {
int idx = indexes[i];
int type = sortTypes[i];
Value o1 = a[idx];
Value o2 = b[idx];
boolean b1 = o1 == ValueNull.INSTANCE, b2 = o2 == ValueNull.INSTANCE;
if (b1 || b2) {
if (b1 == b2) {
continue;
}
if ((type & NULLS_FIRST) != 0) {
return b1 ? -1 : 1;
} else if ((type & NULLS_LAST) != 0) {
return b1 ? 1 : -1;
} else {
// this depends on NULL_SORT_DEFAULT
int comp;
if (Constants.NULL_SORT_DEFAULT == Constants.NULL_SORT_LOW) {
comp = b1 ? -1 : 1;
return (type & DESCENDING) == 0 ? comp : -comp;
} else if (Constants.NULL_SORT_DEFAULT == Constants.NULL_SORT_HIGH) {
comp = b1 ? 1 : -1;
return (type & DESCENDING) == 0 ? comp : -comp;
} else if (Constants.NULL_SORT_DEFAULT == Constants.NULL_SORT_START) {
return b1 ? 1 : -1;
} else {
return b1 ? -1 : 1;
}
}
}
int comp = database.compare(o1, o2);
if (comp != 0) {
return (type & DESCENDING) == 0 ? comp : -comp;
}
}
return 0;
}
public void sort(ObjectArray rows) throws SQLException {
sort(rows, 0, rows.size() - 1);
}
private void swap(ObjectArray rows, int a, int b) {
Object t = rows.get(a);
rows.set(a, rows.get(b));
rows.set(b, t);
}
private void sort(ObjectArray rows, int l, int r) throws SQLException {
int i, j;
while (r - l > 10) {
i = (r + l) >> 1;
if (compare((Value[]) rows.get(l), (Value[]) rows.get(r)) > 0) {
swap(rows, l, r);
}
if (compare((Value[]) rows.get(i), (Value[]) rows.get(l)) < 0) {
swap(rows, l, i);
} else if (compare((Value[]) rows.get(i), (Value[]) rows.get(r)) > 0) {
swap(rows, i, r);
}
j = r - 1;
swap(rows, i, j);
Value[] p = (Value[]) rows.get(j);
i = l;
while (true) {
do {
++i;
} while (compare((Value[]) rows.get(i), p) < 0);
do {
--j;
} while (compare((Value[]) rows.get(j), p) > 0);
if (i >= j) {
break;
}
swap(rows, i, j);
}
swap(rows, i, r - 1);
sort(rows, l, i - 1);
l = i + 1;
}
for (i = l + 1; i <= r; i++) {
Value[] t = (Value[]) rows.get(i);
for (j = i - 1; j >= l && (compare((Value[]) rows.get(j), t) > 0); j--) {
rows.set(j + 1, rows.get(j));
}
rows.set(j + 1, t);
}
}
public int[] getIndexes() {
return indexes;
}
public int[] getSortTypes() {
return sortTypes;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.schema;
import java.sql.SQLException;
import org.h2.engine.DbObject;
import org.h2.engine.Session;
import org.h2.expression.ValueExpression;
import org.h2.message.Message;
import org.h2.message.Trace;
import org.h2.table.Table;
import org.h2.value.Value;
public class Constant extends SchemaObject {
private Value value;
private ValueExpression expression;
public Constant(Schema schema, int id, String name) {
super(schema, id, name, Trace.SCHEMA);
}
public String getCreateSQLForCopy(Table table, String quotedName) {
throw Message.getInternalError();
}
public String getCreateSQL() {
StringBuffer buff = new StringBuffer();
buff.append("CREATE CONSTANT ");
buff.append(getSQL());
buff.append(" VALUE ");
buff.append(value.getSQL());
return buff.toString();
}
public int getType() {
return DbObject.CONSTANT;
}
public void removeChildrenAndResources(Session session) throws SQLException {
invalidate();
}
public void checkRename() throws SQLException {
}
public void setValue(Value value) {
this.value = value;
expression = ValueExpression.get(value);
}
public ValueExpression getValue() {
return expression;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.schema;
import java.sql.SQLException;
import java.util.HashMap;
import org.h2.constraint.Constraint;
import org.h2.engine.Constants;
import org.h2.engine.Database;
import org.h2.engine.DbObject;
import org.h2.engine.Session;
import org.h2.engine.User;
import org.h2.index.Index;
import org.h2.jdbc.JdbcSQLException;
import org.h2.message.Message;
import org.h2.message.Trace;
import org.h2.table.Table;
import org.h2.util.ObjectArray;
public class Schema extends DbObject {
private User owner;
private boolean system;
private HashMap tablesAndViews = new HashMap();
private HashMap indexes = new HashMap();
private HashMap sequences = new HashMap();
private HashMap triggers = new HashMap();
private HashMap constraints = new HashMap();
private HashMap constants = new HashMap();
public Schema(Database database, int id, String schemaName, User owner, boolean system) {
super(database, id, schemaName, Trace.SCHEMA);
this.owner = owner;
this.system = system;
}
public boolean canDrop() {
return !getName().equals(Constants.SCHEMA_INFORMATION) && !getName().equals(Constants.SCHEMA_MAIN);
}
public String getCreateSQLForCopy(Table table, String quotedName) {
throw Message.getInternalError();
}
public String getCreateSQL() {
if(system) {
return null;
}
StringBuffer buff = new StringBuffer();
buff.append("CREATE SCHEMA ");
buff.append(getSQL());
buff.append(" AUTHORIZATION ");
buff.append(owner.getSQL());
return buff.toString();
}
public int getType() {
return DbObject.SCHEMA;
}
public void removeChildrenAndResources(Session session) throws SQLException {
while(triggers != null && triggers.size()>0) {
TriggerObject obj = (TriggerObject)triggers.values().toArray()[0];
database.removeSchemaObject(session, obj);
}
while(constraints != null && constraints.size()>0) {
Constraint obj = (Constraint)constraints.values().toArray()[0];
database.removeSchemaObject(session, obj);
}
while(tablesAndViews != null && tablesAndViews.size()>0) {
Table obj = (Table)tablesAndViews.values().toArray()[0];
database.removeSchemaObject(session, obj);
}
while(indexes != null && indexes.size()>0) {
Index obj = (Index)indexes.values().toArray()[0];
database.removeSchemaObject(session, obj);
}
while(sequences != null && sequences.size()>0) {
Sequence obj = (Sequence)sequences.values().toArray()[0];
database.removeSchemaObject(session, obj);
}
while(constants != null && constants.size()>0) {
Constant obj = (Constant)constants.values().toArray()[0];
database.removeSchemaObject(session, obj);
}
owner = null;
invalidate();
}
public void checkRename() throws SQLException {
}
public User getOwner() {
return owner;
}
private HashMap getMap(int type) {
switch(type) {
case DbObject.TABLE_OR_VIEW:
return tablesAndViews;
case DbObject.SEQUENCE:
return sequences;
case DbObject.INDEX:
return indexes;
case DbObject.TRIGGER:
return triggers;
case DbObject.CONSTRAINT:
return constraints;
case DbObject.CONSTANT:
return constants;
default:
throw Message.getInternalError("type="+type);
}
}
public void add(SchemaObject obj) throws SQLException {
if(Constants.CHECK && obj.getSchema() != this) {
throw Message.getInternalError("wrong schema");
}
String name = obj.getName();
HashMap map = getMap(obj.getType());
if(Constants.CHECK && map.get(name) != null) {
throw Message.getInternalError("object already exists");
}
map.put(name, obj);
}
public void rename(SchemaObject obj, String newName) throws SQLException {
int type = obj.getType();
HashMap map = getMap(type);
if(Constants.CHECK) {
if(!map.containsKey(obj.getName())) {
throw Message.getInternalError("not found: "+obj.getName());
}
if(obj.getName().equals(newName) || map.containsKey(newName)) {
throw Message.getInternalError("object already exists: "+newName);
}
}
map.remove(obj.getName());
obj.rename(newName);
map.put(newName, obj);
}
public Table findTableOrView(Session session, String name) {
Table table = (Table) tablesAndViews.get(name);
if(table == null && session != null) {
table = session.findLocalTempTable(name);
}
return table;
}
public Index findIndex(String name) {
return (Index) indexes.get(name);
}
public TriggerObject findTrigger(String name) {
return (TriggerObject) triggers.get(name);
}
public Sequence findSequence(String sequenceName) {
return (Sequence) sequences.get(sequenceName);
}
public Constraint findConstraint(String constraintName) {
return (Constraint) constraints.get(constraintName);
}
public Constant findConstant(String constantName) {
return (Constant) constants.get(constantName);
}
private String getUniqueName(HashMap map, String prefix) {
for(int i=0;; i++) {
String name = prefix + i;
if(map.get(name)==null) {
return name;
}
}
}
public String getUniqueConstraintName() {
return getUniqueName(constraints, "CONSTRAINT_");
}
public String getUniqueIndexName(String prefix) {
return getUniqueName(indexes, prefix);
}
public Table getTableOrView(Session session, String name) throws SQLException {
Table table = (Table) tablesAndViews.get(name);
if(table == null && session != null) {
table = session.findLocalTempTable(name);
}
if (table == null) {
throw Message.getSQLException(Message.TABLE_OR_VIEW_NOT_FOUND_1, name);
}
return table;
}
public Index getIndex(String name) throws JdbcSQLException {
Index index = (Index) indexes.get(name);
if (index == null) {
throw Message.getSQLException(Message.INDEX_NOT_FOUND_1, name);
}
return index;
}
public Constraint getConstraint(String name) throws SQLException {
Constraint constraint = (Constraint) constraints.get(name);
if (constraint == null) {
throw Message.getSQLException(Message.CONSTRAINT_NOT_FOUND_1, name);
}
return constraint;
}
public Constant getConstant(Session session, String constantName) throws SQLException {
Constant constant = (Constant) constants.get(constantName);
if (constant == null) {
throw Message.getSQLException(Message.CONSTANT_NOT_FOUND_1, constantName);
}
return constant;
}
public Sequence getSequence(String sequenceName) throws SQLException {
Sequence sequence = (Sequence) sequences.get(sequenceName);
if (sequence == null) {
throw Message.getSQLException(Message.SEQUENCE_NOT_FOUND_1, sequenceName);
}
return sequence;
}
public ObjectArray getAll(int type) {
HashMap map = getMap(type);
return new ObjectArray(map.values());
}
public void remove(Session session, SchemaObject obj) throws SQLException {
String objName = obj.getName();
HashMap map = getMap(obj.getType());
if(Constants.CHECK && !map.containsKey(objName)) {
throw Message.getInternalError("not found: "+objName);
}
map.remove(objName);
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.schema;
import org.h2.engine.DbObject;
public abstract class SchemaObject extends DbObject {
private Schema schema;
protected SchemaObject(Schema schema, int id, String name, String traceModule) {
super(schema.getDatabase(), id, name, traceModule);
this.schema = schema;
}
public Schema getSchema() {
return schema;
}
public String getSQL() {
return schema.getSQL() + "." + super.getSQL();
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.schema;
import java.sql.SQLException;
import org.h2.engine.DbObject;
import org.h2.engine.Session;
import org.h2.jdbc.JdbcSQLException;
import org.h2.message.Message;
import org.h2.message.Trace;
import org.h2.table.Table;
public class Sequence extends SchemaObject {
private static final int BLOCK_INCREMENT = 32;
private long value = 1;
private long valueWithMargin;
private long increment = 1;
private boolean belongsToTable;
public Sequence(Schema schema, int id, String name, boolean belongsToTable) {
super(schema, id, name, Trace.SEQUENCE);
this.belongsToTable = belongsToTable;
}
public void setStartValue(long value) {
this.value = value;
this.valueWithMargin = value;
}
public boolean getBelongsToTable() {
return belongsToTable;
}
public long getIncrement() {
return increment;
}
public void setIncrement(long inc) throws JdbcSQLException {
if(increment == 0) {
throw Message.getSQLException(Message.INVALID_VALUE_2, new String[]{"0", "INCREMENT"}, null);
}
this.increment = inc;
}
public String getCreateSQLForCopy(Table table, String quotedName) {
throw Message.getInternalError();
}
public synchronized String getCreateSQL() {
StringBuffer buff = new StringBuffer();
buff.append("CREATE SEQUENCE ");
buff.append(getSQL());
buff.append(" START WITH ");
buff.append(value);
if(increment != 1) {
buff.append(" INCREMENT BY ");
buff.append(increment);
}
if(belongsToTable) {
buff.append(" BELONGS_TO_TABLE");
}
return buff.toString();
}
public synchronized long getNext() throws SQLException {
if((increment > 0 && value >= valueWithMargin) || (increment < 0 && value <= valueWithMargin)) {
valueWithMargin += increment*BLOCK_INCREMENT;
flush();
}
long v = value;
value += increment;
return v;
}
public void flush() throws SQLException {
// can not use the session, because it must be committed immediately
// otherwise other threads can not access the sys table.
Session s = database.getSystemSession();
synchronized(this) {
// just for this case, use the value with the margin for the script
long realValue = value;
try {
value = valueWithMargin;
database.update(s, this);
} finally {
value = realValue;
}
}
s.commit();
}
public void close() throws SQLException {
valueWithMargin = value;
flush();
}
public int getType() {
return DbObject.SEQUENCE;
}
public void removeChildrenAndResources(Session session) {
invalidate();
}
public void checkRename() {
// nothing to do
}
public long getCurrentValue() {
return value - increment;
}
public void setBelongsToTable(boolean b) {
this.belongsToTable = b;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.schema;
import java.sql.Connection;
import java.sql.SQLException;
import org.h2.api.Trigger;
import org.h2.command.Parser;
import org.h2.engine.DbObject;
import org.h2.engine.Session;
import org.h2.message.Message;
import org.h2.message.Trace;
import org.h2.result.Row;
import org.h2.table.Table;
import org.h2.value.DataType;
import org.h2.value.Value;
/**
* @author Thomas
*/
public class TriggerObject extends SchemaObject {
public static final int INSERT=1, UPDATE=2, DELETE=4;
public static final int DEFAULT_QUEUE_SIZE = 1024;
private boolean before;
private int typeMask;
private boolean rowBased;
// TODO trigger: support queue and noWait = false as well
private int queueSize = DEFAULT_QUEUE_SIZE;
private boolean noWait;
private Table table;
private String triggerClassName;
private Trigger triggerCallback;
public TriggerObject(Schema schema, int id, String name, Table table) {
super(schema, id, name, Trace.TRIGGER);
this.table = table;
setTemporary(table.getTemporary());
}
public void setBefore(boolean before) {
this.before = before;
}
public void setTriggerClassName(Session session, String triggerClassName) throws SQLException {
this.triggerClassName = triggerClassName;
try {
Connection c2 = session.createConnection(false);
Object obj = session.getDatabase().loadClass(triggerClassName).newInstance();
triggerCallback = (Trigger)obj;
triggerCallback.init(c2, getSchema().getName(), getName(), table.getName());
} catch(Throwable e) {
throw Message.getSQLException(Message.ERROR_CREATING_TRIGGER_OBJECT_2, new String[]{getName(), triggerClassName}, e);
}
}
public void fire(Session session, boolean beforeAction) throws SQLException {
if(rowBased || before != beforeAction) {
return;
}
Connection c2 = session.createConnection(false);
try {
triggerCallback.fire(c2, null, null);
} catch(Throwable e) {
throw Message.getSQLException(Message.ERROR_EXECUTING_TRIGGER_2, new String[]{getName(), triggerClassName}, e);
}
}
private Object[] convertToObjectList(Row row) throws SQLException {
if(row == null) {
return null;
}
int len = row.getColumnCount();
Object[] list = new Object[len];
for(int i=0; i<len; i++) {
list[i] = row.getValue(i).getObject();
}
return list;
}
public void fireRow(Session session, Row oldRow, Row newRow, boolean beforeAction) throws SQLException {
if(!rowBased || before != beforeAction) {
return;
}
Object[] oldList;
Object[] newList;
boolean fire = false;
if((typeMask & INSERT) != 0) {
if(oldRow == null && newRow != null) {
fire = true;
}
}
if((typeMask & UPDATE) != 0) {
if(oldRow != null && newRow != null) {
fire = true;
}
}
if((typeMask & DELETE) != 0) {
if(oldRow != null && newRow == null) {
fire = true;
}
}
if(!fire) {
return;
}
oldList = convertToObjectList(oldRow);
newList = convertToObjectList(newRow);
Object[] newListBackup;
if(before && newList != null) {
newListBackup = new Object[newList.length];
for(int i=0; i<newList.length; i++) {
newListBackup[i] = newList[i];
}
} else {
newListBackup = null;
}
Connection c2 = session.createConnection(false);
boolean old = session.getAutoCommit();
try {
session.setAutoCommit(false);
triggerCallback.fire(c2, oldList, newList);
if(newListBackup != null) {
for(int i=0; i<newList.length; i++) {
Object o = newList[i];
if(o != newListBackup[i]) {
Value v = DataType.convertToValue(session, o, Value.UNKNOWN);
newRow.setValue(i, v);
}
}
}
} finally {
session.setAutoCommit(old);
}
}
public void setTypeMask(int typeMask) {
this.typeMask = typeMask;
}
public void setRowBased(boolean rowBased) {
this.rowBased = rowBased;
}
public void setQueueSize(int size) {
this.queueSize = size;
}
public int getQueueSize() {
return queueSize;
}
public void setNoWait(boolean noWait) {
this.noWait = noWait;
}
public boolean getNoWait() {
return noWait;
}
public String getCreateSQLForCopy(Table table, String quotedName) {
StringBuffer buff = new StringBuffer();
buff.append("CREATE TRIGGER ");
buff.append(quotedName);
if(before) {
buff.append(" BEFORE ");
} else {
buff.append(" AFTER ");
}
buff.append(getTypeNameList());
buff.append(" ON ");
buff.append(table.getSQL());
if(rowBased) {
buff.append(" FOR EACH ROW");
}
if(noWait) {
buff.append(" NOWAIT");
} else {
buff.append(" QUEUE ");
buff.append(queueSize);
}
buff.append(" CALL ");
buff.append(Parser.quoteIdentifier(triggerClassName));
return buff.toString();
}
public String getTypeNameList() {
StringBuffer buff = new StringBuffer();
if((typeMask & INSERT) != 0) {
buff.append("INSERT");
}
if((typeMask & UPDATE) != 0) {
if(buff.length()>0) {
buff.append(", ");
}
buff.append("UPDATE");
}
if((typeMask & DELETE) != 0) {
if(buff.length()>0) {
buff.append(", ");
}
buff.append("DELETE");
}
return buff.toString();
}
public String getCreateSQL() {
return getCreateSQLForCopy(table, getSQL());
}
public int getType() {
return DbObject.TRIGGER;
}
public void removeChildrenAndResources(Session session) {
table.removeTrigger(session, this);
table = null;
triggerClassName = null;
triggerCallback = null;
invalidate();
}
public void checkRename() {
// nothing to do
}
public Table getTable() {
return table;
}
public boolean getBefore() {
return before;
}
public String getTriggerClassName() {
return triggerClassName;
}
}
差异被折叠。
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.security;
public interface BlockCipher {
int ALIGN = 16;
void setKey(byte[] key);
void encrypt(byte[] bytes, int off, int len);
void decrypt(byte[] bytes, int off, int len);
int getKeyLength();
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.security;
import java.sql.SQLException;
import org.h2.message.Message;
public class CipherFactory {
public static BlockCipher getBlockCipher(String algorithm) throws SQLException {
if ("XTEA".equalsIgnoreCase(algorithm)) {
return new XTEA();
} else if ("AES".equalsIgnoreCase(algorithm)) {
return new AES();
} else {
throw Message.getSQLException(Message.UNSUPPORTED_CIPHER, algorithm);
}
}
public static SHA256 getHash(String algorithm) throws SQLException {
if("SHA256".equalsIgnoreCase(algorithm)) {
return new SHA256();
} else {
throw Message.getInvalidValueException(algorithm, "algorithm");
}
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.security;
import java.util.Arrays;
public class SHA256 {
// TODO maybe implement WHIRLPOOL
public byte[] getHashWithSalt(byte[] data, byte[] salt) {
byte[] buff = new byte[data.length + salt.length];
System.arraycopy(data, 0, buff, 0, data.length);
System.arraycopy(salt, 0, buff, data.length, salt.length);
return getHash(buff);
}
public byte[] getKeyPasswordHash(String userName, char[] password) {
String user=userName + "@";
byte[] buff = new byte[2*(user.length()+password.length)];
int n=0;
for(int i=0; i<user.length(); i++) {
char c = user.charAt(i);
buff[n++] = (byte) (c >> 8);
buff[n++] = (byte) (c);
}
for(int i=0; i<password.length; i++) {
char c = password[i];
buff[n++] = (byte) (c >> 8);
buff[n++] = (byte) (c);
}
Arrays.fill(password, (char)0);
return getHash(buff);
}
// The first 32 bits of the fractional parts of the cube roots of the first
// sixty-four prime numbers
private static final int[] K = { 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98,
0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe,
0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6,
0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3,
0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138,
0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e,
0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116,
0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814,
0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 };
public byte[] getHash(byte[] data) {
int bytelen = data.length;
int intlen = ((bytelen + 9 + 63) / 64) * 16;
byte[] bytes = new byte[intlen * 4];
System.arraycopy(data, 0, bytes, 0, bytelen);
bytes[bytelen] = (byte) 0x80;
int[] buff = new int[intlen];
for (int i = 0, j = 0; j < intlen; i += 4, j++) {
buff[j] = readInt(bytes, i);
}
buff[intlen - 2] = bytelen >>> 29;
buff[intlen - 1] = (bytelen << 3) & 0xffffffff;
int[] w = new int[64];
int[] hh = new int[] { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 };
for (int block = 0; block < intlen; block += 16) {
for (int i = 0; i < 16; i++) {
w[i] = buff[block + i];
}
for (int i = 16; i < 64; i++) {
int x = w[i - 2];
int theta1 = rot(x, 17) ^ rot(x, 19) ^ (x >>> 10);
x = w[i - 15];
int theta0 = rot(x, 7) ^ rot(x, 18) ^ (x >>> 3);
w[i] = theta1 + w[i - 7] + theta0 + w[i - 16];
}
int a = hh[0], b = hh[1], c = hh[2], d = hh[3];
int e = hh[4], f = hh[5], g = hh[6], h = hh[7];
for (int i = 0; i < 64; i++) {
int t1 = h + (rot(e, 6) ^ rot(e, 11) ^ rot(e, 25))
+ ((e & f) ^ ((~e) & g)) + K[i] + w[i];
int t2 = (rot(a, 2) ^ rot(a, 13) ^ rot(a, 22))
+ ((a & b) ^ (a & c) ^ (b & c));
h = g;
g = f;
f = e;
e = d + t1;
d = c;
c = b;
b = a;
a = t1 + t2;
}
hh[0] += a;
hh[1] += b;
hh[2] += c;
hh[3] += d;
hh[4] += e;
hh[5] += f;
hh[6] += g;
hh[7] += h;
}
byte[] result = new byte[32];
for (int i = 0; i < 8; i++) {
writeInt(result, i*4, hh[i]);
}
Arrays.fill(w, 0);
Arrays.fill(buff, 0);
Arrays.fill(hh, 0);
Arrays.fill(bytes, (byte) 0);
return result;
}
private int rot(int i, int count) {
return (i << (32 - count)) | (i >>> count);
}
private int readInt(byte[] b, int i) {
return ((b[i] & 0xff) << 24) + ((b[i + 1] & 0xff) << 16)
+ ((b[i + 2] & 0xff) << 8) + (b[i + 3] & 0xff);
}
private void writeInt(byte[] b, int i, int value) {
b[i] = (byte) (value >> 24);
b[i + 1] = (byte) (value >> 16);
b[i + 2] = (byte) (value >> 8);
b[i + 3] = (byte) value;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.security;
import java.sql.SQLException;
import org.h2.engine.Constants;
import org.h2.message.Message;
import org.h2.store.DataHandler;
import org.h2.store.FileStore;
import org.h2.util.RandomUtils;
public class SecureFileStore extends FileStore {
private byte[] key;
private BlockCipher cipher;
private BlockCipher cipherForInitVector;
private byte[] buffer = new byte[4];
private long pos;
private byte[] bufferForInitVector;
private int keyIterations;
public SecureFileStore(DataHandler handler, String name, byte[] magic, String cipher, byte[] key, int keyIterations) throws SQLException {
super(handler, name, magic);
this.key = key;
if ("XTEA".equalsIgnoreCase(cipher)) {
this.cipher = new XTEA();
this.cipherForInitVector = new XTEA();
} else if ("AES".equalsIgnoreCase(cipher)) {
this.cipher = new AES();
this.cipherForInitVector = new AES();
} else {
throw Message.getSQLException(Message.UNSUPPORTED_CIPHER, cipher);
}
this.keyIterations = keyIterations;
bufferForInitVector = new byte[Constants.FILE_BLOCK_SIZE];
}
protected byte[] generateSalt() {
return RandomUtils.getSecureBytes(Constants.FILE_BLOCK_SIZE);
}
protected void initKey(byte[] salt) {
SHA256 sha = new SHA256();
key = sha.getHashWithSalt(key, salt);
for (int i = 0; i < keyIterations; i++) {
key = sha.getHash(key);
}
cipher.setKey(key);
key = sha.getHash(key);
cipherForInitVector.setKey(key);
}
protected void writeDirect(byte[] b, int off, int len) throws SQLException {
super.write(b, off, len);
pos += len;
}
public void write(byte[] b, int off, int len) throws SQLException {
if (buffer.length < b.length) {
buffer = new byte[len];
}
System.arraycopy(b, off, buffer, 0, len);
xorInitVector(buffer, 0, len, pos);
cipher.encrypt(buffer, 0, len);
super.write(buffer, 0, len);
pos += len;
}
protected void readFullyDirect(byte[] b, int off, int len) throws SQLException {
super.readFully(b, off, len);
pos += len;
}
public void readFully(byte[] b, int off, int len) throws SQLException {
super.readFully(b, off, len);
cipher.decrypt(b, off, len);
xorInitVector(b, off, len, pos);
pos += len;
}
public void seek(long x) throws SQLException {
this.pos = x;
super.seek(x);
}
public void setLength(long newLength) throws SQLException {
long oldPos = pos;
byte[] buff = new byte[Constants.FILE_BLOCK_SIZE];
long length = length();
if(newLength > length) {
seek(length);
for(long i = length; i<newLength; i+= Constants.FILE_BLOCK_SIZE) {
write(buff, 0, Constants.FILE_BLOCK_SIZE);
}
seek(oldPos);
} else {
super.setLength(newLength);
}
}
private void xorInitVector(byte[] b, int off, int len, long pos) {
byte[] iv = bufferForInitVector;
while(len > 0) {
for(int i=0; i<Constants.FILE_BLOCK_SIZE; i+=8) {
long block = ((pos+i) >>> 3);
iv[i] = (byte) (block >> 56);
iv[i+1] = (byte) (block >> 48);
iv[i+2] = (byte) (block >> 40);
iv[i+3] = (byte) (block >> 32);
iv[i+4] = (byte) (block >> 24);
iv[i+5] = (byte) (block >> 16);
iv[i+6] = (byte) (block >> 8);
iv[i+7] = (byte) block;
}
cipherForInitVector.encrypt(iv, 0, Constants.FILE_BLOCK_SIZE);
for(int i=0; i<Constants.FILE_BLOCK_SIZE; i++) {
b[off + i] ^= iv[i];
}
pos += Constants.FILE_BLOCK_SIZE;
off += Constants.FILE_BLOCK_SIZE;
len -= Constants.FILE_BLOCK_SIZE;
}
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.security;
import org.h2.engine.Constants;
import org.h2.message.Message;
/**
* XTEA with 32 rounds
* @author Tom
*
*/
public class XTEA implements BlockCipher {
// TODO maybe implement Blowfish
// best attack reported as of 2004 is 26 rounds [wikipedia]
private static final int DELTA = 0x9E3779B9;
private int k0, k1, k2, k3, k4, k5, k6, k7, k8, k9, k10, k11, k12, k13, k14, k15;
private int k16, k17, k18, k19, k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k30, k31;
public void setKey(byte[] b) {
int[] key = new int[4];
for (int i = 0; i < 16;) {
key[i / 4] = (b[i++] << 24) + ((b[i++] & 255) << 16) + ((b[i++] & 255) << 8) + (b[i++] & 255);
}
int[] r = new int[32];
for (int i = 0, sum = 0; i < 32;) {
r[i++] = sum + key[sum & 3];
sum += DELTA;
r[i++] = sum + key[ (sum >>> 11) & 3];
}
k0=r[0];k1=r[1];k2=r[2];k3=r[3];k4=r[4];k5=r[5];k6=r[6];k7=r[7];
k8=r[8];k9=r[9];k10=r[10];k11=r[11];k12=r[12];k13=r[13];k14=r[14];k15=r[15];
k16=r[16];k17=r[17];k18=r[18];k19=r[19];k20=r[20];k21=r[21];k22=r[22];k23=r[23];
k24=r[24];k25=r[25];k26=r[26];k27=r[27];k28=r[28];k29=r[29];k30=r[30];k31=r[31];
}
public void encrypt(byte[] bytes, int off, int len) {
if (Constants.CHECK && (len % ALIGN != 0)) {
throw Message.getInternalError("unaligned len " + len);
}
for (int i = off; i < off + len; i += 8) {
encryptBlock(bytes, bytes, i);
}
}
public void decrypt(byte[] bytes, int off, int len) {
if (Constants.CHECK && (len % ALIGN != 0)) {
throw Message.getInternalError("unaligned len " + len);
}
for (int i = off; i < off + len; i += 8) {
decryptBlock(bytes, bytes, i);
}
}
public void encryptBlock(byte[] in, byte[] out, int off) {
int y = (in[off] << 24) | ((in[off+1] & 255) << 16) | ((in[off+2] & 255) << 8) | (in[off+3] & 255);
int z = (in[off+4] << 24) | ((in[off+5] & 255) << 16) | ((in[off+6] & 255) << 8) | (in[off+7] & 255);
y += (((z << 4) ^ (z >>> 5)) + z) ^ k0 ; z += (((y >>> 5) ^ (y << 4)) + y) ^ k1;
y += (((z << 4) ^ (z >>> 5)) + z) ^ k2 ; z += (((y >>> 5) ^ (y << 4)) + y) ^ k3;
y += (((z << 4) ^ (z >>> 5)) + z) ^ k4; z += (((y >>> 5) ^ (y << 4)) + y) ^ k5;
y += (((z << 4) ^ (z >>> 5)) + z) ^ k6; z += (((y >>> 5) ^ (y << 4)) + y) ^ k7;
y += (((z << 4) ^ (z >>> 5)) + z) ^ k8; z += (((y >>> 5) ^ (y << 4)) + y) ^ k9;
y += (((z << 4) ^ (z >>> 5)) + z) ^ k10; z += (((y >>> 5) ^ (y << 4)) + y) ^ k11;
y += (((z << 4) ^ (z >>> 5)) + z) ^ k12; z += (((y >>> 5) ^ (y << 4)) + y) ^ k13;
y += (((z << 4) ^ (z >>> 5)) + z) ^ k14; z += (((y >>> 5) ^ (y << 4)) + y) ^ k15;
y += (((z << 4) ^ (z >>> 5)) + z) ^ k16; z += (((y >>> 5) ^ (y << 4)) + y) ^ k17;
y += (((z << 4) ^ (z >>> 5)) + z) ^ k18; z += (((y >>> 5) ^ (y << 4)) + y) ^ k19;
y += (((z << 4) ^ (z >>> 5)) + z) ^ k20; z += (((y >>> 5) ^ (y << 4)) + y) ^ k21;
y += (((z << 4) ^ (z >>> 5)) + z) ^ k22; z += (((y >>> 5) ^ (y << 4)) + y) ^ k23;
y += (((z << 4) ^ (z >>> 5)) + z) ^ k24; z += (((y >>> 5) ^ (y << 4)) + y) ^ k25;
y += (((z << 4) ^ (z >>> 5)) + z) ^ k26; z += (((y >>> 5) ^ (y << 4)) + y) ^ k27;
y += (((z << 4) ^ (z >>> 5)) + z) ^ k28; z += (((y >>> 5) ^ (y << 4)) + y) ^ k29;
y += (((z << 4) ^ (z >>> 5)) + z) ^ k30; z += (((y >>> 5) ^ (y << 4)) + y) ^ k31;
out[off] = (byte) (y >> 24); out[off+1] = (byte) (y >> 16); out[off+2] = (byte) (y >> 8); out[off+3] = (byte) y;
out[off+4] = (byte) (z >> 24); out[off+5] = (byte) (z >> 16); out[off+6] = (byte) (z >> 8); out[off+7] = (byte) z;
}
public void decryptBlock(byte[] in, byte[] out, int off) {
int y = (in[off] << 24) | ((in[off+1] & 255) << 16) | ((in[off+2] & 255) << 8) | (in[off+3] & 255) ;
int z = (in[off+4] << 24) | ((in[off+5] & 255) << 16) | ((in[off+6] & 255) << 8) | (in[off+7] & 255);
z -= (((y >>> 5) ^ (y << 4)) + y) ^ k31; y -= (((z << 4) ^ (z >>> 5)) + z) ^ k30;
z -= (((y >>> 5) ^ (y << 4)) + y) ^ k29; y -= (((z << 4) ^ (z >>> 5)) + z) ^ k28;
z -= (((y >>> 5) ^ (y << 4)) + y) ^ k27; y -= (((z << 4) ^ (z >>> 5)) + z) ^ k26;
z -= (((y >>> 5) ^ (y << 4)) + y) ^ k25; y -= (((z << 4) ^ (z >>> 5)) + z) ^ k24;
z -= (((y >>> 5) ^ (y << 4)) + y) ^ k23; y -= (((z << 4) ^ (z >>> 5)) + z) ^ k22;
z -= (((y >>> 5) ^ (y << 4)) + y) ^ k21; y -= (((z << 4) ^ (z >>> 5)) + z) ^ k20;
z -= (((y >>> 5) ^ (y << 4)) + y) ^ k19; y -= (((z << 4) ^ (z >>> 5)) + z) ^ k18;
z -= (((y >>> 5) ^ (y << 4)) + y) ^ k17; y -= (((z << 4) ^ (z >>> 5)) + z) ^ k16;
z -= (((y >>> 5) ^ (y << 4)) + y) ^ k15; y -= (((z << 4) ^ (z >>> 5)) + z) ^ k14;
z -= (((y >>> 5) ^ (y << 4)) + y) ^ k13; y -= (((z << 4) ^ (z >>> 5)) + z) ^ k12;
z -= (((y >>> 5) ^ (y << 4)) + y) ^ k11; y -= (((z << 4) ^ (z >>> 5)) + z) ^ k10;
z -= (((y >>> 5) ^ (y << 4)) + y) ^ k9; y -= (((z << 4) ^ (z >>> 5)) + z) ^ k8;
z -= (((y >>> 5) ^ (y << 4)) + y) ^ k7; y -= (((z << 4) ^ (z >>> 5)) + z) ^ k6;
z -= (((y >>> 5) ^ (y << 4)) + y) ^ k5; y -= (((z << 4) ^ (z >>> 5)) + z) ^ k4;
z -= (((y >>> 5) ^ (y << 4)) + y) ^ k3; y -= (((z << 4) ^ (z >>> 5)) + z) ^ k2;
z -= (((y >>> 5) ^ (y << 4)) + y) ^ k1; y -= (((z << 4) ^ (z >>> 5)) + z) ^ k0;
out[off] = (byte) (y >> 24); out[off+1] = (byte) (y >> 16); out[off+2] = (byte) (y >> 8); out[off+3] = (byte) y;
out[off+4] = (byte) (z >> 24); out[off+5] = (byte) (z >> 16); out[off+6] = (byte) (z >> 8); out[off+7] = (byte) z;
}
public int getKeyLength() {
return 16;
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论