summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Ahlborn <jtahlborn@yahoo.com>2007-12-04 04:17:40 +0000
committerJames Ahlborn <jtahlborn@yahoo.com>2007-12-04 04:17:40 +0000
commit6d8b4e03a880377e2b97d448837252a53ec0b452 (patch)
tree21f987dcbf2ca64efa7a07af7178fc008ea20d05
parentb873018902c17b24bb581c18694a9f4d43fd3837 (diff)
downloadjackcess-6d8b4e03a880377e2b97d448837252a53ec0b452.tar.gz
jackcess-6d8b4e03a880377e2b97d448837252a53ec0b452.zip
add ids to savepoints in order to verify legitimacy of restore attempts
git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@198 f203690c-595d-4dc9-a70b-905162fa7fd2
-rw-r--r--src/java/com/healthmarketscience/jackcess/Cursor.java72
-rw-r--r--test/src/java/com/healthmarketscience/jackcess/CursorTest.java38
2 files changed, 101 insertions, 9 deletions
diff --git a/src/java/com/healthmarketscience/jackcess/Cursor.java b/src/java/com/healthmarketscience/jackcess/Cursor.java
index 5cc45cf..4578a41 100644
--- a/src/java/com/healthmarketscience/jackcess/Cursor.java
+++ b/src/java/com/healthmarketscience/jackcess/Cursor.java
@@ -67,6 +67,8 @@ public abstract class Cursor implements Iterable<Map<String, Object>>
private static final ScanPosition LAST_SCAN_POSITION =
new ScanPosition(RowId.LAST_ROW_ID);
+ /** identifier for this cursor */
+ private final Id _id;
/** owning table */
private final Table _table;
/** State used for reading the table rows */
@@ -81,7 +83,8 @@ public abstract class Cursor implements Iterable<Map<String, Object>>
private Position _curPos;
- protected Cursor(Table table, Position firstPos, Position lastPos) {
+ protected Cursor(Id id, Table table, Position firstPos, Position lastPos) {
+ _id = id;
_table = table;
_rowState = _table.createRowState();
_firstPos = firstPos;
@@ -255,6 +258,10 @@ public abstract class Cursor implements Iterable<Map<String, Object>>
return null;
}
+ public Id getId() {
+ return _id;
+ }
+
public Table getTable() {
return _table;
}
@@ -272,20 +279,26 @@ public abstract class Cursor implements Iterable<Map<String, Object>>
* point in time by a call to {@link #restoreSavepoint}.
* <p>
* Savepoints may be used across different cursor instances for the same
- * table, but they must be of the same type (index based vs. non-index
- * based).
+ * table, but they must have the same {@link Id}.
*/
public Savepoint getSavepoint() {
- return new Savepoint(_curPos, _prevPos);
+ return new Savepoint(_id, _curPos, _prevPos);
}
/**
* Moves the cursor to a savepoint previously returned from
* {@link #getSavepoint}.
+ * @throws IllegalArgumentException if the given savepoint does not have a
+ * cursorId equal to this cursor's id
*/
public void restoreSavepoint(Savepoint savepoint)
throws IOException
{
+ if(!_id.equals(savepoint.getCursorId())) {
+ throw new IllegalArgumentException(
+ "Savepoint " + savepoint + " is not valid for this cursor with id "
+ + _id);
+ }
restorePosition(savepoint.getCurrentPosition(),
savepoint.getPreviousPosition());
}
@@ -884,7 +897,8 @@ public abstract class Cursor implements Iterable<Map<String, Object>>
private final UsageMap.PageCursor _ownedPagesCursor;
private TableScanCursor(Table table) {
- super(table, FIRST_SCAN_POSITION, LAST_SCAN_POSITION);
+ super(new Id(table, null), table,
+ FIRST_SCAN_POSITION, LAST_SCAN_POSITION);
_ownedPagesCursor = table.getOwnedPagesCursor();
}
@@ -1045,7 +1059,7 @@ public abstract class Cursor implements Iterable<Map<String, Object>>
Index.EntryCursor entryCursor)
throws IOException
{
- super(table,
+ super(new Id(table, index), table,
new IndexPosition(entryCursor.getFirstEntry()),
new IndexPosition(entryCursor.getLastEntry()));
_entryCursor = entryCursor;
@@ -1218,18 +1232,58 @@ public abstract class Cursor implements Iterable<Map<String, Object>>
}
/**
+ * Identifier for a cursor. Will be equal to any other cursor of the same
+ * type for the same table. Primarily used to check the validity of a
+ * Savepoint.
+ */
+ public static final class Id
+ {
+ private final String _tableName;
+ private final String _indexName;
+
+ private Id(Table table, Index index) {
+ _tableName = table.getName();
+ _indexName = ((index != null) ? index.getName() : null);
+ }
+
+ @Override
+ public int hashCode() {
+ return _tableName.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return((this == o) ||
+ ((o != null) && (getClass() == o.getClass()) &&
+ ObjectUtils.equals(_tableName, ((Id)o)._tableName) &&
+ ObjectUtils.equals(_indexName, ((Id)o)._indexName)));
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + " " + _tableName + ":" + _indexName;
+ }
+ }
+
+ /**
* Value object which represents a complete save state of the cursor.
*/
public static final class Savepoint
{
+ private final Id _cursorId;
private final Position _curPos;
private final Position _prevPos;
- private Savepoint(Position curPos, Position prevPos) {
+ private Savepoint(Id cursorId, Position curPos, Position prevPos) {
+ _cursorId = cursorId;
_curPos = curPos;
_prevPos = prevPos;
}
+ public Id getCursorId() {
+ return _cursorId;
+ }
+
public Position getCurrentPosition() {
return _curPos;
}
@@ -1240,8 +1294,8 @@ public abstract class Cursor implements Iterable<Map<String, Object>>
@Override
public String toString() {
- return getClass().getSimpleName() + " CurPosition " + _curPos +
- ", PrevPosition " + _prevPos;
+ return getClass().getSimpleName() + " " + _cursorId + " CurPosition " +
+ _curPos + ", PrevPosition " + _prevPos;
}
}
diff --git a/test/src/java/com/healthmarketscience/jackcess/CursorTest.java b/test/src/java/com/healthmarketscience/jackcess/CursorTest.java
index 590b9aa..87210ff 100644
--- a/test/src/java/com/healthmarketscience/jackcess/CursorTest.java
+++ b/test/src/java/com/healthmarketscience/jackcess/CursorTest.java
@@ -649,5 +649,43 @@ public class CursorTest extends TestCase {
}
}
+ public void testId() throws Exception
+ {
+ Database db = createTestIndexTable();
+
+ Table table = db.getTable("test");
+ Index idx = table.getIndexes().get(0);
+
+ Cursor tCursor = Cursor.createCursor(table);
+ Cursor iCursor = Cursor.createIndexCursor(table, idx);
+
+ Cursor.Savepoint tSave = tCursor.getSavepoint();
+ Cursor.Savepoint iSave = iCursor.getSavepoint();
+
+ tCursor.restoreSavepoint(tSave);
+ iCursor.restoreSavepoint(iSave);
+
+ try {
+ tCursor.restoreSavepoint(iSave);
+ fail("IllegalArgumentException should have been thrown");
+ } catch(IllegalArgumentException e) {
+ // success
+ }
+
+ try {
+ iCursor.restoreSavepoint(tSave);
+ fail("IllegalArgumentException should have been thrown");
+ } catch(IllegalArgumentException e) {
+ // success
+ }
+
+ Cursor tCursor2 = Cursor.createCursor(table);
+ Cursor iCursor2 = Cursor.createIndexCursor(table, idx);
+
+ tCursor2.restoreSavepoint(tSave);
+ iCursor2.restoreSavepoint(iSave);
+
+ db.close();
+ }
}