[jboss-svn-commits] JBL Code SVN: r22026 - in labs/jbosstm/workspace/transactionalFileIO/trunk: conf and 32 other directories.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Fri Aug 29 08:58:31 EDT 2008


Author: ioannis.ganotis
Date: 2008-08-29 08:58:31 -0400 (Fri, 29 Aug 2008)
New Revision: 22026

Added:
   labs/jbosstm/workspace/transactionalFileIO/trunk/README.txt
   labs/jbosstm/workspace/transactionalFileIO/trunk/conf/
   labs/jbosstm/workspace/transactionalFileIO/trunk/conf/authz
   labs/jbosstm/workspace/transactionalFileIO/trunk/conf/passwd
   labs/jbosstm/workspace/transactionalFileIO/trunk/conf/svnserve.conf
   labs/jbosstm/workspace/transactionalFileIO/trunk/dav/
   labs/jbosstm/workspace/transactionalFileIO/trunk/db/
   labs/jbosstm/workspace/transactionalFileIO/trunk/db/current
   labs/jbosstm/workspace/transactionalFileIO/trunk/db/format
   labs/jbosstm/workspace/transactionalFileIO/trunk/db/fs-type
   labs/jbosstm/workspace/transactionalFileIO/trunk/db/revprops/
   labs/jbosstm/workspace/transactionalFileIO/trunk/db/revprops/0
   labs/jbosstm/workspace/transactionalFileIO/trunk/db/revs/
   labs/jbosstm/workspace/transactionalFileIO/trunk/db/revs/0
   labs/jbosstm/workspace/transactionalFileIO/trunk/db/transactions/
   labs/jbosstm/workspace/transactionalFileIO/trunk/db/uuid
   labs/jbosstm/workspace/transactionalFileIO/trunk/db/write-lock
   labs/jbosstm/workspace/transactionalFileIO/trunk/format
   labs/jbosstm/workspace/transactionalFileIO/trunk/hooks/
   labs/jbosstm/workspace/transactionalFileIO/trunk/hooks/post-commit.tmpl
   labs/jbosstm/workspace/transactionalFileIO/trunk/hooks/post-lock.tmpl
   labs/jbosstm/workspace/transactionalFileIO/trunk/hooks/post-revprop-change.tmpl
   labs/jbosstm/workspace/transactionalFileIO/trunk/hooks/post-unlock.tmpl
   labs/jbosstm/workspace/transactionalFileIO/trunk/hooks/pre-commit.tmpl
   labs/jbosstm/workspace/transactionalFileIO/trunk/hooks/pre-lock.tmpl
   labs/jbosstm/workspace/transactionalFileIO/trunk/hooks/pre-revprop-change.tmpl
   labs/jbosstm/workspace/transactionalFileIO/trunk/hooks/pre-unlock.tmpl
   labs/jbosstm/workspace/transactionalFileIO/trunk/hooks/start-commit.tmpl
   labs/jbosstm/workspace/transactionalFileIO/trunk/locks/
   labs/jbosstm/workspace/transactionalFileIO/trunk/locks/db-logs.lock
   labs/jbosstm/workspace/transactionalFileIO/trunk/locks/db.lock
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/build.xml
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/demo-src/
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/demo-src/org/
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/demo-src/org/jboss/
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/demo-src/org/jboss/jbossts/
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/demo-src/org/jboss/jbossts/fileio/
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/demo-src/org/jboss/jbossts/fileio/xalib/
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/demo-src/org/jboss/jbossts/fileio/xalib/txdirs/
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/demo-src/org/jboss/jbossts/fileio/xalib/txdirs/demo/
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/demo-src/org/jboss/jbossts/fileio/xalib/txdirs/demo/TXDirsDemoApp.java
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/demo-src/org/jboss/jbossts/fileio/xalib/txfiles/
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/demo-src/org/jboss/jbossts/fileio/xalib/txfiles/demo/
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/demo-src/org/jboss/jbossts/fileio/xalib/txfiles/demo/TXFilesDemoApp.java
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/docs/
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/docs/UserGuide_TXFileInJava_v1.0.odt
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/DataOutputStream.java
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/ObjectOutputStreamAppend.java
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/Globals.java
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/recovery/
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/recovery/RecoverManager.java
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txdirs/
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txdirs/dir/
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txdirs/dir/XADir.java
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txdirs/dir/XADirFile.java
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txdirs/dir/XAFileResourceManager.java
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txdirs/exceptions/
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txdirs/exceptions/IncompleteTransactionsException.java
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txdirs/exceptions/NotDirectoryException.java
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txfiles/
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txfiles/exceptions/
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txfiles/exceptions/DuplicateTransactionsException.java
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txfiles/exceptions/LockRefusedException.java
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txfiles/file/
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txfiles/file/DataRecord.java
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txfiles/file/XAFile.java
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txfiles/file/XAResourceManager.java
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txfiles/locking/
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txfiles/locking/XALock.java
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txfiles/locking/XALockManager.java
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txfiles/logging/
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txfiles/logging/LogEntry.java
   labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txfiles/logging/RecordsLogger.java
Log:
-Updated Doc



Added: labs/jbosstm/workspace/transactionalFileIO/trunk/README.txt
===================================================================
--- labs/jbosstm/workspace/transactionalFileIO/trunk/README.txt	                        (rev 0)
+++ labs/jbosstm/workspace/transactionalFileIO/trunk/README.txt	2008-08-29 12:58:31 UTC (rev 22026)
@@ -0,0 +1,5 @@
+This is a Subversion repository; use the 'svnadmin' tool to examine
+it.  Do not add, delete, or modify files here unless you know how
+to avoid corrupting the repository.
+
+Visit http://subversion.tigris.org/ for more information.

Added: labs/jbosstm/workspace/transactionalFileIO/trunk/conf/authz
===================================================================
--- labs/jbosstm/workspace/transactionalFileIO/trunk/conf/authz	                        (rev 0)
+++ labs/jbosstm/workspace/transactionalFileIO/trunk/conf/authz	2008-08-29 12:58:31 UTC (rev 22026)
@@ -0,0 +1,21 @@
+### This file is an example authorization file for svnserve.
+### Its format is identical to that of mod_authz_svn authorization
+### files.
+### As shown below each section defines authorizations for the path and
+### (optional) repository specified by the section name.
+### The authorizations follow. An authorization line can refer to a
+### single user, to a group of users defined in a special [groups]
+### section, or to anyone using the '*' wildcard.  Each definition can
+### grant read ('r') access, read-write ('rw') access, or no access
+### ('').
+
+[groups]
+# harry_and_sally = harry,sally
+
+# [/foo/bar]
+# harry = rw
+# * =
+
+# [repository:/baz/fuz]
+# @harry_and_sally = rw
+# * = r

Added: labs/jbosstm/workspace/transactionalFileIO/trunk/conf/passwd
===================================================================
--- labs/jbosstm/workspace/transactionalFileIO/trunk/conf/passwd	                        (rev 0)
+++ labs/jbosstm/workspace/transactionalFileIO/trunk/conf/passwd	2008-08-29 12:58:31 UTC (rev 22026)
@@ -0,0 +1,9 @@
+### This file is an example password file for svnserve.
+### Its format is similar to that of svnserve.conf. As shown in the
+### example below it contains one section labelled [users].
+### The name and password for each user follow, one account per line.
+
+[users]
+# harry = harryssecret
+# sally = sallyssecret
+ioannis.ganotis = wei497ap

Added: labs/jbosstm/workspace/transactionalFileIO/trunk/conf/svnserve.conf
===================================================================
--- labs/jbosstm/workspace/transactionalFileIO/trunk/conf/svnserve.conf	                        (rev 0)
+++ labs/jbosstm/workspace/transactionalFileIO/trunk/conf/svnserve.conf	2008-08-29 12:58:31 UTC (rev 22026)
@@ -0,0 +1,30 @@
+### This file controls the configuration of the svnserve daemon, if you
+### use it to allow access to this repository.  (If you only allow
+### access through http: and/or file: URLs, then this file is
+### irrelevant.)
+
+### Visit http://subversion.tigris.org/ for more information.
+
+[general]
+### These options control access to the repository for unauthenticated
+### and authenticated users.  Valid values are "write", "read",
+### and "none".  The sample settings below are the defaults.
+# anon-access = read
+# auth-access = write
+### The password-db option controls the location of the password
+### database file.  Unless you specify a path starting with a /,
+### the file's location is relative to the conf directory.
+### Uncomment the line below to use the default password file.
+ password-db = passwd
+### The authz-db option controls the location of the authorization
+### rules for path-based access control.  Unless you specify a path
+### starting with a /, the file's location is relative to the conf
+### directory.  If you don't specify an authz-db, no path-based access
+### control is done.
+### Uncomment the line below to use the default authorization file.
+# authz-db = authz
+### This option specifies the authentication realm of the repository.
+### If two repositories have the same authentication realm, they should
+### have the same password database, and vice versa.  The default realm
+### is repository's uuid.
+ realm = Redhatfileio Repository

Added: labs/jbosstm/workspace/transactionalFileIO/trunk/db/current
===================================================================
--- labs/jbosstm/workspace/transactionalFileIO/trunk/db/current	                        (rev 0)
+++ labs/jbosstm/workspace/transactionalFileIO/trunk/db/current	2008-08-29 12:58:31 UTC (rev 22026)
@@ -0,0 +1 @@
+0 1 1

Added: labs/jbosstm/workspace/transactionalFileIO/trunk/db/format
===================================================================
--- labs/jbosstm/workspace/transactionalFileIO/trunk/db/format	                        (rev 0)
+++ labs/jbosstm/workspace/transactionalFileIO/trunk/db/format	2008-08-29 12:58:31 UTC (rev 22026)
@@ -0,0 +1 @@
+2

Added: labs/jbosstm/workspace/transactionalFileIO/trunk/db/fs-type
===================================================================
--- labs/jbosstm/workspace/transactionalFileIO/trunk/db/fs-type	                        (rev 0)
+++ labs/jbosstm/workspace/transactionalFileIO/trunk/db/fs-type	2008-08-29 12:58:31 UTC (rev 22026)
@@ -0,0 +1 @@
+fsfs

Added: labs/jbosstm/workspace/transactionalFileIO/trunk/db/revprops/0
===================================================================
--- labs/jbosstm/workspace/transactionalFileIO/trunk/db/revprops/0	                        (rev 0)
+++ labs/jbosstm/workspace/transactionalFileIO/trunk/db/revprops/0	2008-08-29 12:58:31 UTC (rev 22026)
@@ -0,0 +1,5 @@
+K 8
+svn:date
+V 27
+2008-08-29T11:54:04.944069Z
+END

Added: labs/jbosstm/workspace/transactionalFileIO/trunk/db/revs/0
===================================================================
--- labs/jbosstm/workspace/transactionalFileIO/trunk/db/revs/0	                        (rev 0)
+++ labs/jbosstm/workspace/transactionalFileIO/trunk/db/revs/0	2008-08-29 12:58:31 UTC (rev 22026)
@@ -0,0 +1,11 @@
+PLAIN
+END
+ENDREP
+id: 0.0.r0/17
+type: dir
+count: 0
+text: 0 0 4 4 2d2977d1c96f487abe4a1e202dd03b4e
+cpath: /
+
+
+17 107

Added: labs/jbosstm/workspace/transactionalFileIO/trunk/db/uuid
===================================================================
--- labs/jbosstm/workspace/transactionalFileIO/trunk/db/uuid	                        (rev 0)
+++ labs/jbosstm/workspace/transactionalFileIO/trunk/db/uuid	2008-08-29 12:58:31 UTC (rev 22026)
@@ -0,0 +1 @@
+83bccdfc-51d3-44b8-95e6-426da1033d43

Added: labs/jbosstm/workspace/transactionalFileIO/trunk/db/write-lock
===================================================================

Added: labs/jbosstm/workspace/transactionalFileIO/trunk/format
===================================================================
--- labs/jbosstm/workspace/transactionalFileIO/trunk/format	                        (rev 0)
+++ labs/jbosstm/workspace/transactionalFileIO/trunk/format	2008-08-29 12:58:31 UTC (rev 22026)
@@ -0,0 +1 @@
+5

Added: labs/jbosstm/workspace/transactionalFileIO/trunk/hooks/post-commit.tmpl
===================================================================
--- labs/jbosstm/workspace/transactionalFileIO/trunk/hooks/post-commit.tmpl	                        (rev 0)
+++ labs/jbosstm/workspace/transactionalFileIO/trunk/hooks/post-commit.tmpl	2008-08-29 12:58:31 UTC (rev 22026)
@@ -0,0 +1,51 @@
+#!/bin/sh
+
+# POST-COMMIT HOOK
+#
+# The post-commit hook is invoked after a commit.  Subversion runs
+# this hook by invoking a program (script, executable, binary, etc.)
+# named 'post-commit' (for which this file is a template) with the 
+# following ordered arguments:
+#
+#   [1] REPOS-PATH   (the path to this repository)
+#   [2] REV          (the number of the revision just committed)
+#
+# The default working directory for the invocation is undefined, so
+# the program should set one explicitly if it cares.
+#
+# Because the commit has already completed and cannot be undone,
+# the exit code of the hook program is ignored.  The hook program
+# can use the 'svnlook' utility to help it examine the
+# newly-committed tree.
+#
+# On a Unix system, the normal procedure is to have 'post-commit'
+# invoke other programs to do the real work, though it may do the
+# work itself too.
+#
+# Note that 'post-commit' must be executable by the user(s) who will
+# invoke it (typically the user httpd runs as), and that user must
+# have filesystem-level permission to access the repository.
+#
+# On a Windows system, you should name the hook program
+# 'post-commit.bat' or 'post-commit.exe',
+# but the basic idea is the same.
+# 
+# The hook program typically does not inherit the environment of
+# its parent process.  For example, a common problem is for the
+# PATH environment variable to not be set to its usual value, so
+# that subprograms fail to launch unless invoked via absolute path.
+# If you're having unexpected problems with a hook program, the
+# culprit may be unusual (or missing) environment variables.
+# 
+# Here is an example hook script, for a Unix /bin/sh interpreter.
+# For more examples and pre-written hooks, see those in
+# the Subversion repository at
+# http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/ and
+# http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/
+
+
+REPOS="$1"
+REV="$2"
+
+commit-email.pl "$REPOS" "$REV" commit-watchers at example.org
+log-commit.py --repository "$REPOS" --revision "$REV"

Added: labs/jbosstm/workspace/transactionalFileIO/trunk/hooks/post-lock.tmpl
===================================================================
--- labs/jbosstm/workspace/transactionalFileIO/trunk/hooks/post-lock.tmpl	                        (rev 0)
+++ labs/jbosstm/workspace/transactionalFileIO/trunk/hooks/post-lock.tmpl	2008-08-29 12:58:31 UTC (rev 22026)
@@ -0,0 +1,44 @@
+#!/bin/sh
+
+# POST-LOCK HOOK
+#
+# The post-lock hook is run after a path is locked.  Subversion runs
+# this hook by invoking a program (script, executable, binary, etc.)
+# named 'post-lock' (for which this file is a template) with the 
+# following ordered arguments:
+#
+#   [1] REPOS-PATH   (the path to this repository)
+#   [2] USER         (the user who created the lock)
+#
+# The paths that were just locked are passed to the hook via STDIN (as
+# of Subversion 1.2, only one path is passed per invocation, but the
+# plan is to pass all locked paths at once, so the hook program
+# should be written accordingly).
+#
+# The default working directory for the invocation is undefined, so
+# the program should set one explicitly if it cares.
+#
+# Because the lock has already been created and cannot be undone,
+# the exit code of the hook program is ignored.  The hook program
+# can use the 'svnlook' utility to help it examine the
+# newly-created lock.
+#
+# On a Unix system, the normal procedure is to have 'post-lock'
+# invoke other programs to do the real work, though it may do the
+# work itself too.
+#
+# Note that 'post-lock' must be executable by the user(s) who will
+# invoke it (typically the user httpd runs as), and that user must
+# have filesystem-level permission to access the repository.
+#
+# On a Windows system, you should name the hook program
+# 'post-lock.bat' or 'post-lock.exe',
+# but the basic idea is the same.
+# 
+# Here is an example hook script, for a Unix /bin/sh interpreter:
+
+REPOS="$1"
+USER="$2"
+
+# Send email to interested parties, let them know a lock was created:
+mailer.py lock "$REPOS" "$USER" /path/to/mailer.conf

Added: labs/jbosstm/workspace/transactionalFileIO/trunk/hooks/post-revprop-change.tmpl
===================================================================
--- labs/jbosstm/workspace/transactionalFileIO/trunk/hooks/post-revprop-change.tmpl	                        (rev 0)
+++ labs/jbosstm/workspace/transactionalFileIO/trunk/hooks/post-revprop-change.tmpl	2008-08-29 12:58:31 UTC (rev 22026)
@@ -0,0 +1,56 @@
+#!/bin/sh
+
+# POST-REVPROP-CHANGE HOOK
+#
+# The post-revprop-change hook is invoked after a revision property
+# has been added, modified or deleted.  Subversion runs this hook by
+# invoking a program (script, executable, binary, etc.) named
+# 'post-revprop-change' (for which this file is a template), with the
+# following ordered arguments:
+#
+#   [1] REPOS-PATH   (the path to this repository)
+#   [2] REV          (the revision that was tweaked)
+#   [3] USER         (the username of the person tweaking the property)
+#   [4] PROPNAME     (the property that was changed)
+#   [5] ACTION       (the property was 'A'dded, 'M'odified, or 'D'eleted)
+#
+#   [STDIN] PROPVAL  ** the old property value is passed via STDIN.
+#
+# Because the propchange has already completed and cannot be undone,
+# the exit code of the hook program is ignored.  The hook program
+# can use the 'svnlook' utility to help it examine the
+# new property value.
+#
+# On a Unix system, the normal procedure is to have 'post-revprop-change'
+# invoke other programs to do the real work, though it may do the
+# work itself too.
+#
+# Note that 'post-revprop-change' must be executable by the user(s) who will
+# invoke it (typically the user httpd runs as), and that user must
+# have filesystem-level permission to access the repository.
+#
+# On a Windows system, you should name the hook program
+# 'post-revprop-change.bat' or 'post-revprop-change.exe',
+# but the basic idea is the same.
+# 
+# The hook program typically does not inherit the environment of
+# its parent process.  For example, a common problem is for the
+# PATH environment variable to not be set to its usual value, so
+# that subprograms fail to launch unless invoked via absolute path.
+# If you're having unexpected problems with a hook program, the
+# culprit may be unusual (or missing) environment variables.
+# 
+# Here is an example hook script, for a Unix /bin/sh interpreter.
+# For more examples and pre-written hooks, see those in
+# the Subversion repository at
+# http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/ and
+# http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/
+
+
+REPOS="$1"
+REV="$2"
+USER="$3"
+PROPNAME="$4"
+ACTION="$5"
+
+propchange-email.pl "$REPOS" "$REV" "$USER" "$PROPNAME" watchers at example.org

Added: labs/jbosstm/workspace/transactionalFileIO/trunk/hooks/post-unlock.tmpl
===================================================================
--- labs/jbosstm/workspace/transactionalFileIO/trunk/hooks/post-unlock.tmpl	                        (rev 0)
+++ labs/jbosstm/workspace/transactionalFileIO/trunk/hooks/post-unlock.tmpl	2008-08-29 12:58:31 UTC (rev 22026)
@@ -0,0 +1,42 @@
+#!/bin/sh
+
+# POST-UNLOCK HOOK
+#
+# The post-unlock hook runs after a path is unlocked.  Subversion runs
+# this hook by invoking a program (script, executable, binary, etc.)
+# named 'post-unlock' (for which this file is a template) with the 
+# following ordered arguments:
+#
+#   [1] REPOS-PATH   (the path to this repository)
+#   [2] USER         (the user who destroyed the lock)
+#
+# The paths that were just unlocked are passed to the hook via STDIN
+# (as of Subversion 1.2, only one path is passed per invocation, but
+# the plan is to pass all unlocked paths at once, so the hook program
+# should be written accordingly).
+#
+# The default working directory for the invocation is undefined, so
+# the program should set one explicitly if it cares.
+#
+# Because the lock has already been destroyed and cannot be undone,
+# the exit code of the hook program is ignored.
+#
+# On a Unix system, the normal procedure is to have 'post-unlock'
+# invoke other programs to do the real work, though it may do the
+# work itself too.
+#
+# Note that 'post-unlock' must be executable by the user(s) who will
+# invoke it (typically the user httpd runs as), and that user must
+# have filesystem-level permission to access the repository.
+#
+# On a Windows system, you should name the hook program
+# 'post-unlock.bat' or 'post-unlock.exe',
+# but the basic idea is the same.
+# 
+# Here is an example hook script, for a Unix /bin/sh interpreter:
+
+REPOS="$1"
+USER="$2"
+
+# Send email to interested parties, let them know a lock was removed:
+mailer.py unlock "$REPOS" "$USER" /path/to/mailer.conf

Added: labs/jbosstm/workspace/transactionalFileIO/trunk/hooks/pre-commit.tmpl
===================================================================
--- labs/jbosstm/workspace/transactionalFileIO/trunk/hooks/pre-commit.tmpl	                        (rev 0)
+++ labs/jbosstm/workspace/transactionalFileIO/trunk/hooks/pre-commit.tmpl	2008-08-29 12:58:31 UTC (rev 22026)
@@ -0,0 +1,70 @@
+#!/bin/sh
+
+# PRE-COMMIT HOOK
+#
+# The pre-commit hook is invoked before a Subversion txn is
+# committed.  Subversion runs this hook by invoking a program
+# (script, executable, binary, etc.) named 'pre-commit' (for which
+# this file is a template), with the following ordered arguments:
+#
+#   [1] REPOS-PATH   (the path to this repository)
+#   [2] TXN-NAME     (the name of the txn about to be committed)
+#
+# The default working directory for the invocation is undefined, so
+# the program should set one explicitly if it cares.
+#
+# If the hook program exits with success, the txn is committed; but
+# if it exits with failure (non-zero), the txn is aborted, no commit
+# takes place, and STDERR is returned to the client.   The hook
+# program can use the 'svnlook' utility to help it examine the txn.
+#
+# On a Unix system, the normal procedure is to have 'pre-commit'
+# invoke other programs to do the real work, though it may do the
+# work itself too.
+#
+#   ***  NOTE: THE HOOK PROGRAM MUST NOT MODIFY THE TXN, EXCEPT  ***
+#   ***  FOR REVISION PROPERTIES (like svn:log or svn:author).   ***
+#
+#   This is why we recommend using the read-only 'svnlook' utility.
+#   In the future, Subversion may enforce the rule that pre-commit
+#   hooks should not modify the versioned data in txns, or else come
+#   up with a mechanism to make it safe to do so (by informing the
+#   committing client of the changes).  However, right now neither
+#   mechanism is implemented, so hook writers just have to be careful.
+#
+# Note that 'pre-commit' must be executable by the user(s) who will
+# invoke it (typically the user httpd runs as), and that user must
+# have filesystem-level permission to access the repository.
+#
+# On a Windows system, you should name the hook program
+# 'pre-commit.bat' or 'pre-commit.exe',
+# but the basic idea is the same.
+#
+# The hook program typically does not inherit the environment of
+# its parent process.  For example, a common problem is for the
+# PATH environment variable to not be set to its usual value, so
+# that subprograms fail to launch unless invoked via absolute path.
+# If you're having unexpected problems with a hook program, the
+# culprit may be unusual (or missing) environment variables.
+# 
+# Here is an example hook script, for a Unix /bin/sh interpreter.
+# For more examples and pre-written hooks, see those in
+# the Subversion repository at
+# http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/ and
+# http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/
+
+
+REPOS="$1"
+TXN="$2"
+
+# Make sure that the log message contains some text.
+SVNLOOK=/usr/bin/svnlook
+$SVNLOOK log -t "$TXN" "$REPOS" | \
+   grep "[a-zA-Z0-9]" > /dev/null || exit 1
+
+# Check that the author of this commit has the rights to perform
+# the commit on the files and directories being modified.
+commit-access-control.pl "$REPOS" "$TXN" commit-access-control.cfg || exit 1
+
+# All checks passed, so allow the commit.
+exit 0

Added: labs/jbosstm/workspace/transactionalFileIO/trunk/hooks/pre-lock.tmpl
===================================================================
--- labs/jbosstm/workspace/transactionalFileIO/trunk/hooks/pre-lock.tmpl	                        (rev 0)
+++ labs/jbosstm/workspace/transactionalFileIO/trunk/hooks/pre-lock.tmpl	2008-08-29 12:58:31 UTC (rev 22026)
@@ -0,0 +1,64 @@
+#!/bin/sh
+
+# PRE-LOCK HOOK
+#
+# The pre-lock hook is invoked before an exclusive lock is
+# created.  Subversion runs this hook by invoking a program 
+# (script, executable, binary, etc.) named 'pre-lock' (for which
+# this file is a template), with the following ordered arguments:
+#
+#   [1] REPOS-PATH   (the path to this repository)
+#   [2] PATH         (the path in the repository about to be locked)
+#   [3] USER         (the user creating the lock)
+#
+# The default working directory for the invocation is undefined, so
+# the program should set one explicitly if it cares.
+#
+# If the hook program exits with success, the lock is created; but
+# if it exits with failure (non-zero), the lock action is aborted
+# and STDERR is returned to the client.
+
+# On a Unix system, the normal procedure is to have 'pre-lock'
+# invoke other programs to do the real work, though it may do the
+# work itself too.
+#
+# Note that 'pre-lock' must be executable by the user(s) who will
+# invoke it (typically the user httpd runs as), and that user must
+# have filesystem-level permission to access the repository.
+#
+# On a Windows system, you should name the hook program
+# 'pre-lock.bat' or 'pre-lock.exe',
+# but the basic idea is the same.
+#
+# Here is an example hook script, for a Unix /bin/sh interpreter:
+
+REPOS="$1"
+PATH="$2"
+USER="$3"
+
+# If a lock exists and is owned by a different person, don't allow it
+# to be stolen (e.g., with 'svn lock --force ...').
+
+# (Maybe this script could send email to the lock owner?)
+SVNLOOK=/usr/bin/svnlook
+GREP=/bin/grep
+SED=/bin/sed
+
+LOCK_OWNER=`$SVNLOOK lock "$REPOS" "$PATH" | \
+            $GREP '^Owner: ' | $SED 's/Owner: //'`
+
+# If we get no result from svnlook, there's no lock, allow the lock to
+# happen:
+if [ "$LOCK_OWNER" = "" ]; then
+  exit 0
+fi
+
+# If the person locking matches the lock's owner, allow the lock to
+# happen:
+if [ "$LOCK_OWNER" = "$USER" ]; then
+  exit 0
+fi
+
+# Otherwise, we've got an owner mismatch, so return failure:
+echo "Error: $PATH already locked by ${LOCK_OWNER}." 1>&2
+exit 1

Added: labs/jbosstm/workspace/transactionalFileIO/trunk/hooks/pre-revprop-change.tmpl
===================================================================
--- labs/jbosstm/workspace/transactionalFileIO/trunk/hooks/pre-revprop-change.tmpl	                        (rev 0)
+++ labs/jbosstm/workspace/transactionalFileIO/trunk/hooks/pre-revprop-change.tmpl	2008-08-29 12:58:31 UTC (rev 22026)
@@ -0,0 +1,66 @@
+#!/bin/sh
+
+# PRE-REVPROP-CHANGE HOOK
+#
+# The pre-revprop-change hook is invoked before a revision property
+# is added, modified or deleted.  Subversion runs this hook by invoking
+# a program (script, executable, binary, etc.) named 'pre-revprop-change'
+# (for which this file is a template), with the following ordered
+# arguments:
+#
+#   [1] REPOS-PATH   (the path to this repository)
+#   [2] REVISION     (the revision being tweaked)
+#   [3] USER         (the username of the person tweaking the property)
+#   [4] PROPNAME     (the property being set on the revision)
+#   [5] ACTION       (the property is being 'A'dded, 'M'odified, or 'D'eleted)
+#
+#   [STDIN] PROPVAL  ** the new property value is passed via STDIN.
+#
+# If the hook program exits with success, the propchange happens; but
+# if it exits with failure (non-zero), the propchange doesn't happen.
+# The hook program can use the 'svnlook' utility to examine the 
+# existing value of the revision property.
+#
+# WARNING: unlike other hooks, this hook MUST exist for revision
+# properties to be changed.  If the hook does not exist, Subversion 
+# will behave as if the hook were present, but failed.  The reason
+# for this is that revision properties are UNVERSIONED, meaning that
+# a successful propchange is destructive;  the old value is gone
+# forever.  We recommend the hook back up the old value somewhere.
+#
+# On a Unix system, the normal procedure is to have 'pre-revprop-change'
+# invoke other programs to do the real work, though it may do the
+# work itself too.
+#
+# Note that 'pre-revprop-change' must be executable by the user(s) who will
+# invoke it (typically the user httpd runs as), and that user must
+# have filesystem-level permission to access the repository.
+#
+# On a Windows system, you should name the hook program
+# 'pre-revprop-change.bat' or 'pre-revprop-change.exe',
+# but the basic idea is the same.
+#
+# The hook program typically does not inherit the environment of
+# its parent process.  For example, a common problem is for the
+# PATH environment variable to not be set to its usual value, so
+# that subprograms fail to launch unless invoked via absolute path.
+# If you're having unexpected problems with a hook program, the
+# culprit may be unusual (or missing) environment variables.
+# 
+# Here is an example hook script, for a Unix /bin/sh interpreter.
+# For more examples and pre-written hooks, see those in
+# the Subversion repository at
+# http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/ and
+# http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/
+
+
+REPOS="$1"
+REV="$2"
+USER="$3"
+PROPNAME="$4"
+ACTION="$5"
+
+if [ "$ACTION" = "M" -a "$PROPNAME" = "svn:log" ]; then exit 0; fi
+
+echo "Changing revision properties other than svn:log is prohibited" >&2
+exit 1

Added: labs/jbosstm/workspace/transactionalFileIO/trunk/hooks/pre-unlock.tmpl
===================================================================
--- labs/jbosstm/workspace/transactionalFileIO/trunk/hooks/pre-unlock.tmpl	                        (rev 0)
+++ labs/jbosstm/workspace/transactionalFileIO/trunk/hooks/pre-unlock.tmpl	2008-08-29 12:58:31 UTC (rev 22026)
@@ -0,0 +1,60 @@
+#!/bin/sh
+
+# PRE-UNLOCK HOOK
+#
+# The pre-unlock hook is invoked before an exclusive lock is
+# destroyed.  Subversion runs this hook by invoking a program 
+# (script, executable, binary, etc.) named 'pre-unlock' (for which
+# this file is a template), with the following ordered arguments:
+#
+#   [1] REPOS-PATH   (the path to this repository)
+#   [2] PATH         (the path in the repository about to be unlocked)
+#   [3] USER         (the user destroying the lock)
+#
+# The default working directory for the invocation is undefined, so
+# the program should set one explicitly if it cares.
+#
+# If the hook program exits with success, the lock is destroyed; but
+# if it exits with failure (non-zero), the unlock action is aborted
+# and STDERR is returned to the client.
+
+# On a Unix system, the normal procedure is to have 'pre-unlock'
+# invoke other programs to do the real work, though it may do the
+# work itself too.
+#
+# Note that 'pre-unlock' must be executable by the user(s) who will
+# invoke it (typically the user httpd runs as), and that user must
+# have filesystem-level permission to access the repository.
+#
+# On a Windows system, you should name the hook program
+# 'pre-unlock.bat' or 'pre-unlock.exe',
+# but the basic idea is the same.
+#
+# Here is an example hook script, for a Unix /bin/sh interpreter:
+
+REPOS="$1"
+PATH="$2"
+USER="$3"
+
+# If a lock is owned by a different person, don't allow it be broken.
+# (Maybe this script could send email to the lock owner?)
+
+SVNLOOK=/usr/bin/svnlook
+GREP=/bin/grep
+SED=/bin/sed
+
+LOCK_OWNER=`$SVNLOOK lock "$REPOS" "$PATH" | \
+            $GREP '^Owner: ' | $SED 's/Owner: //'`
+
+# If we get no result from svnlook, there's no lock, return success:
+if [ "$LOCK_OWNER" = "" ]; then
+  exit 0
+fi
+# If the person unlocking matches the lock's owner, return success:
+if [ "$LOCK_OWNER" = "$USER" ]; then
+  exit 0
+fi
+
+# Otherwise, we've got an owner mismatch, so return failure:
+echo "Error: $PATH locked by ${LOCK_OWNER}." 1>&2
+exit 1

Added: labs/jbosstm/workspace/transactionalFileIO/trunk/hooks/start-commit.tmpl
===================================================================
--- labs/jbosstm/workspace/transactionalFileIO/trunk/hooks/start-commit.tmpl	                        (rev 0)
+++ labs/jbosstm/workspace/transactionalFileIO/trunk/hooks/start-commit.tmpl	2008-08-29 12:58:31 UTC (rev 22026)
@@ -0,0 +1,54 @@
+#!/bin/sh
+
+# START-COMMIT HOOK
+#
+# The start-commit hook is invoked before a Subversion txn is created
+# in the process of doing a commit.  Subversion runs this hook
+# by invoking a program (script, executable, binary, etc.) named
+# 'start-commit' (for which this file is a template)
+# with the following ordered arguments:
+#
+#   [1] REPOS-PATH   (the path to this repository)
+#   [2] USER         (the authenticated user attempting to commit)
+#
+# The default working directory for the invocation is undefined, so
+# the program should set one explicitly if it cares.
+#
+# If the hook program exits with success, the commit continues; but
+# if it exits with failure (non-zero), the commit is stopped before
+# a Subversion txn is created, and STDERR is returned to the client.
+#
+# On a Unix system, the normal procedure is to have 'start-commit'
+# invoke other programs to do the real work, though it may do the
+# work itself too.
+#
+# Note that 'start-commit' must be executable by the user(s) who will
+# invoke it (typically the user httpd runs as), and that user must
+# have filesystem-level permission to access the repository.
+#
+# On a Windows system, you should name the hook program
+# 'start-commit.bat' or 'start-commit.exe',
+# but the basic idea is the same.
+# 
+# The hook program typically does not inherit the environment of
+# its parent process.  For example, a common problem is for the
+# PATH environment variable to not be set to its usual value, so
+# that subprograms fail to launch unless invoked via absolute path.
+# If you're having unexpected problems with a hook program, the
+# culprit may be unusual (or missing) environment variables.
+# 
+# Here is an example hook script, for a Unix /bin/sh interpreter.
+# For more examples and pre-written hooks, see those in
+# the Subversion repository at
+# http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/ and
+# http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/
+
+
+REPOS="$1"
+USER="$2"
+
+commit-allower.pl --repository "$REPOS" --user "$USER" || exit 1
+special-auth-check.py --user "$USER" --auth-level 3 || exit 1
+
+# All checks passed, so allow the commit.
+exit 0

Added: labs/jbosstm/workspace/transactionalFileIO/trunk/locks/db-logs.lock
===================================================================
--- labs/jbosstm/workspace/transactionalFileIO/trunk/locks/db-logs.lock	                        (rev 0)
+++ labs/jbosstm/workspace/transactionalFileIO/trunk/locks/db-logs.lock	2008-08-29 12:58:31 UTC (rev 22026)
@@ -0,0 +1,3 @@
+This file is not used by Subversion 1.3.x or later.
+However, its existence is required for compatibility with
+Subversion 1.2.x or earlier.

Added: labs/jbosstm/workspace/transactionalFileIO/trunk/locks/db.lock
===================================================================
--- labs/jbosstm/workspace/transactionalFileIO/trunk/locks/db.lock	                        (rev 0)
+++ labs/jbosstm/workspace/transactionalFileIO/trunk/locks/db.lock	2008-08-29 12:58:31 UTC (rev 22026)
@@ -0,0 +1,3 @@
+This file is not used by Subversion 1.3.x or later.
+However, its existence is required for compatibility with
+Subversion 1.2.x or earlier.

Added: labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/build.xml
===================================================================
--- labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/build.xml	                        (rev 0)
+++ labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/build.xml	2008-08-29 12:58:31 UTC (rev 22026)
@@ -0,0 +1,113 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+  JBoss, Home of Professional Open Source
+  Copyright 2008, Red Hat Middleware LLC, and individual contributors
+  as indicated by the @author tags.
+  See the copyright.txt in the distribution for a full listing
+  of individual contributors.
+  This copyrighted material is made available to anyone wishing to use,
+  modify, copy, or redistribute it subject to the terms and conditions
+  of the GNU Lesser General Public License, v. 2.1.
+  This program is distributed in the hope that it will be useful, but WITHOUT A
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+  PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+  You should have received a copy of the GNU Lesser General Public License,
+  v.2.1 along with this distribution; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+  MA  02110-1301, USA.
+
+  (C) 2008,
+  @author Red Hat Middleware LLC.
+-->
+<project name="jbossts-fileio" default="compile">
+
+    <!-- set to the dir in which JBossTS 4.4 is installed.  http://www.jboss.org/jbosstm/ -->
+    <property name="jbossts.home" value="/put/something/here"/>
+
+    <!-- set to the dir in which Apache Commons Transaction is installed.  http://commons.apache.org/transaction/
+        This is required only for transaction directory support. -->
+    <property name="apache.home" value="/put/something/here"/>
+
+    <!-- you should not need to change anything below this point -->
+
+    <property name="build" value="build"/>
+    <property name="debug" value="true"/>
+
+    <path id="txfiles.classpath">
+        <pathelement location="${jbossts.home}/lib/ext/jta-1_1-classes.zip"/>
+        <pathelement location="${jbossts.home}/lib/jbossjta.jar"/>
+    </path>
+
+    <path id="txdirs.classpath">
+        <pathelement location="${apache.home}/commons-transaction-1.2.jar"/>
+        <pathelement location="${apache.home}/lib/commons-logging-1.1.jar"/>
+    </path>
+
+    <path id="demo.runtime.classpath">
+        <pathelement location="${build}/classes"/>
+        <fileset dir="${jbossts.home}/lib/">
+            <include name="*.jar"/>
+            <include name="ext/*.jar"/>
+            <include name="ext/*.zip"/>
+        </fileset>
+        <pathelement location="${jbossts.home}/etc"/>
+    </path>
+
+    <target name="clean" description="cleanup module">
+        <delete dir="${build}"/>
+    </target>
+
+    <target name="clean-demo" description="cleanup files used by the demo app">
+        <delete dir="PutObjectStoreDirHere"/>
+        <delete dir="Logging"/>
+        <delete dir="Locks"/>
+        <delete file="entries.txt"/>
+        <delete file="transaction.log"/>
+        <delete dir="businesstxdir"/>
+    </target>
+
+    <target name="init" description="initialize build">
+        <mkdir dir="${build}"/>
+        <mkdir dir="${build}/classes"/>
+        <available file="${apache.home}" property="have.apache.commons.tx" value="true"/>
+    </target>
+
+    <target name="compile" depends="init" description="compile package">
+        <javac destdir="${build}/classes" debug="${debug}" srcdir="src">
+            <exclude name="**/txdirs/**" unless="have.apache.commons.tx"/>
+            <classpath refid="txfiles.classpath"/>
+            <classpath refid="txdirs.classpath"/>
+        </javac>
+        <javac destdir="${build}/classes" debug="${debug}" srcdir="demo-src">
+            <exclude name="**/txdirs/**" unless="have.apache.commons.tx"/>
+            <classpath refid="txfiles.classpath"/>
+            <classpath refid="txdirs.classpath"/>
+        </javac>
+    </target>
+
+    <target name="jar" depends="compile" description="build lib jar file">
+        <jar basedir="${build}/classes" file="${build}/jbossts-fileio.jar">
+            <exclude name="**/demo/**"/>
+        </jar>
+    </target>
+
+    <target name="javadoc" depends="init" description="generate the javadoc for the lib">
+        <javadoc destdir="${build}/docs" sourcepath="src"/>
+    </target>
+
+    <target name="txfiles-demo" depends="compile" description="run the txfiles demo">
+        <java classname="org.jboss.jbossts.fileio.xalib.txfiles.demo.TXFilesDemoApp" fork="true">
+            <classpath refid="demo.runtime.classpath"/>
+        </java>
+    </target>
+
+    <target name="txdirs-demo" depends="compile" description="run the txdirs demo">
+        <java classname="org.jboss.jbossts.fileio.xalib.txdirs.demo.TXDirsDemoApp" fork="true">
+            <classpath>
+                <path refid="demo.runtime.classpath"/>
+                <path refid="txdirs.classpath"/>
+            </classpath>
+        </java>
+    </target>
+
+</project>

Added: labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/demo-src/org/jboss/jbossts/fileio/xalib/txdirs/demo/TXDirsDemoApp.java
===================================================================
--- labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/demo-src/org/jboss/jbossts/fileio/xalib/txdirs/demo/TXDirsDemoApp.java	                        (rev 0)
+++ labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/demo-src/org/jboss/jbossts/fileio/xalib/txdirs/demo/TXDirsDemoApp.java	2008-08-29 12:58:31 UTC (rev 22026)
@@ -0,0 +1,139 @@
+/*     JBoss, Home of Professional Open Source Copyright 2008, Red Hat
+ *  Middleware LLC, and individual contributors as indicated by the
+ *  @author tags.
+ *     See the copyright.txt in the distribution for a full listing of
+ *  individual contributors. This copyrighted material is made available
+ *  to anyone wishing to use, modify, copy, or redistribute it subject to
+ *  the terms and conditions of the GNU Lesser General Public License, v. 2.1.
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY
+ *  or FITNESS FOR A PARTICULAR PURPOSE.
+ *     See the GNU Lesser General Public License for more details. You should
+ *  have received a copy of the GNU Lesser General Public License, v.2.1
+ *  along with this distribution; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA  02110-1301, USA.
+ *
+ *  (C) 2008,
+ *  @author Red Hat Middleware LLC.
+ */
+package org.jboss.jbossts.fileio.xalib.txdirs.demo;
+
+import org.jboss.jbossts.fileio.xalib.txdirs.dir.XADir;
+import org.jboss.jbossts.fileio.xalib.txdirs.dir.XADirFile;
+import javax.transaction.TransactionManager;
+import java.io.File;
+import java.io.IOException;
+import com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionManagerImple;
+
+/**
+ * This is a demo class.
+ * Demonstrates a file operation applied transactionally on a file
+ * under some directory.
+ *
+ * @author Ioannis Ganotis
+ * @version Aug 23, 2008
+ */
+public class TXDirsDemoApp
+{
+  final String EXISTING_FILENAME = "file.txt";
+  final String NEW_FILENAME = "new_file.txt";
+  final String TX_FOLDER_NAME = "businesstxdir";
+  XADir xadir;
+  TransactionManager txMngr;
+
+  public TXDirsDemoApp() throws Exception {
+    initialiseFiles();
+
+    xadir = new XADir(new File(TX_FOLDER_NAME));
+    txMngr = new TransactionManagerImple();
+
+    executeDemo();
+  }
+
+  /**
+   * Creates a directory if it does not exists and also
+   * creates a file in it. The file will be used to apply
+   * file operations on it.
+   *
+   * @exception IOException if an I/O error occurs
+   */
+  private void initialiseFiles() throws IOException  {
+    System.out.println("######### Initialise:Begin #########");
+    File folder = new File(TX_FOLDER_NAME);
+    if (folder.exists()) {
+      deleteFiles(folder.listFiles());
+      folder.delete();
+    }
+    // Create the folder and a file in it
+    folder.mkdir();
+    File file = new File(TX_FOLDER_NAME + "/" + EXISTING_FILENAME);
+    file.createNewFile();
+    System.out.println("--- File name in the tx directory: <" + file.getName() + "> ---");
+    System.out.println("#########  Initialise:End  #########\n");    
+  }
+
+  /**
+   * Deletes all the given <code>files</code>
+   *
+   * @param files the files to delete
+   */
+  private void deleteFiles(File[] files) {
+    for (File file : files) {
+      if (file.isDirectory())
+        deleteFiles(file.listFiles());
+      file.delete();
+    }
+  }
+
+  /**
+   * The method performs a simple rename operation to an existing
+   * file in the transactional directory during the execution of a
+   * transaction.
+   *
+   * @exception Exception if an error occurs during the execution of
+   *                      the transaction
+   */
+  private void executeDemo() throws Exception {
+    try {
+      txMngr.begin();
+      {
+        System.out.println("######### TransactionManager:Started #########");
+        xadir.startTransactionOn(txMngr);
+
+        // Get a list of all the files in the directory
+        XADirFile[] files = xadir.listTXFiles();
+
+        // Apply a file operation - rename old file to something else
+        files[0].renameTo(new File(NEW_FILENAME));
+        System.out.println("------ TX renamed old file ------");
+        System.out.println("------ TX reads new filename: <" + files[0].getName() + "> ------");
+
+        System.out.println("--- Actual filename: <" + getFileName() + "> ---");
+      }
+      txMngr.commit();
+      System.out.println("######### TransactionManager:Committed #########\n");
+      System.out.println("--- Actual filename: <" + getFileName() + "> ---");
+    } catch (Exception e) {
+      txMngr.rollback();
+      System.out.println("XXXXXXXX TransactionManager:Rolled-back XXXXXXXX\n");
+      System.out.println("--- Actual filename: <" + getFileName() + "> ---");      
+    }
+    xadir.close();
+  }
+
+  /**
+   * Returns the name of the file in the folder
+   *
+   * @return a <code>String</code> representing the name of the
+   *         file in the folder
+   */
+  private String getFileName() {
+    File folder = new File(TX_FOLDER_NAME);
+    return folder.list()[0]; // return the filename
+  }
+
+  public static void main (String[] args) throws Exception {
+    new TXDirsDemoApp();
+  }
+}

Added: labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/demo-src/org/jboss/jbossts/fileio/xalib/txfiles/demo/TXFilesDemoApp.java
===================================================================
--- labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/demo-src/org/jboss/jbossts/fileio/xalib/txfiles/demo/TXFilesDemoApp.java	                        (rev 0)
+++ labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/demo-src/org/jboss/jbossts/fileio/xalib/txfiles/demo/TXFilesDemoApp.java	2008-08-29 12:58:31 UTC (rev 22026)
@@ -0,0 +1,128 @@
+/*     JBoss, Home of Professional Open Source Copyright 2008, Red Hat
+ *  Middleware LLC, and individual contributors as indicated by the
+ *  @author tags.
+ *     See the copyright.txt in the distribution for a full listing of
+ *  individual contributors. This copyrighted material is made available
+ *  to anyone wishing to use, modify, copy, or redistribute it subject to
+ *  the terms and conditions of the GNU Lesser General Public License, v. 2.1.
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY
+ *  or FITNESS FOR A PARTICULAR PURPOSE.
+ *     See the GNU Lesser General Public License for more details. You should
+ *  have received a copy of the GNU Lesser General Public License, v.2.1
+ *  along with this distribution; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA  02110-1301, USA.
+ *
+ *  (C) 2008,
+ *  @author Red Hat Middleware LLC.
+ */
+package org.jboss.jbossts.fileio.xalib.txfiles.demo;
+
+import org.jboss.jbossts.fileio.xalib.txfiles.file.XAFile;
+import javax.transaction.TransactionManager;
+import com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionManagerImple;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+
+/**
+ * This is a demo class.
+ * It demonstrates how to apply read and write operations transactionally
+ * to a file
+ *
+ * @author Ioannis Ganotis
+ * @version Aug 20, 2008
+ */
+public class TXFilesDemoApp
+{
+  final String FILENAME = "entries.txt";
+  final String MSG = "The result of the computation is: ";
+  final byte COMPUTATION_RESULT = 49;
+  XAFile xaFile;
+  TransactionManager txMngr;
+
+  public TXFilesDemoApp() throws Exception {
+    initialiseData();
+    xaFile = new XAFile(FILENAME, "rw", true);
+    txMngr = new TransactionManagerImple();
+
+    executeDemo();
+
+  }
+
+  /**
+   * Crreates a file if it does not exist, and writes some
+   * data to it.
+   *
+   * @exception IOException if an I/O error occurs
+   */
+  private void initialiseData() throws IOException {
+    System.out.println("######### Initialise:Begin #########");
+    RandomAccessFile raf = new RandomAccessFile(FILENAME, "rw");
+    raf.writeBytes(MSG);
+    raf.write(COMPUTATION_RESULT);
+    raf.seek(0);
+    System.out.println(raf.readLine());
+    raf.close();
+    System.out.println("#########  Initialise:End  #########\n");
+  }
+
+  /**
+   * Applies simple write and read operations to demonstrate the behaviour
+   * of the {@link org.jboss.jbossts.fileio.xalib.txfiles.file.XAFile}.
+   *
+   * @exception Exception if an error occurs during the transaction
+   */
+  private void executeDemo() throws Exception {
+    try {
+      txMngr.begin();
+      {
+        System.out.println("######### TransactionManager:Started #########");
+        xaFile.newTransaction(txMngr);
+        // ---------- Read the current value ----------
+        xaFile.seek(MSG.length()); // seek to the end of the message
+        byte result = xaFile.readByte();
+
+        // ---------- Modify the current value ----------
+        result++; // increment by 1
+
+        // ---------- Write the new value to the file ----------
+        xaFile.seek(MSG.length());
+        xaFile.write(result);
+        System.out.println("------ TX modifies data in the file ------");
+
+        // Request a read operation whilst within a tx
+        xaFile.seek(0);
+        System.out.println("------ TX reads data in the file: <" + xaFile.readLine() + "> ------");
+
+        System.out.println("--- Actual data in file: <" + readActualData() + "> ---");
+      }
+      txMngr.commit();
+      System.out.println("######### TransactionManager:Committed #########\n");
+      System.out.println("--- Actual data in file: <" + readActualData() + "> ---");
+    } catch (Exception e) {
+      txMngr.rollback();
+      System.out.println("XXXXXXXX TransactionManager:Rolled-back XXXXXXXX\n");
+      System.out.println("--- Actual data in file: <" + readActualData() + "> ---");      
+      e.printStackTrace();
+    }
+    xaFile.close();
+  }
+
+  /**
+   * Reads data from the file.
+   *
+   * @return a <code>String</code> containing the data in the file.    * 
+   * @exception IOException if an I/O error occurs
+   */
+  private String readActualData() throws IOException {
+    RandomAccessFile raf = new RandomAccessFile(FILENAME, "r");
+    String line = raf.readLine();
+    raf.close();
+    return line;
+  }
+
+  public static void main(String[] args) throws Exception {
+    new TXFilesDemoApp();
+  }
+}
\ No newline at end of file

Added: labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/docs/UserGuide_TXFileInJava_v1.0.odt
===================================================================
(Binary files differ)


Property changes on: labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/docs/UserGuide_TXFileInJava_v1.0.odt
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/DataOutputStream.java
===================================================================
--- labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/DataOutputStream.java	                        (rev 0)
+++ labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/DataOutputStream.java	2008-08-29 12:58:31 UTC (rev 22026)
@@ -0,0 +1,134 @@
+/*     JBoss, Home of Professional Open Source Copyright 2008, Red Hat
+ *  Middleware LLC, and individual contributors as indicated by the
+ *  @author tags.
+ *     See the copyright.txt in the distribution for a full listing of
+ *  individual contributors. This copyrighted material is made available
+ *  to anyone wishing to use, modify, copy, or redistribute it subject to
+ *  the terms and conditions of the GNU Lesser General Public License, v. 2.1.
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY
+ *  or FITNESS FOR A PARTICULAR PURPOSE.
+ *     See the GNU Lesser General Public License for more details. You should
+ *  have received a copy of the GNU Lesser General Public License, v.2.1
+ *  along with this distribution; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA  02110-1301, USA.
+ *
+ *  (C) 2008,
+ *  @author Red Hat Middleware LLC.
+ */
+package org.jboss.jbossts.fileio;
+
+import java.io.DataOutput;
+import java.io.IOException;
+import java.io.UTFDataFormatException;
+import java.io.OutputStream;
+
+/**
+ * User: Ioannis Ganotis
+ * Date: Aug 5, 2008
+ */
+public class DataOutputStream extends java.io.DataOutputStream
+{
+  /**
+   * bytearr is initialized on demand by writeUTF
+   */
+  private byte[] bytearr = null;
+
+  /**
+   * Creates a new data output stream to write data to the specified
+   * underlying output stream. The counter <code>written</code> is
+   * set to zero.
+   *
+   * @param   out   the underlying output stream, to be saved for later
+   *                use.
+   * @see     java.io.FilterOutputStream#out
+   */
+  public DataOutputStream(OutputStream out) {
+    super(out);
+  }
+
+
+  /**
+   * Writes a string to the specified DataOutput using
+   * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
+   * encoding in a machine-independent manner.
+   * <p/>
+   * First, two bytes are written to out as if by the <code>writeShort</code>
+   * method giving the number of bytes to follow. This value is the number of
+   * bytes actually written out, not the length of the string. Following the
+   * length, each character of the string is output, in sequence, using the
+   * modified UTF-8 encoding for the character. If no exception is thrown, the
+   * counter <code>written</code> is incremented by the total number of
+   * bytes written to the output stream. This will be at least two
+   * plus the length of <code>str</code>, and at most two plus
+   * thrice the length of <code>str</code>.
+   *
+   * @param str a string to be written.
+   * @param out destination to write to
+   * @return The number of bytes written out.
+   * @throws java.io.IOException if an I/O error occurs.
+   */
+    public static int writeUTF(String str, DataOutput out) throws IOException {
+    int strlen = str.length();
+    int utflen = 0;
+    int c, count = 0;
+
+    /* use charAt instead of copying String to char array */
+    for (int i = 0; i < strlen; i++) {
+      c = str.charAt(i);
+      if ((c >= 0x0001) && (c <= 0x007F)) {
+        utflen++;
+      } else if (c > 0x07FF) {
+        utflen += 3;
+      } else {
+        utflen += 2;
+      }
+    }
+
+    if (utflen > 65535) {
+      throw new UTFDataFormatException(
+          "encoded string too long: " + utflen + " bytes");
+    }
+
+    byte[] bytearr;
+    if (out instanceof DataOutputStream) {
+      DataOutputStream dos = (DataOutputStream) out;
+      if (dos.bytearr == null || (dos.bytearr.length < (utflen + 2))) {
+        dos.bytearr = new byte[(utflen * 2) + 2];
+      }
+      bytearr = dos.bytearr;
+    } else {
+      bytearr = new byte[utflen + 2];
+    }
+
+    bytearr[count++] = (byte) ((utflen >>> 8) & 0xFF);
+    bytearr[count++] = (byte) ((utflen) & 0xFF);
+
+    int i;
+    for (i = 0; i < strlen; i++) {
+      c = str.charAt(i);
+      if (!((c >= 0x0001) && (c <= 0x007F))) {
+        break;
+      }
+      bytearr[count++] = (byte) c;
+    }
+
+    for (; i < strlen; i++) {
+      c = str.charAt(i);
+      if ((c >= 0x0001) && (c <= 0x007F)) {
+        bytearr[count++] = (byte) c;
+
+      } else if (c > 0x07FF) {
+        bytearr[count++] = (byte) (0xE0 | ((c >> 12) & 0x0F));
+        bytearr[count++] = (byte) (0x80 | ((c >> 6) & 0x3F));
+        bytearr[count++] = (byte) (0x80 | ((c) & 0x3F));
+      } else {
+        bytearr[count++] = (byte) (0xC0 | ((c >> 6) & 0x1F));
+        bytearr[count++] = (byte) (0x80 | ((c) & 0x3F));
+      }
+    }
+    out.write(bytearr, 0, utflen + 2);
+    return utflen + 2;
+  }
+}

Added: labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/ObjectOutputStreamAppend.java
===================================================================
--- labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/ObjectOutputStreamAppend.java	                        (rev 0)
+++ labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/ObjectOutputStreamAppend.java	2008-08-29 12:58:31 UTC (rev 22026)
@@ -0,0 +1,41 @@
+/*     JBoss, Home of Professional Open Source Copyright 2008, Red Hat
+ *  Middleware LLC, and individual contributors as indicated by the
+ *  @author tags.
+ *     See the copyright.txt in the distribution for a full listing of
+ *  individual contributors. This copyrighted material is made available
+ *  to anyone wishing to use, modify, copy, or redistribute it subject to
+ *  the terms and conditions of the GNU Lesser General Public License, v. 2.1.
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY
+ *  or FITNESS FOR A PARTICULAR PURPOSE.
+ *     See the GNU Lesser General Public License for more details. You should
+ *  have received a copy of the GNU Lesser General Public License, v.2.1
+ *  along with this distribution; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA  02110-1301, USA.
+ *
+ *  (C) 2008,
+ *  @author Red Hat Middleware LLC.
+ */
+package org.jboss.jbossts.fileio;
+
+import java.io.OutputStream;
+import java.io.ObjectOutputStream;
+import java.io.IOException;
+
+/**
+ * User: igan
+ * Date: Jul 27, 2008
+ */
+public class ObjectOutputStreamAppend extends ObjectOutputStream
+{
+  public ObjectOutputStreamAppend(OutputStream os) throws IOException {
+    super(os);
+  }
+
+  @Override
+  protected void writeStreamHeader() throws IOException {
+    reset();
+  }
+}
+

Added: labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/Globals.java
===================================================================
--- labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/Globals.java	                        (rev 0)
+++ labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/Globals.java	2008-08-29 12:58:31 UTC (rev 22026)
@@ -0,0 +1,47 @@
+/*     JBoss, Home of Professional Open Source Copyright 2008, Red Hat
+ *  Middleware LLC, and individual contributors as indicated by the
+ *  @author tags.
+ *     See the copyright.txt in the distribution for a full listing of
+ *  individual contributors. This copyrighted material is made available
+ *  to anyone wishing to use, modify, copy, or redistribute it subject to
+ *  the terms and conditions of the GNU Lesser General Public License, v. 2.1.
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY
+ *  or FITNESS FOR A PARTICULAR PURPOSE.
+ *     See the GNU Lesser General Public License for more details. You should
+ *  have received a copy of the GNU Lesser General Public License, v.2.1
+ *  along with this distribution; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA  02110-1301, USA.
+ *
+ *  (C) 2008,
+ *  @author Red Hat Middleware LLC.
+ */
+package org.jboss.jbossts.fileio.xalib;
+
+/**
+ * This class defines some global constants used by the
+ * <code>XA_lib</code>.
+ * 
+ * @author Ioannis Ganotis
+ * @version Jun 12, 2008
+ */
+public class Globals
+{
+  //-------------------- txfiles --------------------
+  public static final String LOG_FOLDER_PATH = "Logging";
+  public static final String LOCKS_FOLDER_PATH = "Locks/";
+  public static final int THREAD_TIMEOUT = 15000;
+  public static final int TX_GROUPS = 20;
+  // Used in Lock policies
+  public static final int NO_MOD_LOCK = 100;
+  public static final int REFUSE_LOCK = -100;
+  public static final int UPDATE_OLD_LOCK = 50;
+  public static final int ADD_NEW_LOCK = 1;
+  public static final int MOVE_LOCK_BOUNDS = 200;
+  // Recovery
+  public static final long RECOVERY_ID = -100;
+
+  // -------------------- txdirs --------------------
+  public static final String WORK_DIR_NAME = "txDir_work";
+}
\ No newline at end of file

Added: labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/recovery/RecoverManager.java
===================================================================
--- labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/recovery/RecoverManager.java	                        (rev 0)
+++ labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/recovery/RecoverManager.java	2008-08-29 12:58:31 UTC (rev 22026)
@@ -0,0 +1,46 @@
+/*     JBoss, Home of Professional Open Source Copyright 2008, Red Hat
+ *  Middleware LLC, and individual contributors as indicated by the
+ *  @author tags.
+ *     See the copyright.txt in the distribution for a full listing of
+ *  individual contributors. This copyrighted material is made available
+ *  to anyone wishing to use, modify, copy, or redistribute it subject to
+ *  the terms and conditions of the GNU Lesser General Public License, v. 2.1.
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY
+ *  or FITNESS FOR A PARTICULAR PURPOSE.
+ *     See the GNU Lesser General Public License for more details. You should
+ *  have received a copy of the GNU Lesser General Public License, v.2.1
+ *  along with this distribution; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA  02110-1301, USA.
+ *
+ *  (C) 2008,
+ *  @author Red Hat Middleware LLC.
+ */
+package org.jboss.jbossts.fileio.xalib.recovery;
+
+import com.arjuna.ats.arjuna.recovery.RecoveryManager;
+
+/**
+ * This class can be used to recover incomplete transactions after
+ * a system crash.
+ *
+ * @author Ioannis Ganotis
+ * @version Aug 28, 2008
+ */
+public class RecoverManager
+{
+  /**
+   * Constructor to create RecoverManager objects.
+   * Every object will try to get a {@link com.arjuna.ats.arjuna.recovery.RecoveryManager}
+   * and start a thread on it.
+   */
+  public RecoverManager() {
+    RecoveryManager rm = RecoveryManager.manager();
+    rm.startRecoveryManagerThread();
+  }
+
+  public static void main (String[] args) {
+    new RecoverManager();
+  }
+}

Added: labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txdirs/dir/XADir.java
===================================================================
--- labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txdirs/dir/XADir.java	                        (rev 0)
+++ labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txdirs/dir/XADir.java	2008-08-29 12:58:31 UTC (rev 22026)
@@ -0,0 +1,205 @@
+/*     JBoss, Home of Professional Open Source Copyright 2008, Red Hat
+ *  Middleware LLC, and individual contributors as indicated by the
+ *  @author tags.
+ *     See the copyright.txt in the distribution for a full listing of
+ *  individual contributors. This copyrighted material is made available
+ *  to anyone wishing to use, modify, copy, or redistribute it subject to
+ *  the terms and conditions of the GNU Lesser General Public License, v. 2.1.
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY
+ *  or FITNESS FOR A PARTICULAR PURPOSE.
+ *     See the GNU Lesser General Public License for more details. You should
+ *  have received a copy of the GNU Lesser General Public License, v.2.1
+ *  along with this distribution; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA  02110-1301, USA.
+ *
+ *  (C) 2008,
+ *  @author Red Hat Middleware LLC.
+ */
+package org.jboss.jbossts.fileio.xalib.txdirs.dir;
+
+import org.apache.commons.transaction.file.FileResourceManager;
+import org.apache.commons.transaction.file.ResourceManagerException;
+import org.apache.commons.transaction.util.CommonsLoggingLogger;
+import org.apache.commons.transaction.util.PrintWriterLogger;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.jbossts.fileio.xalib.txdirs.exceptions.NotDirectoryException;
+import org.jboss.jbossts.fileio.xalib.txdirs.exceptions.IncompleteTransactionsException;
+import org.jboss.jbossts.fileio.xalib.Globals;
+import javax.transaction.TransactionManager;
+import javax.transaction.Transaction;
+import javax.transaction.RollbackException;
+import javax.transaction.SystemException;
+import java.util.LinkedList;
+import java.io.*;
+
+/**
+ * Instances of this class represent a transactional directory on which
+ * file operations such as create, rename and delete can be applied. The
+ * contents (files) of this directory are represented by {@link XADirFile}
+ * objects. Through these objects the application programmer can access the
+ * file operations.
+ * <p>
+ * It provides methods to list the files in the directory and access the
+ * {@link org.apache.commons.transaction.file.FileResourceManager} of the Apache
+ * commons transaction project.
+ *
+ * @see XADirFile
+ * @see org.apache.commons.transaction.file.FileResourceManager
+ * @see org.jboss.jbossts.fileio.xalib.txdirs.dir.XAFileResourceManager 
+ *
+ * @author Ioannis Ganotis
+ * @version Aug 6, 2008
+ */
+public class XADir implements Serializable, Closeable
+{
+  private String curTxId;
+  transient private FileResourceManager freMngr;
+  private long length;
+
+  /**
+   * Constructor to create objects that represent a transactional directory.
+   * <p>
+   * The constructor checks if the <code>storeDir</code> is a directory or not.
+   * If it is not then {@link org.jboss.jbossts.fileio.xalib.txdirs.exceptions.NotDirectoryException}
+   * exception is thrown. Otherwise, a new <code>FileResourceManager</code> object
+   * is created to allow access to transactional methods (e.g. start, commit, rollback
+   * a transaction)
+   *
+   * @param storeDir directory where main data should go after commit
+   * @exception org.jboss.jbossts.fileio.xalib.txdirs.exceptions.NotDirectoryException
+   *            if the <code>storeDir</code> is not a directory
+   * @exception org.apache.commons.transaction.file.ResourceManagerException
+   *            if an error in the <code>FileResourceManager</code> occurs
+   */
+  public XADir(File storeDir) throws IOException, ResourceManagerException {
+    if (!storeDir.exists()) {
+      storeDir.mkdir();
+    } else {
+      if (!storeDir.isDirectory())
+        throw new NotDirectoryException("The file given is not a directory.");
+    }
+
+    length = storeDir.list().length;
+    String workDir = storeDir.getCanonicalPath() + "/" + Globals.WORK_DIR_NAME;
+    freMngr = new FileResourceManager(storeDir.getCanonicalPath(), workDir, false,
+        new PrintWriterLogger(new PrintWriter(System.out),
+            XADirFile.class.getName(), false));
+    freMngr.start(); // start the FileResourceManager service, must be started
+  }                  // before using any of its methods
+
+  /**
+   * This method lists all the files under the transactional directory.
+   * It lists only files and not <code>File</code>s as in Java this may
+   * also mean directories.
+   * @return a list of <code>XADirFile</code> objects which represent
+   *         the files within the directory
+   */
+  public synchronized XADirFile[] listTXFiles() {
+    File dir = new File(freMngr.getStoreDir());
+    File[] files = dir.listFiles();
+    LinkedList<XADirFile> xaDirFileList = new LinkedList<XADirFile>();
+
+    for (File f : files) {
+      if (!f.isDirectory()) {
+        xaDirFileList.add(new XADirFile(f, this));
+      }
+    }
+    XADirFile[] xaDirFiles = new XADirFile[xaDirFileList.size()];
+    xaDirFileList.toArray(xaDirFiles);
+    return xaDirFiles;
+  }
+
+  /**
+   * This method must be used after a <code>TransactionManager</code>
+   * has begun and within the boundaries of a transaction (<code>begin,
+   * commit/rollback</code>).
+   * <p>
+   * The method also creates a new {@link XAFileResourceManager} and
+   * enlists it to the transaction obtained by the <code>txnMngr</code>.
+   *
+   * @param txnMngr the <code>TransactionManager</code> used to commit
+   *                or rollback the file operations
+   * @exception javax.transaction.RollbackException
+   *            if an error occurs while enlisting the <code>XAResource</code>
+   * @exception javax.transaction.SystemException
+   *            if there is a problem enlisting the XAResource created
+   *            within this method or when the <code>getTransaction</code> in the
+   *            <code>TransactionManager</code> fails or when the TransactionManager
+   *            is not in ready (<code>Status.ACTIVE</code>) mode
+   */
+  public synchronized void startTransactionOn(TransactionManager txnMngr)
+      throws SystemException, RollbackException {
+    curTxId = "txDir-" + freMngr.getWorkDir().replace('/', '_') + "_" +
+        Thread.currentThread().getId() + "!" + System.nanoTime();
+    XAFileResourceManager xafre = new XAFileResourceManager(freMngr, curTxId);
+    Transaction tx = txnMngr.getTransaction();
+    tx.enlistResource(xafre);
+  }
+
+  /**
+   * Returns the <code>FileResourceManager</code> object used to access
+   * transaction and file operations (e.g. startTransaction, copyResource).
+   *
+   * @return the <code>FileResourceManager</code> object
+   */
+  protected FileResourceManager getFreMngr() {
+    return freMngr;
+  }
+
+  /**
+   * This is the name of the "shadow" folder which keeps the changes whilst
+   * a transaction is still in progress.
+   *
+   * @return a <code>String</code> which contains the name of the "shadow"
+   *         folder
+   */
+  protected String getCurTxId() {
+    return curTxId;
+  }
+
+  /**
+   * Increases the counter of files in the directory by one
+   */
+  protected void increaseLength() {
+    length++;
+  }
+
+  /**
+   * Decreases the counter of files in the directory by one
+   */
+  protected void decreaseLength() {
+    length--;
+  }
+
+  /**
+   * Returns the number of files (not directories) under this
+   * transactional directory.
+   *
+   * @return a <code>long</code> representing the number of files
+   *         within the transactional directory
+   */
+  public long length() {
+    return length;
+  }
+
+  /**
+   * As this class represents a transactional directory, the application
+   * programmer must call this method after his transactional work is over.
+   * The method will release and remove any of the "shadow" files/folders
+   * used whilist the transaction was in progress.
+   * <p>
+   * If there are pending transactions the method will fail to close.
+   *
+   * @exception IOException if an I/O error occurs
+   */
+  public void close() throws IOException {
+    File store = new File (freMngr.getWorkDir());
+    if (store.list().length != 0) // pending txs exist
+      throw new IncompleteTransactionsException();
+
+    store.delete();
+    freMngr = null;
+  }
+}
\ No newline at end of file

Added: labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txdirs/dir/XADirFile.java
===================================================================
--- labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txdirs/dir/XADirFile.java	                        (rev 0)
+++ labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txdirs/dir/XADirFile.java	2008-08-29 12:58:31 UTC (rev 22026)
@@ -0,0 +1,162 @@
+/*     JBoss, Home of Professional Open Source Copyright 2008, Red Hat
+ *  Middleware LLC, and individual contributors as indicated by the
+ *  @author tags.
+ *     See the copyright.txt in the distribution for a full listing of
+ *  individual contributors. This copyrighted material is made available
+ *  to anyone wishing to use, modify, copy, or redistribute it subject to
+ *  the terms and conditions of the GNU Lesser General Public License, v. 2.1.
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY
+ *  or FITNESS FOR A PARTICULAR PURPOSE.
+ *     See the GNU Lesser General Public License for more details. You should
+ *  have received a copy of the GNU Lesser General Public License, v.2.1
+ *  along with this distribution; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA  02110-1301, USA.
+ *
+ *  (C) 2008,
+ *  @author Red Hat Middleware LLC.
+ */
+package org.jboss.jbossts.fileio.xalib.txdirs.dir;
+
+import org.apache.commons.transaction.file.ResourceManagerException;
+import org.apache.commons.transaction.file.FileResourceManager;
+import java.io.*;
+
+/**
+ * Instances of this class are used by {@link XADir} objects to
+ * apply file operations. These operations can include creating
+ * new, deletinig and renaming files.
+ * <p>
+ * Each of these file operations invoke methods from the Apache's
+ * {@link org.apache.commons.transaction.file.FileResourceManager} object
+ * to manipulate operations on the files.
+ *
+ * @see XADir
+ * @see org.apache.commons.transaction.file.FileResourceManager
+ *
+ * @author Ioannis Ganotis
+ * @version Aug 7, 2008
+ */
+public class XADirFile implements Serializable
+{
+  transient private FileResourceManager freMngr;
+  private String curTxId;
+  private String curObjId;
+  private XADir xadir;
+  private String filename;
+
+  /**
+   * Constructor to create <code>XADirFile</code> objects.
+   * These objects can be used to apply file operations.
+   *
+   * @param file the <code>File</code> object that represents
+   *        the file in the transactional directory
+   * @param xadir the transactional directory
+   */
+  public XADirFile(File file, XADir xadir) {
+    filename = file.getName();
+    this.freMngr = xadir.getFreMngr();
+    this.curTxId = xadir.getCurTxId();
+    curObjId = "/" + file.getName();
+    this.xadir = xadir;
+  }
+
+  /**
+   * Returns the name of the file.
+   *
+   * @return <code>String</code> representing the name of the
+   *         file in the transactional directory
+   */
+  public String getName() {
+    return filename;
+  }
+
+  /**
+   * Returns an InputStream containing the bytes of this
+   * <code>XADirFile</code> file.
+   *
+   * @return an <code>InputStream</code> object
+   * @exception ResourceManagerException ]
+   *            if an error in the <code>ResourceManager</code> occurs
+   */
+  public InputStream readResource() throws ResourceManagerException {
+    try {
+      String obj = freMngr.getStoreDir() + curObjId;
+      return new FileInputStream(new File(obj));
+    } catch (IOException ioe) {
+      ioe.printStackTrace();
+    }
+    return null;
+  }
+
+  /**
+   * Returns an OutputStream containing the bytes written to this
+   * <code>XADirFile</code> file.
+   *
+   * @return an <code>OutputStream</code>
+   * @throws ResourceManagerException
+   *         if an error in the <code>ResourceManager</code> occurs
+   */
+  public OutputStream writeResource() throws ResourceManagerException {
+    return freMngr.writeResource(curTxId, curObjId);
+  }
+
+  /**
+   * Renames this file to the name of the file given by <code>file</code>.
+   *
+   * @param file the <codeFile</code> object that contains the new file name
+   * @return true if the rename operations completed successfully;false otherwise
+   *
+   */
+  public synchronized boolean renameTo(File file) {
+    String resId = "/" + file.getName();
+    try {
+      freMngr.lockResource(curObjId, curTxId, false, false, 0, true);
+      freMngr.copyResource(curTxId, curObjId, resId, true);
+      freMngr.deleteResource(curTxId, curObjId);
+      curObjId = resId;
+      filename = file.getName();
+      return true;
+    } catch (ResourceManagerException e) {
+      e.printStackTrace();
+    }
+    return false;
+  }
+
+  /**
+   * Create a new file in the disk. If the file already exists the method
+   * will return false; otherwise true.
+   *
+   * @return true if the file was created successfully; false otherwise
+   */
+  public boolean createNewFile() {
+    try {
+      freMngr.createResource(curTxId, curObjId, false);
+      xadir.increaseLength();
+      return true;
+    } catch (ResourceManagerException e) {
+      e.printStackTrace();
+    }
+    return false;
+  }
+
+  /**
+   * This method will delete the file. If the file does not
+   * exist it will return false; Otherwise true.
+   *
+   * @return true if the file could be deleted successfully;
+   *         false otherwise.
+   */
+  public boolean delete() {
+    try {
+      freMngr.lockResource(curObjId, curTxId, false, false, 0, true);
+      freMngr.deleteResource(curTxId, curObjId, false);
+      xadir.decreaseLength();
+      return true;
+    } catch (ResourceManagerException e) {
+      e.printStackTrace();
+    }
+    return false;
+  }
+}
\ No newline at end of file

Added: labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txdirs/dir/XAFileResourceManager.java
===================================================================
--- labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txdirs/dir/XAFileResourceManager.java	                        (rev 0)
+++ labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txdirs/dir/XAFileResourceManager.java	2008-08-29 12:58:31 UTC (rev 22026)
@@ -0,0 +1,294 @@
+/*     JBoss, Home of Professional Open Source Copyright 2008, Red Hat
+ *  Middleware LLC, and individual contributors as indicated by the
+ *  @author tags.
+ *     See the copyright.txt in the distribution for a full listing of
+ *  individual contributors. This copyrighted material is made available
+ *  to anyone wishing to use, modify, copy, or redistribute it subject to
+ *  the terms and conditions of the GNU Lesser General Public License, v. 2.1.
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY
+ *  or FITNESS FOR A PARTICULAR PURPOSE.
+ *     See the GNU Lesser General Public License for more details. You should
+ *  have received a copy of the GNU Lesser General Public License, v.2.1
+ *  along with this distribution; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA  02110-1301, USA.
+ *
+ *  (C) 2008,
+ *  @author Red Hat Middleware LLC.
+ */
+package org.jboss.jbossts.fileio.xalib.txdirs.dir;
+
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+import javax.transaction.xa.XAException;
+import java.io.Serializable;
+import java.io.ObjectInputStream;
+import java.io.IOException;
+import java.io.File;
+
+import org.apache.commons.transaction.file.*;
+import org.apache.commons.transaction.util.CommonsLoggingLogger;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.jbossts.fileio.xalib.Globals;
+
+/**
+ * This class implements methods of the standard {@link javax.transaction.xa.XAResource} interface
+ * which acts like a contract between a Resource Manager and a Transaction
+ * Manager.
+ * <p>
+ * Each instance of an <code>XAFileResourceManager</code> has its own {@link javax.transaction.xa.Xid}
+ * which distinguishes by the other objects of this class and is associated
+ * with a Transaction. It also has a unique transaction id which is represented by
+ * a <code>String</code> and is used by {@link org.apache.commons.transaction.file.FileResourceManager}
+ * to know which transaction to start, commit/rollback etc.
+ * <p>
+ * Any changes made within a transaction specified by the <code>Xid</code> mentioned above
+ * will be applied to the transactional directory only after this <code>XAFileResourceManager</code>
+ * has commited. If the decision is to rollback then all the modifications made within the transaction
+ * are removed.
+ *
+ * @author Ioannis Ganotis
+ * @version Aug 6, 2008
+ */
+public class XAFileResourceManager implements XAResource, Serializable
+{
+  private Xid currentXid;
+  private String curTxId;
+  transient private FileResourceManager freMngr; // todo must be setializable
+  private boolean recovers;
+  private String storeDir;
+
+  /**
+   * Constructor to create Resource Manager objects. Each of these
+   * objects, at transaction time, are informed by the Transaction
+   * Manager to prepare, commit or rollback (depending on the outcome
+   * of the 2PC protocol).
+   *
+   * @param freMngr the Resource Manager on which methods like start, commit
+   *                or rollback a transaction will be applied
+   * @param curTxId the unique transaction id used by <code>freMngr</code> to
+   *                know on which transaction to work
+   */
+  public XAFileResourceManager(FileResourceManager freMngr, String curTxId) {
+    this.freMngr = freMngr;
+    this.curTxId = curTxId;
+    storeDir = freMngr.getStoreDir();
+    recovers = false;
+  }
+
+  /**
+   * Acts like the {@link org.apache.commons.transaction.file.FileResourceManager#prepareTransaction(Object)}
+   * method does.
+   *
+   * @param xid the global transaction id
+   * @throws XAException
+   *         if a <code>ResourceManagerException</code> is thrown
+   */
+  public int prepare(Xid xid) throws XAException {
+    // flush data on disk here
+    System.out.println("XAFileResourceManager.prepare(Xid=" + xid + ")");
+    try {
+      return freMngr.prepareTransaction(curTxId);
+    } catch (ResourceManagerException rme) {
+      throw new XAException(rme.getMessage());
+    }
+  }
+
+  /**
+   * Method to commit the global transaction with the given <code>xid</code>.
+   * <p/>
+   * It also acts like the {@link org.apache.commons.transaction.file.FileResourceManager#commitTransaction(Object)}
+   * does.
+   *
+   * @param xid      a global Transaction id
+   * @param onePhase If true, the resource manager should use a one-phase
+   *                 commit protocol to commit the work done on behalf of xid
+   * @throws XAException
+   *         if a <code>ResourceManagerException</code> is thrown
+   */
+  public void commit(Xid xid, boolean onePhase) throws XAException {
+    System.out.println("XAFileResourceManager.commit(Xid=" + xid + ", onePhase=" +
+        onePhase + ")");
+    if (!xid.equals(currentXid)) {
+      System.out.println("XAFileResourceManager.commit - wrong Xid!");
+    }
+    try {
+      if (!recovers) {
+        freMngr.commitTransaction(curTxId);
+      } else {
+        // the initFREM() method will take care of incomplete txs
+      }
+    } catch (ResourceManagerException rme) {
+      throw new XAException(rme.getMessage());
+    }
+    currentXid = null;
+  }
+
+  /**
+   * Ends the work performed on behalf of a transaction branch.
+   *
+   * @param xid   a global transaction identifier that is the same as what was used
+   *              previously in the start method
+   * @param flags (can be anything)
+   */
+  public void end(Xid xid, int flags) {
+    System.out.println("XAFileResourceManager.end(Xid=" + xid + ", flags=" + flags + ")");
+  }
+
+  /**
+   * Forget about a heuristically completed transaction branch.
+   * The <code>currentXid</code> is set to null
+   *
+   * @param xid a global Transaction id
+   */
+  public void forget(Xid xid) {
+    System.out.println("XAFileResourceManager.forget(Xid=" + xid + ")");
+    if (!xid.equals(currentXid)) {
+      System.out.println("XAFileResourceManager.forget - wrong Xid!");
+    }
+    currentXid = null;
+  }
+
+  /**
+   * Obtain the current transaction timeout value set for this
+   * <code>XAFileResourceManager</code> instance. If
+   * <code>XAFileResourceManager.setTransactionTimeout</code> was not used prior to
+   * invoking this method, the return value is the default timeout set for
+   * the resource manager; otherwise, the value used in the previous
+   * <code>setTransactionTimeout</code> call is returned.
+   *
+   * @return the transaction timeout value in seconds
+   */
+  public int getTransactionTimeout() throws XAException {
+    try {
+      int timeout = (int) freMngr.getTransactionTimeout(curTxId) / 1000; // ms -> secs
+      System.out.println("XAFileResourceManager.getTransactionTimeout() [returning " + timeout + "]");
+      return timeout;
+    } catch (ResourceManagerException rme) {
+      throw new XAException(rme.getMessage());
+    }
+  }
+
+  /*
+  * No implementation.
+  * @param xares an XAResource object whose resource manager instance is to
+  *              be compared with the resource manager instance of the target
+  *              object
+  * @return always false
+  */
+  public boolean isSameRM(XAResource xares) throws XAException {
+    System.out.println("XAFileResourceManager.isSameRM(xaresMngr=" + xares + ")");
+    return false;
+  }
+
+  /*
+  * No implementation.
+  * @param flag
+  * @return always zero xids
+  */
+  public Xid[] recover(int flag) throws XAException {
+    System.out.println("XAFileResourceManager.recover(flag=" + flag + ")");
+    return new Xid[0];
+  }
+
+  /**
+   * Rollback any updates attempted to be written to the directory.
+   * <p/>
+   * The method acts like the
+   * {@link org.apache.commons.transaction.file.FileResourceManager#rollbackTransaction(Object)}
+   * does.
+   * @param xid a global Transaction id
+   * @throws XAException
+   *         if a <code>ResourceManagerException</code> is thrown
+   */
+  public void rollback(Xid xid) throws XAException {
+    System.out.println("XAFileResourceManager.rollback(Xid=" + xid + ")");
+    try {
+      freMngr.rollbackTransaction(curTxId);
+    } catch (ResourceManagerException rme) {
+      throw new XAException(rme.getMessage());
+    }
+    currentXid = null;
+  }
+
+  /**
+   * Set the current transaction <code>timeout</code> value for this
+   * <code>XAFileResourceManager</code> instance. Once set, this timeout value is
+   * effective until <code>setTransactionTimeout</code> is invoked again with
+   * a different value.
+   * The method acts like the
+   * {@link org.apache.commons.transaction.file.FileResourceManager#setTransactionTimeout(Object, long)}
+   * does.
+   *
+   * @param seconds transaction timeout value in seconds
+   * @return true if transaction timeout value is set successfully;
+   *         otherwise false
+   */
+  public boolean setTransactionTimeout(int seconds) throws XAException {
+    System.out.println("XAFileResourceManager.setTransactionTimeout(timeout=" + seconds + ")");
+    try {
+      freMngr.setTransactionTimeout(curTxId, seconds * 1000);
+    } catch (ResourceManagerException rme) {
+      throw new XAException(rme.getMessage());
+    }
+    return false;
+  }
+
+  /**
+   * Start work on behalf of a transaction branch specified in <code>xid</code>.
+   * The method act like the
+   * {@link org.apache.commons.transaction.file.FileResourceManager#startTransaction(Object)}
+   * does.
+   * @param xid   a global Transaction id to be associated with this
+   *              Resource Manager instance
+   * @param flags (can be anything)
+   * @throws XAException if there is already a Transaction
+   */
+  public void start(Xid xid, int flags) throws XAException {
+    System.out.println("XAFileResourceManager.start(Xid=" + xid + ", flags=" +
+        flags + ")");
+    if (currentXid != null) {
+      System.out.println("XAFileResourceManager.start - wrong Xid!");
+      throw new XAException("Current Transaction is: <" + currentXid +
+          ">\nCannot start the new Transaction.");
+    }
+    try {
+      freMngr.startTransaction(curTxId);
+    } catch (ResourceManagerException rme) {
+      throw new XAException(rme.getMessage());
+    }
+    currentXid = xid;
+  }
+
+  /**
+   * Returns the global Transaction id associated with this
+   * <code>XAFileResourceManager</code>
+   * @return the global Transaction id associated with this
+   *         <code>XAFileResourceManager</code>
+   */
+  public Xid getCurrentXid() {
+    return currentXid;
+  }
+
+  /**
+   * After a system crash and upon recovery phase the <code>FileResourceManager</code>
+   * object needs to be re-initialised.
+   */
+  private void initFREM() {
+    String workDir = storeDir + "/" + Globals.WORK_DIR_NAME;
+    freMngr = new FileResourceManager(storeDir, workDir, false,
+        new CommonsLoggingLogger(LogFactory.getLog(XADir.class.getName())));
+    try {
+      freMngr.start(); // will automatically recover incomplete txs
+    } catch (ResourceManagerSystemException e) {
+      e.printStackTrace();
+    }
+  }
+
+  private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
+    in.defaultReadObject();
+    recovers = true; // indicate that the XAFileResourceManager recovers now
+    initFREM();
+  }
+}

Added: labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txdirs/exceptions/IncompleteTransactionsException.java
===================================================================
--- labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txdirs/exceptions/IncompleteTransactionsException.java	                        (rev 0)
+++ labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txdirs/exceptions/IncompleteTransactionsException.java	2008-08-29 12:58:31 UTC (rev 22026)
@@ -0,0 +1,56 @@
+/*     JBoss, Home of Professional Open Source Copyright 2008, Red Hat
+ *  Middleware LLC, and individual contributors as indicated by the
+ *  @author tags.
+ *     See the copyright.txt in the distribution for a full listing of
+ *  individual contributors. This copyrighted material is made available
+ *  to anyone wishing to use, modify, copy, or redistribute it subject to
+ *  the terms and conditions of the GNU Lesser General Public License, v. 2.1.
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY
+ *  or FITNESS FOR A PARTICULAR PURPOSE.
+ *     See the GNU Lesser General Public License for more details. You should
+ *  have received a copy of the GNU Lesser General Public License, v.2.1
+ *  along with this distribution; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA  02110-1301, USA.
+ *
+ *  (C) 2008,
+ *  @author Red Hat Middleware LLC.
+ */
+package org.jboss.jbossts.fileio.xalib.txdirs.exceptions;
+
+import java.io.IOException;
+
+/**
+ * Signals that there are incomplete transactions
+ * <p>
+ * The exception is mainly used by the
+ * {@link org.jboss.jbossts.fileio.xalib.txdirs.dir.XADir#close()} method when
+ * invoked by the application programmer while there are active transactions.
+ *
+ * @author Ioannis Ganotis
+ * @version Aug 23, 2008
+ */
+public class IncompleteTransactionsException extends IOException
+{
+  /**
+   * Constructs a <code>IncompleteTransactionsException</code> with
+   * <code>null</code> as its error detail message.
+   */
+  public IncompleteTransactionsException() {
+    super();
+  }
+
+  /**
+   * Constructs a <code>IncompleteTransactionsException</code> with
+   * the given <code>msg</code> as its detail message.
+   * <p>
+   * The string <code>msg</code> may later be retrieved by the
+   * {@link Throwable#getMessage()} method of class <code>java.lang.Throwable</code>
+   * @param msg the detail message
+   */
+  public IncompleteTransactionsException(String msg) {
+    super(msg);
+  }
+
+}

Added: labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txdirs/exceptions/NotDirectoryException.java
===================================================================
--- labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txdirs/exceptions/NotDirectoryException.java	                        (rev 0)
+++ labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txdirs/exceptions/NotDirectoryException.java	2008-08-29 12:58:31 UTC (rev 22026)
@@ -0,0 +1,55 @@
+/*     JBoss, Home of Professional Open Source Copyright 2008, Red Hat
+ *  Middleware LLC, and individual contributors as indicated by the
+ *  @author tags.
+ *     See the copyright.txt in the distribution for a full listing of
+ *  individual contributors. This copyrighted material is made available
+ *  to anyone wishing to use, modify, copy, or redistribute it subject to
+ *  the terms and conditions of the GNU Lesser General Public License, v. 2.1.
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY
+ *  or FITNESS FOR A PARTICULAR PURPOSE.
+ *     See the GNU Lesser General Public License for more details. You should
+ *  have received a copy of the GNU Lesser General Public License, v.2.1
+ *  along with this distribution; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA  02110-1301, USA.
+ *
+ *  (C) 2008,
+ *  @author Red Hat Middleware LLC.
+ */
+package org.jboss.jbossts.fileio.xalib.txdirs.exceptions;
+
+import java.io.IOException;
+
+/**
+ * Signals that a <ccode>File</code> is not a directory.
+ * <p>
+ * The exception is mainly used by the
+ * {@link org.jboss.jbossts.fileio.xalib.txdirs.dir.XADir} class when
+ * craeting new objects to ensure they are directories and not files.
+ *
+ * @author Ioannis Ganotis
+ * @version Aug 7, 2008
+ */
+public class NotDirectoryException extends IOException
+{
+  /**
+   * Constructs a <code>NotDirectoryException</code> with
+   * <code>null</code> as its error detail message.
+   */
+  public NotDirectoryException() {
+    super();
+  }
+
+  /**
+   * Constructs a <code>NotDirectoryException</code> with
+   * the given <code>msg</code> as its detail message.
+   * <p>
+   * The string <code>msg</code> may later be retrieved by the
+   * {@link Throwable#getMessage()} method of class <code>java.lang.Throwable</code>
+   * @param msg the detail message
+   */
+  public NotDirectoryException(String msg) {
+    super(msg);
+  }
+}

Added: labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txfiles/exceptions/DuplicateTransactionsException.java
===================================================================
--- labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txfiles/exceptions/DuplicateTransactionsException.java	                        (rev 0)
+++ labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txfiles/exceptions/DuplicateTransactionsException.java	2008-08-29 12:58:31 UTC (rev 22026)
@@ -0,0 +1,54 @@
+/*     JBoss, Home of Professional Open Source Copyright 2008, Red Hat
+ *  Middleware LLC, and individual contributors as indicated by the
+ *  @author tags.
+ *     See the copyright.txt in the distribution for a full listing of
+ *  individual contributors. This copyrighted material is made available
+ *  to anyone wishing to use, modify, copy, or redistribute it subject to
+ *  the terms and conditions of the GNU Lesser General Public License, v. 2.1.
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY
+ *  or FITNESS FOR A PARTICULAR PURPOSE.
+ *     See the GNU Lesser General Public License for more details. You should
+ *  have received a copy of the GNU Lesser General Public License, v.2.1
+ *  along with this distribution; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA  02110-1301, USA.
+ *
+ *  (C) 2008,
+ *  @author Red Hat Middleware LLC.
+ */
+package org.jboss.jbossts.fileio.xalib.txfiles.exceptions;
+
+import javax.transaction.xa.XAException;
+
+/**
+ * Signals that a Transaction with the same thread id already exists.
+ * <p>
+ * The exception is mainly used by the {@link org.jboss.jbossts.fileio.xalib.txfiles.file.XAFile} to disallow
+ * associating the same thread id with two different Transactions
+ * and two different {@link org.jboss.jbossts.fileio.xalib.txfiles.file.XAResourceManager}s.
+ * 
+ * @author Ioannis Ganotis
+ * @version Jul 30, 2008
+ */
+public class DuplicateTransactionsException extends XAException {
+  /**
+   * Constructs a <code>DuplicateTransactionsException</code> with
+   * <code>null</code> as its error detail message.
+   */
+  public DuplicateTransactionsException() {
+    super();
+  }
+
+  /**
+   * Constructs a <code>DuplicateTransactionsException</code> with
+   * the given <code>msg</code> as its detail message.
+   * <p>
+   * The string <code>msg</code> may later be retrieved by the
+   * {@link Throwable#getMessage()} method of class <code>java.lang.Throwable</code>
+   * @param msg the detail message
+   */
+  public DuplicateTransactionsException(String msg) {
+    super(msg);
+  }
+}

Added: labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txfiles/exceptions/LockRefusedException.java
===================================================================
--- labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txfiles/exceptions/LockRefusedException.java	                        (rev 0)
+++ labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txfiles/exceptions/LockRefusedException.java	2008-08-29 12:58:31 UTC (rev 22026)
@@ -0,0 +1,54 @@
+/*     JBoss, Home of Professional Open Source Copyright 2008, Red Hat
+ *  Middleware LLC, and individual contributors as indicated by the
+ *  @author tags.
+ *     See the copyright.txt in the distribution for a full listing of
+ *  individual contributors. This copyrighted material is made available
+ *  to anyone wishing to use, modify, copy, or redistribute it subject to
+ *  the terms and conditions of the GNU Lesser General Public License, v. 2.1.
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY
+ *  or FITNESS FOR A PARTICULAR PURPOSE.
+ *     See the GNU Lesser General Public License for more details. You should
+ *  have received a copy of the GNU Lesser General Public License, v.2.1
+ *  along with this distribution; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA  02110-1301, USA.
+ *
+ *  (C) 2008,
+ *  @author Red Hat Middleware LLC.
+ */
+package org.jboss.jbossts.fileio.xalib.txfiles.exceptions;
+
+import java.io.IOException;
+
+/**
+ * Signals that a lock cannot be granted to either read from or write
+ * to a Transactional file.
+ * <p>
+ * The exception is mainly used by {@link org.jboss.jbossts.fileio.xalib.txfiles.file.XAFile} in the attempt of
+ * reading from or writing to a file.
+ * 
+ * @author Ioannis Ganotis
+ * @version Jul 28, 2008
+ */
+public class LockRefusedException extends IOException {
+  /**
+   * Constructs a <code>LockRefusedException</code> with <code>null</code>
+   * as its error detail message.
+   */
+  public LockRefusedException() {
+    super();
+  }
+
+  /**
+   * Constructs a <code>LockRefusedException</code> with the
+   * given <code>msg</code> as its detail message.
+   * <p>
+   * The string <code>msg</code> may later be retrieved by the
+   * {@link Throwable#getMessage()} method of class <code>java.lang.Throwable</code>
+   * @param msg the detail message
+   */
+  public LockRefusedException(String msg) {
+    super(msg);
+  }
+}

Added: labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txfiles/file/DataRecord.java
===================================================================
--- labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txfiles/file/DataRecord.java	                        (rev 0)
+++ labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txfiles/file/DataRecord.java	2008-08-29 12:58:31 UTC (rev 22026)
@@ -0,0 +1,121 @@
+/*     JBoss, Home of Professional Open Source Copyright 2008, Red Hat
+ *  Middleware LLC, and individual contributors as indicated by the
+ *  @author tags.
+ *     See the copyright.txt in the distribution for a full listing of
+ *  individual contributors. This copyrighted material is made available
+ *  to anyone wishing to use, modify, copy, or redistribute it subject to
+ *  the terms and conditions of the GNU Lesser General Public License, v. 2.1.
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY
+ *  or FITNESS FOR A PARTICULAR PURPOSE.
+ *     See the GNU Lesser General Public License for more details. You should
+ *  have received a copy of the GNU Lesser General Public License, v.2.1
+ *  along with this distribution; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA  02110-1301, USA.
+ *
+ *  (C) 2008,
+ *  @author Red Hat Middleware LLC.
+ */
+package org.jboss.jbossts.fileio.xalib.txfiles.file;
+
+import org.jboss.jbossts.fileio.xalib.txfiles.file.XAFile;
+
+import java.io.Serializable;
+import java.io.IOException;
+
+/**
+ * This class represents a record when reading or writing from an
+ * {@link org.jboss.jbossts.fileio.xalib.txfiles.file.XAFile}.
+ *
+ * @author Ioannis Ganotis
+ * @version Jun 12, 2008
+ */
+public class DataRecord implements Serializable
+{
+  private long startPoint;
+  private int recordLength;
+  private int[] recordBytes;
+
+  /**
+   * Constructor to create <code>DataRecord</code> objects to be used while
+   * read/write operations are used in the <code>XAFile</code>. It is also used
+   * by the {@link org.jboss.jbossts.fileio.xalib.txfiles.file.XAResourceManager} after reading a log file and while trying
+   * to re-construct the records' information to be committed to the <code>XAFile</code>.
+   *
+   * @param startPoint the position in the file of the first byte in the <code>recordBytes</code>
+   *                   array
+   * @param recordLength the length of the updated bytes to commit
+   * @param recordBytes the actual updated bytes
+   * @exception  IOException if an I/O error occurs
+   */
+  protected DataRecord(long startPoint, int recordLength, int[] recordBytes)
+      throws IOException {
+    this.startPoint = startPoint;
+    this.recordLength = recordLength;
+    this.recordBytes = recordBytes;
+  }
+
+  /**
+   * Returns the updated bytes as an array of <code>Integer</code>s.
+   * @return an array of <code>int</code>s that contains the updated
+   *         bytes
+   */
+  protected int[] getIntBytes() {
+    return recordBytes;
+  }
+
+  /**
+   * Returns the position in the file of the first byte in the
+   * <code>recordBytes</code> array.
+   * @return a <code>long</code> which represents the starting
+   *         position of this record in the file
+   */
+  protected long getStartPosition() {
+    return startPoint;
+  }
+
+  /**
+   * Returns the length of this record
+   * @return an <code>int</code> which represents the length of
+   * this record
+   */
+  protected int getRecordLength() {
+    return recordLength;
+  }
+
+  /**
+   * Returns a <code>String</code> which contains all the updated bytes
+   * of this record.
+   * @return a <code>String</code> which represents the updated bytes of
+   *         this record
+   */
+  protected String getRecordStr() {
+    return toString(getIntBytes());
+  }
+
+  /**
+   * Returns a <code>byte</code> array which contains the updated bytes
+   * held by this record.
+   * @return an array of bytes which are the updates held by this record
+   */
+  protected byte[] getRecordBytes() {
+    return XAFile.getBytesFromInts(recordBytes);
+  }
+
+  /**
+   * Converts the given <code>ints</code> array into a <code>String</code>
+   * used to display a more readable representation of the updated bytes
+   * held by this record.
+   * @param ints the array of updated bytes to convert
+   * @return a <code>String</code> that incluldes the updated bytes in a
+   *         readable format
+   */
+  private String toString(int[] ints) {
+    String txt = "[ ";
+    for (int i : ints) {
+      txt += i + ", ";
+    }
+    return txt.substring(0, txt.length() - 2) + " ]";
+  }
+}
\ No newline at end of file

Added: labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txfiles/file/XAFile.java
===================================================================
--- labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txfiles/file/XAFile.java	                        (rev 0)
+++ labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txfiles/file/XAFile.java	2008-08-29 12:58:31 UTC (rev 22026)
@@ -0,0 +1,1389 @@
+/*     JBoss, Home of Professional Open Source Copyright 2008, Red Hat
+ *  Middleware LLC, and individual contributors as indicated by the
+ *  @author tags.
+ *     See the copyright.txt in the distribution for a full listing of
+ *  individual contributors. This copyrighted material is made available
+ *  to anyone wishing to use, modify, copy, or redistribute it subject to
+ *  the terms and conditions of the GNU Lesser General Public License, v. 2.1.
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY
+ *  or FITNESS FOR A PARTICULAR PURPOSE.
+ *     See the GNU Lesser General Public License for more details. You should
+ *  have received a copy of the GNU Lesser General Public License, v.2.1
+ *  along with this distribution; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA  02110-1301, USA.
+ *
+ *  (C) 2008,
+ *  @author Red Hat Middleware LLC.
+ */
+package org.jboss.jbossts.fileio.xalib.txfiles.file;
+
+import com.arjuna.ats.txoj.LockMode;
+import com.arjuna.ats.txoj.LockResult;
+import javax.transaction.*;
+import javax.transaction.xa.Xid;
+import java.util.Hashtable;
+import java.io.Closeable;
+import java.io.DataInput;
+import java.io.DataInputStream;
+import java.io.DataOutput;
+import java.io.EOFException;
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.RandomAccessFile;
+import java.io.Serializable;
+import java.io.UTFDataFormatException;
+import org.jboss.jbossts.fileio.DataOutputStream;
+import org.jboss.jbossts.fileio.xalib.txfiles.exceptions.LockRefusedException;
+import org.jboss.jbossts.fileio.xalib.txfiles.exceptions.DuplicateTransactionsException;
+import org.jboss.jbossts.fileio.xalib.txfiles.logging.RecordsLogger;
+import org.jboss.jbossts.fileio.xalib.txfiles.locking.XALockManager;
+import org.jboss.jbossts.fileio.xalib.txfiles.locking.XALock;
+import org.jboss.jbossts.fileio.xalib.Globals;
+
+/**
+ * Instances of this class support both reading/writing to a
+ * random access file and using the random access file with
+ * the support of Transactions. If <code>newTransaction</code> is
+ * invoked after a <code>TransactionManager</code> has been created
+ * and begun, the XAFile will automatically act as a Transactional File,
+ * otherwise it will act as a normal random access file with operations
+ * acting directly on the source file. If the XAFile is in Transactional
+ * mode then any changes (writes) will not affect directly the file, but
+ * will only take effect right after the <code>TransactionManager</code> invokes
+ * its own </em>commit</em> method which will cause the <code>commitUpdates</code>
+ * apply (write) the updated bytes to the source file.
+ * <p>
+ * Calling the <code>newTransaction</code> method twice from the same
+ * thread will cause a <code>DuplicateTransactionsException</code> to
+ * be thrown. As this XAFile class implements the <code>DataInput, DataOutput</code>
+ * interfaces all of their implemented read or write methods will throw an
+ * <code>IOException</code> like specified in the above interfaces and
+ * the read/write methods of the random access file used.
+ *
+ * @author Ioannis Ganotis
+ * @version Jun 10, 2008
+ *
+ * @see org.jboss.jbossts.fileio.xalib.txfiles.locking.XALockManager
+ * @see XAResourceManager
+ * @see RecordsLogger
+ * @see DataRecord
+ */
+public class XAFile implements DataInput, DataOutput, Serializable, Closeable
+{
+  private String filename;
+  private String mode;
+  transient private RandomAccessFile raf;
+  private Hashtable<Long, XAResourceManager> xares;
+  transient private XALockManager xaLockManager;
+  transient private File loggingFolder;
+  transient private File locksFolder;
+  transient private boolean transactionsEnabled;
+
+  /**
+   * Constructor to create objects that represent a Transactional
+   * File on which read and write operations can be applied with the
+   * presence of ACID semantics.
+   * 
+   * @param filename the name of the source file
+   * @param mode the access mode (as specified in the {@link java.io.RandomAccessFile})
+   * @param transactionsEnabled if true the XAFile will behave Transactionally and will
+   *                            allow commit/rollback operations, otherwise will behave
+   *                            as a normal random access file with read/write operations
+   *
+   * @exception FileNotFoundException
+   *            if the mode is <tt>"r"</tt> but the given string does not
+   *            denote an existing regular file, or if the mode begins with
+   *            <tt>"rw"</tt> but the given string does not denote an
+   *            existing, writable regular file and a new regular file of
+   *            that name cannot be created, or if some other error occurs
+   *            while opening or creating the file
+   * @exception IOException if an I/O error occurs
+   */
+  public XAFile(String filename, String mode, boolean transactionsEnabled)
+      throws IOException {
+    raf = new RandomAccessFile(filename, mode);
+    loggingFolder = new File(Globals.LOG_FOLDER_PATH);
+    locksFolder = new File(Globals.LOCKS_FOLDER_PATH);
+    this.filename = filename;
+    this.mode = mode;
+    this.transactionsEnabled = transactionsEnabled;
+    xares = new Hashtable<Long, XAResourceManager>();
+    initLocksHeld();
+
+    prepareFolders();
+  }
+
+  /**
+   * Method to create folders that are needed
+   * by the library
+   */
+  private void prepareFolders()
+  {
+    if (!loggingFolder.exists())
+      loggingFolder.mkdir();
+    if (!locksFolder.exists())
+      locksFolder.mkdir();
+  }
+
+  /**
+   * Method to create a new Transaction and enlist XAResources.
+   * <p>
+   * The transaction is enlisted in a new {@link XAResourceManager}
+   * and appropriate log files are created each time the method is invoked.
+   * It is important that this method is called after the {@link javax.transaction.TransactionManager}
+   * has began, in order to benefit from the Transactional effects.
+   * <p>
+   * This method can be used in a multi-threaded environemnt but each
+   * thread must call it once, otherwise a <code>DuplicateTransactionsException</code>
+   * will be thrown to prevent this.
+   *
+   * @param txnMngr the <code>TransactionManager</code> used to
+   *                commit or rollback any attempted modifications to the
+   *                source file
+   *
+   * @exception org.jboss.jbossts.fileio.xalib.txfiles.exceptions.DuplicateTransactionsException
+   *            When trying to call this method within the same thread
+   * @exception IOException
+   *            May be thrown if there is a problem with either creating
+   *            the <code>XAResourceManager</code> or the <code>RecordsLogger</code>
+   * @exception javax.transaction.SystemException
+   *            Will be thrown if there is a problem enlisting the XAResource created
+   *            within this method or when the <code>getTransaction</code> in the
+   *            <code>TransactionManager</code> fails or when the TransactionManager
+   *            is not in ready (<code>Status.ACTIVE</code>) mode
+   * @exception javax.transaction.RollbackException
+   *            Will be thrown if there is a problem while enlisting the resource to
+   *            the transaction
+   * @exception IllegalStateException
+   *            if the <code>transactionsEnabled</code> in the constructor of the
+   *            XAFile has been chosen to be false
+   */
+  public synchronized void newTransaction(TransactionManager txnMngr)
+      throws DuplicateTransactionsException, IOException, SystemException, RollbackException {
+    if (transactionsEnabled) {
+      if (txnMngr.getStatus() == Status.STATUS_ACTIVE)
+      {
+        long th_id = Thread.currentThread().getId();
+        if (!xares.containsKey(th_id)) {
+          String logName = loggingFolder.getPath() + '/' + th_id + '_' + System.nanoTime();
+
+          RecordsLogger log = new RecordsLogger(logName);
+
+          XAResourceManager xareMngr = new XAResourceManager(this, log, th_id);
+          xares.put(th_id, xareMngr);
+          Transaction txn = txnMngr.getTransaction();
+          txn.enlistResource(xareMngr);
+        } else
+        {
+          throw new DuplicateTransactionsException("Cannot create a new Transaction. " +
+              "There is already a thread with id=<" + th_id + "> associated with that " +
+              "Transaction.");
+        }
+      } else
+      {
+        throw new SystemException("The newTransaction() method must be called only " +
+            "when TransactionManager's status is ACTIVE, after the manager has begun.");
+      }
+    } else
+    {
+      throw new IllegalStateException("Transactional support is set to be disabled. " +
+          "Enable using the setTransactionsEnabled() method.");
+    }
+  }
+
+  /**
+   * Returns the <code>RandomAccessFile</code> object used to read/write
+   * @return the <code>RandomAccessFile</code> object associated with
+   *         this class to apply the read/write operations
+   */
+  public RandomAccessFile getRAF() {
+    return raf;
+  }
+
+  /**
+   * Closes this XAFile.
+   * <p>
+   * The method actually closes the random access file stream and releases
+   * any system resources associated with the stream and the Transactions.
+   * If this file has an associated channel then the channel is closed
+   * as well.
+   *
+   * @exception  IOException  if an I/O error occurs or if there are
+   *                          incomplete Transactions.
+   */
+  public void close() throws IOException {
+    if (!xares.isEmpty())
+        throw new IOException("Failed to close the file. There are incomplete Transactions."); //todo better rollback??
+    raf.close();
+    if (xaLockManager.obtainHeldLocksWith(null).isEmpty()) // if the file is not  empty,
+      xaLockManager.deleteFile();      // possibly another VM has written to it, so
+  }                                    // do not delete it
+
+  /**
+   * Gets the <code>FileDescriptor</code> of the
+   * random access file used and forces synchronization.
+   *
+   * This method is used at the <code>prepare</code> phase of an
+   * <code>{@link XAResourceManager}</code>.
+   *
+   * @exception IOException if an I/O error occurs
+   */
+  protected void sync() throws IOException {
+    FileDescriptor fd = raf.getFD();
+    fd.sync();
+  }
+
+  /**
+   * Forces data to be written to disk by instantly closing and re-opening
+   * the random access file. The file pointer returns to the correct
+   * position after re-opening the file.
+   *
+   * @exception IOException if an I/O error occurs
+   */
+  public synchronized void flush() throws IOException {
+    long curPos = raf.getFilePointer();
+    raf.close();
+    raf = new RandomAccessFile(filename, mode);
+    raf.seek(curPos);
+  }
+
+  /**
+   * Sets the file-pointer offset, measured from the beginning of this
+   * file, at which the next read or write occurs.  The offset may be
+   * set beyond the end of the file. Setting the offset beyond the end
+   * of the file does not change the file length.  The file length will
+   * change only by writing after the offset has been set beyond the end
+   * of the file.
+   *
+   * @param      position   the offset position, measured in bytes from the
+   *                        beginning of the file, at which to set the file
+   *                        pointer.
+   * @exception  IOException  if <code>position</code> is less than
+   *                          <code>0</code> or if an I/O error occurs.
+   */
+  public void seek(long position) throws IOException {
+    raf.seek(position);
+  }
+
+  /**
+   * Method to enable Transactional support in the file
+   * <p>
+   * If the transactions are enabled and a read/write operation is invoked
+   * outside the scope of begin-commit/rollback an exception will be thrown
+   * as specified in the <code>newTransaction</code> method. To use these
+   * operations in that way set transaction support to false. 
+   * @param transactionsEnabled if true, the XAFile will create transactions
+   *                            and will allow commit/rollback operations in
+   *                            the <code>TransactionManager.</code>
+   */
+  public void setTransactionsEnabled(boolean transactionsEnabled) {
+    this.transactionsEnabled = transactionsEnabled;
+  }
+
+  /**
+   * Returns a standard error message based on the given <code>th_id</code>
+   * @param th_id the thread id participating in the generated message
+   * @return a standard error message based on the given <code>th_id</code>
+   */
+  private String getErrMsg(long th_id)
+  {
+    return "Failed to update source file. " +
+        "The thread with id=<" + th_id + "> is not associated with any Transaction";
+  }
+
+  /**
+   * Method to update a series of bytes in the file starting from a
+   * given <code>position</code>.
+   * <p>
+   * The method is called after an {@link XAResourceManager} is
+   * ready to commit. It copies <code>data</code> of exact <code>recordLength</code>
+   * and starting from position <code>position</code> in the source file.
+   *
+   * @param position the position in the file to start copying <code>data</code>
+   * @param recordLength the length of bytes to be copied
+   * @param data the actual data/updates
+   * @param th_id the thread associated with the Transaction trying to commit
+   * @exception IOException if an I/O error occurs
+   * @exception IllegalStateException
+   *            if the given <code>th_id</code> is not associated with a
+   *            Transaction
+   */  
+  protected synchronized void commitUpdates(long position, int recordLength, byte[] data,
+                                            long th_id) throws IOException {
+    if (th_id != Globals.RECOVERY_ID && th_id != getCurrentThreadId())
+      throw new IllegalStateException(getErrMsg(th_id));
+    long curPos = raf.getFilePointer();
+    commitUpdates(position, recordLength, data);
+    raf.seek(curPos);
+  }
+
+  /**
+   * Method to update a series of bytes in the file starting from a
+   * given <code>position</code>.
+   * <p>
+   * The method is called after an {@link XAResourceManager} is
+   * ready to commit. It copies <code>data</code> of exact <code>recordLength</code>
+   * and starting from position <code>position</code> in the source file.
+   *
+   * @param position the position in the file to start copying <code>data</code>
+   * @param recordLength the length of bytes to be copied
+   * @param data the actual data/updates
+   * @exception IOException if an I/O error occurs
+   */
+  private void commitUpdates(long position, int recordLength, byte[] data) throws IOException
+  {
+    raf.seek(position);
+    raf.write(data, 0, recordLength);
+  }
+
+  /**
+   * Disassociates a current thread from an existing Transaction.
+   * <p>
+   * After a <code>TransactionManager</code>'s commit/rollback operations
+   * this method is invoked to remove the thread registered by the
+   * <code>newTransaction</code> method.
+   * 
+   * @param xid the thread as a key to remove the corresponding
+   *              <code>XAResourceManager</code> from the list.
+   * @param recovers true if the system has crashed and tries to recover;
+   *                 otherwise false
+   * @exception IOException
+   *         if an I/O error occurs or there is no registered thread
+   *         with the given <code>th_id</code>
+   */
+  protected synchronized void removeTransaction(Xid xid, boolean recovers)
+      throws IOException {
+    if (!recovers) {
+      long th_id = getCurrentThreadId();
+      xares.remove(th_id);
+    }
+    xaLockManager.releaseLocks(xid);
+  }
+
+  /**
+   * Fill the list of locks held while trying to read/write to
+   * the file.
+   *
+   * @exception IOException if an I/O error occurs
+   */
+  protected void initLocksHeld() throws IOException {
+    xaLockManager = new XALockManager(filename);
+  }
+
+  /**
+   * Internal method to ask from {@link org.jboss.jbossts.fileio.xalib.txfiles.locking.XALockManager} to apply
+   * a read/write lock on a given <code>DataRecord</code>.
+   * <p>
+   * The method is invoked by read/write operations within the
+   * XAFile to lock on a specific range of bytes in the file.
+   * @param dr the record to lock on, either in read or write mode
+   * @param xid the {@link javax.transaction.xa.Xid} of the current
+   *        {@link XAResourceManager}
+   * @param mode read/write modes as specified in the
+   *             {@link com.arjuna.ats.txoj.LockMode} class
+   * @return the {@link com.arjuna.ats.txoj.LockResult} depending on
+   *         whether the lock can be <em>GRANTED or REFUSED</em>
+   * @exception IOException if an I/O error occurs
+   * @exception org.jboss.jbossts.fileio.xalib.txfiles.exceptions.LockRefusedException if lock cannot be <em>GRANTED</em>
+   */
+  private int acquireLockOn(DataRecord dr, Xid xid, int mode) throws IOException {
+    XALock xaLock = new XALock(xid, mode, dr.getStartPosition(), dr.getRecordLength());
+    int res = xaLockManager.tryLock(xaLock);//LockManager.waitTotalTimeout);
+
+    if (res == LockResult.REFUSED) {
+      String msg = "REFUSED:WRITE_LOCK on byte(s): " + dr.getRecordStr();
+      if (mode == LockMode.READ) {
+        msg = "REFUSED:READ_LOCK on byte(s): " + dr.getRecordStr();
+      }
+      throw new LockRefusedException(msg);
+    } else if (res == LockResult.GRANTED) {
+      String msg = "GRANTED:WRITE_LOCK on byte(s): " + dr.getRecordStr();
+      if (mode == LockMode.READ) {
+        msg = "GRANTED:READ_LOCK on byte(s): " + dr.getRecordStr();
+      }
+//      System.out.println(msg);
+    }
+    return res;
+  }
+
+  /**
+   * Returns the name of the file
+   * @return the name of the file
+   */
+  public String getFilename() {
+    return filename;
+  }
+
+  /**
+   * Returns the access mode in which the <code>XAFile</code> was
+   * created
+   * @return the access mode which was set when created the
+   *         <code>XAFile</code> object
+   */
+  public String getMode() {
+    return mode;
+  }
+
+  /**
+   * Internal method used by read operations in this <code>XAFile</code>.
+   * If the class is used in the Transactional mode (Transactions are enabled)
+   * the method tries to read bytes from memory. If that fails it means no
+   * previous write operations applied on the same range of bytes so the
+   * method will try to read and return the bytes as read directly from the
+   * source file. If Transactions are disabled the method does not make any
+   * attempts to find if there are any modified bytes by previous write
+   * operations and so it reads directly from the file.
+   * <p>
+   * The method starts reading bytes at the current file pointer. If data
+   * are retrieved from the memory instead of the actual file, the file
+   * pointer progresses by <code>len</code> steps, if successful.
+   * @param len the length of data to read
+   * @return the bytes read into an array of Integers
+   * @exception IOException          if an I/O error occurs 
+   * @exception org.jboss.jbossts.fileio.xalib.txfiles.exceptions.LockRefusedException if a lock cannot be <code>GRANTED</code>
+   */
+  private synchronized int[] readRecord(int len) throws IOException {
+    if (transactionsEnabled) {
+      long curThread = getCurrentThreadId();
+      XAResourceManager xare = xares.get(curThread);
+
+      Hashtable<Long, Integer> updatedBytes = xare.getUpdatedBytes();
+      int[] upds = new int[len];
+      long startPos = raf.getFilePointer();
+      int i;
+      for (i=0;i<len;i++) {
+//        if (startPos >= raf.length())
+//          return null;
+        if (updatedBytes.containsKey(startPos)) {
+          upds[i] = updatedBytes.get(startPos++);
+          raf.seek(raf.getFilePointer()+1);
+        } else {
+          upds[i] = raf.read();
+        }
+      }
+      DataRecord dr = new DataRecord(raf.getFilePointer()-len, len, upds);
+      acquireLockOn(dr, xare.getXid(), LockMode.READ);
+      return upds;
+    }
+    return readDirectlyFromFile(len);
+  }
+
+  /**
+   * Method to read exactly <code>len</code> bytes
+   * directly from the file and starting at the current file
+   * pointer.
+   *
+   * @param len the length of bytes to read from the file
+   * @return the bytes read into an Integer array
+   * @exception IOException if an I/O error occurs
+   */
+  public int[] readDirectlyFromFile(int len) throws IOException {
+    int[] buffer = new int[len];
+    for (int b=0; b<len; b++) {
+      buffer[b] = raf.read();
+    }
+    return buffer;
+  }
+
+  /**
+   * Reads a <code>boolean</code> from this file. This method reads a
+   * single byte from the <code>readByte</code> method, starting at
+   * the current file pointer. A value of <code>0</code> represents
+   * <code>false</code>. Any other value represents <code>true</code>.
+   * This method blocks until the byte is read, the end of the stream
+   * is detected, or an exception is thrown.
+   *
+   * @return     the <code>boolean</code> value read.
+   * @exception  EOFException  if this file has reached the end.
+   * @exception  IOException   if an I/O error occurs.
+   */  
+  public boolean readBoolean() throws IOException {
+    int ch = readByte();
+    if (ch < 0) {
+      throw new EOFException();
+    }
+    return (ch != 0);
+  }
+
+  /**
+   * Reads a <code>double</code> from this file. This method reads a
+   * <code>long</code> value, starting at the current file pointer,
+   * as if by the <code>readLong</code> method
+   * and then converts that <code>long</code> to a <code>double</code>
+   * using the <code>longBitsToDouble</code> method in
+   * class <code>Double</code>.
+   * <p>
+   * This method blocks until the eight bytes are read, the end of the
+   * stream is detected, or an exception is thrown.
+   *
+   * @return     the next eight bytes of this file, interpreted as a
+   *             <code>double</code>.
+   * @exception  EOFException  if this file reaches the end before reading
+   *             eight bytes.
+   * @exception  IOException   if an I/O error occurs.
+   * @see        java.io.RandomAccessFile#readLong()
+   * @see        java.lang.Double#longBitsToDouble(long)
+   */
+  public double readDouble() throws IOException {
+    return Double.longBitsToDouble(readLong());
+  }
+
+  /**
+   * Reads an unsigned 16-bit number from this file. This method gets
+   * the two bytes return from the <code>readRecord</code> method,
+   * starting at the current file pointer. If the bytes read, in order, are
+   * <code>b1</code> and <code>b2</code>, where
+   * <code>0&nbsp;&lt;=&nbsp;b1, b2&nbsp;&lt;=&nbsp;255</code>,
+   * then the result is equal to:
+   * <blockquote><pre>
+   *     (b1 &lt;&lt; 8) | b2
+   * </pre></blockquote>
+   * <p>
+   * This method blocks until the two bytes are read, the end of the
+   * stream is detected, or an exception is thrown.
+   *
+   * @return     the next two bytes of this file (or memory if there are
+   *             uncommitted changes), interpreted as an unsigned
+   *             16-bit integer.
+   * @exception  EOFException  if this file reaches the end before reading
+   *                           two bytes.
+   * @exception  IOException   if an I/O error occurs.
+   */
+  public int readUnsignedShort() throws IOException {
+    int[] ints = readRecord(Short.SIZE/Byte.SIZE);
+
+    int ch1 = ints[0];
+    int ch2 = ints[1];
+    if ((ch1 | ch2) < 0)
+      throw new EOFException();
+
+    return (ch1 << 8) + (ch2);
+  }
+
+  /**
+   * Reads <code>bytes.length</code> bytes from this file(or memory if there
+   * are uncommitted updated bytes) into the byte
+   * array, starting at the current file pointer. This method reads
+   * repeatedly until the requested number of bytes are read. This
+   * method blocks until the requested number of bytes are read,
+   * the end of the stream is detected, or an exception is thrown.
+   *
+   * @param      bytes   the buffer into which the data is read.
+   * @exception  EOFException  if this file reaches the end before reading
+   *               all the bytes.
+   * @exception  IOException   if an I/O error occurs.
+   */
+  public void readFully(byte[] bytes) throws IOException {
+    readFully(bytes, 0, bytes.length);
+  }
+
+  /**
+   * Reads exactly <code>len</code> bytes from this file(or memory if there
+   * are uncommitted updated bytes) into the byte
+   * array, starting at the current file pointer. This method reads
+   * repeatedly until the requested number of bytes are read. This
+   * method blocks until the requested number of bytes are read,
+   * the end of the stream is detected, or an exception is thrown.
+   *
+   * @param      bytes   the buffer into which the data is read.
+   * @param      off   the start offset of the data.
+   * @param      len   the number of bytes to read.
+   * @exception  EOFException  if this file reaches the end before reading
+   *                           all the bytes.
+   * @exception  IOException   if an I/O error occurs.
+   * @exception IndexOutOfBoundsException
+   *            if offset is negative, or len is negative, or offset+len is
+   *            greater than the size of the <code>bytes</code> array
+   */
+  public void readFully(byte[] bytes, int off, int len) throws IOException {
+    if (off < 0 || len < 0 || off + len > bytes.length)
+      throw new IndexOutOfBoundsException("bytes.length=" + bytes.length +
+          ", off=" + off + ", len=" + len);
+
+    byte[] bs = getBytesFromInts(readRecord(len));
+    System.arraycopy(bs, 0, bytes, off, len);
+//    for (int b = off; b < off + len; b++) {
+//      bytes[b] = readByte();
+//    }
+  }
+
+  /**
+   * Reads a signed 16-bit number from this file. The method reads two
+   * bytes from this file (or memory if there are uncommitted byte updates),
+   * starting at the current file pointer. If the two bytes read, in order,
+   * are <code>b1</code> and <code>b2</code>, where each of the two values is
+   * between <code>0</code> and <code>255</code>, inclusive, then the
+   * result is equal to:
+   * <blockquote><pre>
+   *     (short)((b1 &lt;&lt; 8) | b2)
+   * </pre></blockquote>
+   * <p>
+   * This method blocks until the two bytes are read, the end of the
+   * stream is detected, or an exception is thrown.
+   *
+   * @return     the next two bytes of this file(memory), interpreted as a signed
+   *             16-bit number.
+   * @exception  EOFException  if this file reaches the end before reading
+   *                           two bytes.
+   * @exception  IOException   if an I/O error occurs.
+   */
+  public short readShort() throws IOException {
+    int[] ints = readRecord(Short.SIZE/Byte.SIZE);
+
+    int ch1 = ints[0];
+    int ch2 = ints[1];
+    if ((ch1 | ch2) < 0) {
+      throw new EOFException();
+    }
+    return (short) ((ch1 << 8) + (ch2));
+  }
+
+  /**
+   * Reads in a string from this file (or memory if there are uncommitted
+   * byte updates). The string has been encoded using a
+   * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
+   * format.
+   * <p>
+   * The first two bytes are read, starting from the current file
+   * pointer, as if by
+   * <code>readUnsignedShort</code>. This value gives the number of
+   * following bytes that are in the encoded string, not
+   * the length of the resulting string. The following bytes are then
+   * interpreted as bytes encoding characters in the modified UTF-8 format
+   * and are converted into characters.
+   * <p>
+   * This method blocks until all the bytes are read, the end of the
+   * stream is detected, or an exception is thrown.
+   *
+   * @return     a Unicode string.
+   * @exception  EOFException
+   *             if this file reaches the end before reading all the bytes.
+   * @exception  IOException             if an I/O error occurs.
+   * @exception  UTFDataFormatException
+   *             if the bytes do not represent
+   *             valid modified UTF-8 encoding of a Unicode string.
+   * @see        java.io.RandomAccessFile#readUnsignedShort()
+   */
+  public String readUTF() throws IOException {
+    return DataInputStream.readUTF(this);
+  }
+
+  /**
+   * Reads a <code>float</code> from this file (or memory if there are
+   * uncommitted byte updates). This method reads an 
+   * <code>int</code> value, starting at the current file pointer,
+   * as if by the <code>readInt</code> method
+   * and then converts that <code>int</code> to a <code>float</code>
+   * using the <code>intBitsToFloat</code> method in class
+   * <code>Float</code>.
+   * <p>
+   * This method blocks until the four bytes are read, the end of the
+   * stream is detected, or an exception is thrown.
+   *
+   * @return     the next four bytes of this file, interpreted as a
+   *             <code>float</code>.
+   * @exception  EOFException  if this file reaches the end before reading
+   *             four bytes.
+   * @exception  IOException   if an I/O error occurs.
+   * @see        java.io.RandomAccessFile#readInt()
+   * @see        java.lang.Float#intBitsToFloat(int)
+   */
+  public float readFloat() throws IOException {
+    return Float.intBitsToFloat(readInt());
+  }
+
+  /**
+   * Reads a signed 32-bit integer from this file (or memory if there
+   * are uncommitted byte updates). This method reads 4
+   * bytes from the file, starting at the current file pointer.
+   * If the bytes read, in order, are <code>b1</code>,
+   * <code>b2</code>, <code>b3</code>, and <code>b4</code>, where
+   * <code>0&nbsp;&lt;=&nbsp;b1, b2, b3, b4&nbsp;&lt;=&nbsp;255</code>,
+   * then the result is equal to:
+   * <blockquote><pre>
+   *     (b1 &lt;&lt; 24) | (b2 &lt;&lt; 16) + (b3 &lt;&lt; 8) + b4
+   * </pre></blockquote>
+   * <p>
+   * This method blocks until the four bytes are read, the end of the
+   * stream is detected, or an exception is thrown.
+   *
+   * @return     the next four bytes of this file, interpreted as an
+   *             <code>int</code>.
+   * @exception  EOFException  if this file reaches the end before reading
+   *               four bytes.
+   * @exception  IOException   if an I/O error occurs.
+   */
+  public int readInt() throws IOException {
+    int[] ints = readRecord(Integer.SIZE/Byte.SIZE);
+
+    int ch1 = ints[0];
+    int ch2 = ints[1];
+    int ch3 = ints[2];
+    int ch4 = ints[3];
+    if ((ch1 | ch2 | ch3 | ch4) < 0) {
+      throw new EOFException();
+    }
+    return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4));
+  }
+
+  /**
+   * Reads an unsigned eight-bit number from this file (or memory if there
+   * are uncommitted byte updates). This method reads
+   * a byte, starting at the current file pointer, and returns that byte.
+   * <p>
+   * This method blocks until the byte is read, the end of the stream
+   * is detected, or an exception is thrown.
+   *
+   * @return     the next byte of this file, interpreted as an unsigned
+   *             eight-bit number.
+   * @exception  EOFException  if this file has reached the end.
+   * @exception  IOException   if an I/O error occurs.
+   */
+  public int readUnsignedByte() throws IOException {
+    int ch = readByte();
+    if (ch < 0) {
+      throw new EOFException();
+    }
+    return ch;
+  }
+
+  /**
+   * Reads a signed eight-bit value from this file (or memory if there
+   * are uncommitted byte updates). This method reads a
+   * byte, starting from the current file pointer. If the byte read is
+   * <code>b</code>, where <code>0&nbsp;&lt;=&nbsp;b&nbsp;&lt;=&nbsp;255</code>,
+   * then the result is:
+   * <blockquote><pre>
+   *     (byte)(b)
+   * </pre></blockquote>
+   * <p>
+   * This method blocks until the byte is read, the end of the stream
+   * is detected, or an exception is thrown.
+   *
+   * @return     the next byte of this file as a signed eight-bit
+   *             <code>byte</code>.
+   * @exception  EOFException  if this file has reached the end.
+   * @exception  IOException   if an I/O error occurs.
+   */
+  public byte readByte() throws IOException {
+    int[] ints = readRecord(Byte.SIZE/Byte.SIZE);
+    return (ints != null) ? (byte) ints[0] : -1;
+  }
+
+  /**
+   * Reads the next line of text from this file.  This method successively
+   * reads bytes from the file (or memory if there are uncommitted byte updates),
+   * starting at the current file pointer, until it reaches a line terminator
+   * or the end of the file. Each byte is converted into a character by taking
+   * the byte's value for the lower eight bits of the character and setting the
+   * high eight bits of the character to zero.  This method does not,
+   * therefore, support the full Unicode character set.
+   *
+   * <p> A line of text is terminated by a carriage-return character
+   * (<code>'&#92;r'</code>), a newline character (<code>'&#92;n'</code>), a
+   * carriage-return character immediately followed by a newline character,
+   * or the end of the file.  Line-terminating characters are discarded and
+   * are not included as part of the string returned.
+   *
+   * <p> This method blocks until a newline character is read, a carriage
+   * return and the byte following it are read (to see if it is a newline),
+   * the end of the file is reached, or an exception is thrown.
+   *
+   * @return     the next line of text from this file, or null if end
+   *             of file is encountered before even one byte is read.
+   * @exception  IOException  if an I/O error occurs.
+   */
+  public String readLine() throws IOException {
+    StringBuffer input = new StringBuffer();
+    int c = -1;
+    boolean eol = false;
+
+    while (!eol) {
+      switch (c = readByte()) {
+        case -1:
+        case '\n':
+          eol = true;
+          break;
+        case '\r':
+          eol = true;
+          long cur = raf.getFilePointer();
+          if ((readByte()) != '\n') {
+            raf.seek(cur);
+          }
+          break;
+        default:
+          input.append((char) c);
+          break;
+      }
+    }
+    if ((c == -1) && (input.length() == 0)) {
+      return null;
+    }
+    return input.toString();
+  }
+
+  /**
+   * Reads up to <code>bytes.length</code> bytes of data from this file
+   * (or memory if there are uncommitted byte updates) into an array of
+   * bytes. This method blocks until at least one byte of input is available.
+   * <p>
+   * Although <code>XAFile</code> is not a subclass of
+   * <code>InputStream</code>, this method behaves in exactly the
+   * same way as the {@link InputStream#read(byte[])} method of
+   * <code>InputStream</code>.
+   *
+   * @param      bytes   the buffer into which the data is read.
+   * @return     the total number of bytes read into the buffer, or
+   *             <code>-1</code> if there is no more data because the end of
+   *             this file has been reached.
+   * @exception  IOException
+   *             If the first byte cannot be read for any reason
+   *             other than end of file, or if the random access file has been
+   *             closed, or if some other I/O error occurs.
+   * @exception  NullPointerException If <code>bytes</code> is <code>null</code>.
+   */
+  public int read(byte[] bytes) throws IOException {
+    return read(bytes, 0, bytes.length);
+  }
+
+  /**
+   * Reads exactly <code>len</code> bytes of data from this file
+   * (or memory if there are uncommitted byte updates) into an array of
+   * bytes. This method blocks until at least one byte of input is available.
+   * <p>
+   * Although <code>XAFile</code> is not a subclass of
+   * <code>InputStream</code>, this method behaves in exactly the
+   * same way as the {@link InputStream#read(byte[])} method of
+   * <code>InputStream</code>.
+   *
+   * @param      bytes   the buffer into which the data is read.
+   * @param      off   the start offset in array <code>bytes</code>
+   *                   at which the data is written.
+   * @param      len   the maximum number of bytes read.
+   * @return     the total number of bytes read into the buffer, or
+   *             <code>-1</code> if there is no more data because the end of
+   *             this file has been reached.
+   * @exception  IOException
+   *             If the first byte cannot be read for any reason
+   *             other than end of file, or if the random access file has been
+   *             closed, or if some other I/O error occurs.
+   * @exception  NullPointerException If <code>bytes</code> is <code>null</code>.
+   * @exception IndexOutOfBoundsException
+   *            if offset is negative, or len is negative, or offset+len is
+   *            greater than the size of the <code>bytes</code> array
+   */
+  public int read(byte[] bytes, int off, int len) throws IOException {
+    if (off < 0 || len < 0 || off + len > bytes.length)
+      throw new IndexOutOfBoundsException("bytes.length=" + bytes.length +
+          ", off=" + off + ", len=" + len);
+    if (bytes.length == 0)
+      return 0;
+    byte[] bs = getBytesFromInts(readRecord(len)); //todo readRecord may return null
+    System.arraycopy(bs, 0, bytes, off, len);
+//    int b;
+//    for (b = off; b < off + len; b++) {
+//      if (b >= raf.length())
+//        return -1;
+//      bytes[b] = readByte();
+//    }
+    return bs.length;
+  }
+
+  /**
+   * Reads up to <code>chars.length</code> characters from this file
+   * (or memory if there are uncommitted byte updates) into an array
+   * of characters.
+   * <p>
+   * This method blocks until the char is read, the end of the
+   * stream is detected, or an exception is thrown.
+   *
+   * @param chars the array into which the characters are read
+   * @return     a <code>String</code> containing the read characters
+   * @exception  EOFException  if this file reaches the end before reading
+   *                           <code>chars.length</code> characters.
+   * @exception  IOException   if an I/O error occurs.
+   */
+  public String readChars(char[] chars) throws IOException {
+    for (int c = 0; c < chars.length; c++) {
+      chars[c] = readChar();
+    }
+    return new String(chars);
+  }
+
+  /**
+   * Reads a character from this file. This method reads two
+   * bytes from the file (or memory if there are uncommitted byte updates),
+   * starting at the current file pointer.
+   * If the bytes read, in order, are
+   * <code>b1</code> and <code>b2</code>, where
+   * <code>0&nbsp;&lt;=&nbsp;b1,&nbsp;b2&nbsp;&lt;=&nbsp;255</code>,
+   * then the result is equal to:
+   * <blockquote><pre>
+   *     (char)((b1 &lt;&lt; 8) | b2)
+   * </pre></blockquote>
+   * <p>
+   * This method blocks until the two bytes are read, the end of the
+   * stream is detected, or an exception is thrown.
+   *
+   * @return     the next two bytes of this file, interpreted as a
+   *		         <code>char</code>.
+   * @exception  EOFException  if this file reaches the end before reading
+   *                           two bytes.
+   * @exception  IOException   if an I/O error occurs.
+   */
+  public char readChar() throws IOException {
+    int[] ints = readRecord(Character.SIZE/Byte.SIZE);
+
+    int ch1 = ints[0];
+    int ch2 = ints[1];
+    if ((ch1 | ch2) < 0) {
+      throw new EOFException();
+    }
+    return (char) ((ch1 << 8) + (ch2));
+  }
+
+  /**
+   * Reads a signed 64-bit integer from this file. This method reads eight
+   * bytes from the file (or memory if there are uncommitted byte updates),
+   * starting at the current file pointer.
+   * If the bytes read, in order, are
+   * <code>b1</code>, <code>b2</code>, <code>b3</code>,
+   * <code>b4</code>, <code>b5</code>, <code>b6</code>,
+   * <code>b7</code>, and <code>b8,</code> where:
+   * <blockquote><pre>
+   *     0 &lt;= b1, b2, b3, b4, b5, b6, b7, b8 &lt;=255,
+   * </pre></blockquote>
+   * <p>
+   * then the result is equal to:
+   * <p><blockquote><pre>
+   *     ((long)b1 &lt;&lt; 56) + ((long)b2 &lt;&lt; 48)
+   *     + ((long)b3 &lt;&lt; 40) + ((long)b4 &lt;&lt; 32)
+   *     + ((long)b5 &lt;&lt; 24) + ((long)b6 &lt;&lt; 16)
+   *     + ((long)b7 &lt;&lt; 8) + b8
+   * </pre></blockquote>
+   * <p>
+   * This method blocks until the eight bytes are read, the end of the
+   * stream is detected, or an exception is thrown.
+   *
+   * @return     the next eight bytes of this file, interpreted as a
+   *             <code>long</code>.
+   * @exception  EOFException  if this file reaches the end before reading
+   *                           eight bytes.
+   * @exception  IOException   if an I/O error occurs.
+   */
+  public long readLong() throws IOException {
+    return ((long) (readInt()) << 32) + (readInt() & 0xFFFFFFFFL);
+  }
+
+  /**
+   * Attempts to write a <code>long</code> to the file as eight bytes,
+   * high byte first. The write starts at the current position of the
+   * file pointer.
+   * <p>
+   * Updates will be written to the file after a commit operation call.
+   *
+   * @param      l   a <code>long</code> to be written.
+   * @exception  IOException  if an I/O error occurs.
+   */
+  public void writeLong(long l) throws IOException {
+    int[] ls = new int[]{((int) (l >>> 56) & 0xFF), ((int) (l >>> 48) & 0xFF),
+                         ((int) (l >>> 40) & 0xFF), ((int) (l >>> 32) & 0xFF),
+                         ((int) (l >>> 24) & 0xFF), ((int) (l >>> 16) & 0xFF),
+                         ((int) (l >>> 8) & 0xFF), ((int) (l) & 0xFF)};
+    writeRecord(ls);
+  }
+
+  /**
+   * Attempts to write the specified byte to this file. The write starts at
+   * the current file pointer.
+   * <p>
+   * The byte will be written to the file only after the commit operation
+   * @param      b   the <code>byte</code> to be written.
+   * @exception  IOException  if an I/O error occurs.
+   */
+  public void write(int b) throws IOException {
+    writeRecord(new int[]{b});
+  }
+
+  /**
+   * Attempts to write an <code>int</code> to the file as four bytes, high
+   * byte first. The write starts at the current position of the file pointer.
+   * <p>
+   * The <code>int</code> will be written to the file only after a commit operation call
+   * @param      n   an <code>int</code> to be written.
+   * @exception  IOException  if an I/O error occurs.
+   */
+  public void writeInt(int n) throws IOException {
+    int[] ls = new int[]{((n >>> 24) & 0xFF), ((n >>> 16) & 0xFF),
+        ((n >>> 8) & 0xFF), ((n) & 0xFF)};
+    writeRecord(ls);
+  }
+
+  /**
+   * Converts the double argument to a <code>long</code> using the
+   * <code>doubleToLongBits</code> method in class <code>Double</code>,
+   * and then attempts to write that <code>long</code> value to the file as an
+   * eight-byte quantity, high byte first. The write starts at the current
+   * position of the file pointer.
+   * <p>
+   * The <code>double</code> will be written to the file only after a
+   * commit operation call
+   *
+   * @param      d   a <code>double</code> value to be written.
+   * @exception  IOException  if an I/O error occurs.
+   * @see        java.lang.Double#doubleToLongBits(double)
+   */
+  public void writeDouble(double d) throws IOException {
+    writeLong(Double.doubleToLongBits(d));
+  }
+
+  /**
+   * Converts the float argument to an <code>int</code> using the
+   * <code>floatToIntBits</code> method in class <code>Float</code>,
+   * and then attempts to write that <code>int</code> value to the file as a
+   * four-byte quantity, high byte first. The write starts at the
+   * current position of the file pointer.
+   * <p>
+   * The <code>float</code> will be written to the file only after a
+   * commit operation call
+   *
+   * @param      f   a <code>float</code> value to be written.
+   * @exception  IOException  if an I/O error occurs.
+   * @see        java.lang.Float#floatToIntBits(float)
+   * @see        XAFile#readFloat()
+   */
+  public void writeFloat(float f) throws IOException {
+    writeInt(Float.floatToIntBits(f));
+  }
+
+  /**
+   * Attempts to write a <code>boolean</code> to the file as a one-byte
+   * value. The value <code>true</code> is written out as the value
+   * <code>(byte)1</code>; the value <code>false</code> is written out
+   * as the value <code>(byte)0</code>. The write starts at
+   * the current position of the file pointer.
+   * <p>
+   * The <code>boolean</code> will be written to the file only after a
+   * commit operation call
+   *
+   * @param      b   a <code>boolean</code> value to be written.
+   * @exception  IOException  if an I/O error occurs.
+   * @see XAFile#readBoolean()
+   */
+  public void writeBoolean(boolean b) throws IOException {
+    write(b ? 1 : 0);
+  }
+
+  /**
+   * Attempts to write a <code>byte</code> to the file as a one-byte value.
+   * The write starts at the current position of the file pointer.
+   * <p>
+   * The <code>byte</code> will be written to the file only after a
+   * commit operation call
+   *
+   * @param      b   a <code>byte</code> value to be written.
+   * @exception  IOException  if an I/O error occurs.
+   */
+  public synchronized void writeByte(int b) throws IOException {
+    write(b);
+  }
+
+  /**
+   * Internal method used by write oprations in the <code>XAFile</code>.
+   * If Transactions are disabled, bytes are written directly to the file.
+   * If Transactions are enabled the given <code>bytes</code> are written
+   * to the memory (added in a hashtable).
+   * <p>
+   * The method may be called by different threads. To prevent different
+   * Transactions to modify an already modified record by another
+   * Transaction a lock in <code>WRITE</code> mode is acquired. If the lock
+   * is finally <code>GRANTED</code> the <code>bytes<code> are added
+   * to the list of modified records in the correct <code>XAResourceManager</code>.
+   *
+   * @param bytes the array of bytes to write to the file
+   * @exception IOException if an I/O error occurs
+   * @exception org.jboss.jbossts.fileio.xalib.txfiles.exceptions.LockRefusedException if lock is <code>REFUSED</code>
+   */
+  private synchronized void writeRecord(int[] bytes) throws IOException {
+    if (transactionsEnabled) { // write bytes to the memory first
+      long curthr = getCurrentThreadId();
+      int lockRes;
+
+      XAResourceManager xareMngr = xares.get(curthr);
+
+      DataRecord dr = new DataRecord(raf.getFilePointer(), bytes.length, bytes);
+      lockRes = acquireLockOn(dr, xareMngr.getXid(), LockMode.WRITE);
+
+      if (lockRes == LockResult.GRANTED) {
+        xareMngr.addUpdatedBytes(raf.getFilePointer(), bytes);
+        xareMngr.add2Log(dr);
+        raf.skipBytes(bytes.length);
+      }
+    } else {  // write bytes directly to the file
+              // XAFile will now behave like a RandomAccessFile
+      commitUpdates(raf.getFilePointer(), bytes.length, getBytesFromInts(bytes));
+    }
+  }
+
+  /**
+   * Attempts to write a <code>short</code> to the file as two bytes, high
+   * byte first. The write starts at the current position of the file pointer.
+   * <p>
+   * The <code>short</code> will be written to the file only after a
+   * commit operation call
+   *
+   * @param      s   a <code>short</code> to be written.
+   * @exception  IOException  if an I/O error occurs.
+   * @see XAFile#readShort()
+   */
+  public void writeShort(int s) throws IOException {
+    int[] ss = new int[]{(s >>> 8 & 0xFF), ((s) & 0xFF)};
+    writeRecord(ss);
+  }
+
+  /**
+   * Attempts to write <code>len</code> bytes from the specified
+   * byte array starting at offset <code>off</code> to this file. 
+   * <p>
+   * The bytes will be written to the file only after a
+   * commit operation call
+   *
+   * @param      bytes the data.
+   * @param      off   the start offset in the data.
+   * @param      len   the number of bytes to write.
+   * @exception  IOException  if an I/O error occurs.
+   * @exception IndexOutOfBoundsException
+   *            if offset is negative, or len is negative, or offset+len is
+   *            greater than the size of the <code>bytes</code> array
+   * @see XAFile#read(byte[], int, int)
+   */
+  public void write(byte[] bytes, int off, int len) throws IOException {
+    if (off < 0 || len < 0 || off + len > bytes.length)
+      throw new IndexOutOfBoundsException("bytes.length=" + bytes.length +
+          ", off=" + off + ", len=" + len);
+    
+    byte[] newByteArray = new byte[len];
+    System.arraycopy(bytes, off, newByteArray, 0, len);
+    writeRecord(getIntsFromBytes(newByteArray));
+  }
+
+  /**
+   * Attempts to write a string to the file as a sequence of characters.
+   * Each character is written to the data output stream as if by the
+   * <code>writeChar</code> method. The write starts at the current
+   * position of the file pointer.
+   * <p>
+   * The <code>String</code> will be written to the file only after a
+   * commit operation call
+   *
+   * @param      s   a <code>String</code> value to be written.
+   * @exception  IOException  if an I/O error occurs.
+   * @see        java.io.RandomAccessFile#writeChar(int)
+   * @see        XAFile#readChar()
+   */
+  public void writeChars(String s) throws IOException {
+    int clen = s.length();
+    int blen = 2 * clen;
+    byte[] b = new byte[blen];
+    char[] c = new char[clen];
+    s.getChars(0, clen, c, 0);
+    for (int i = 0, j = 0; i < clen; i++) {
+      b[j++] = (byte) (c[i] >>> 8);
+      b[j++] = (byte) (c[i]);
+    }
+    write(b, 0, blen);
+  }
+
+  /**
+   * Attempts to write a <code>char</code> to the file as a two-byte
+   * value, high byte first. The write starts at the current position
+   * of the file pointer.
+   * <p>
+   * The <code>char</code> will be written to the file only after a
+   * commit operation call
+   *
+   * @param      ch   a <code>char</code> value to be written.
+   * @exception  IOException  if an I/O error occurs.
+   * @see XAFile#writeChars(String)
+   * @see XAFile#readChar()
+   */
+  public void writeChar(int ch) throws IOException {
+    int[] chs = new int[]{((ch >>> 8) & 0xFF), ((ch) & 0xFF)};
+    writeRecord(chs);
+  }
+
+  /**
+   * Attempts to write the string to the file as a sequence of bytes. Each
+   * character in the string is written out, in sequence, by discarding
+   * its high eight bits. The write starts at the current position of
+   * the file pointer.
+   * <p>
+   * The <code>String</code> will be written to the file only after a
+   * commit operation call
+   *
+   * @param      bytes   a string of bytes to be written.
+   * @exception  IOException  if an I/O error occurs.
+   */
+  public void writeBytes(String bytes) throws IOException {
+    int len = bytes.length();
+    byte[] b = bytes.getBytes();
+    write(b, 0, len);
+  }
+
+  /**
+   * Attempts to write <code>bytes.length</code> bytes from the specified
+   * byte array to this file, starting at current file pointer.
+   * <p>
+   * The bytes will be written to the file only after a
+   * commit operation call
+   *
+   * @param      bytes the data.
+   * @exception  IOException  if an I/O error occurs.
+   * @see XAFile#read(byte[])
+   */
+  public void write(byte[] bytes) throws IOException {
+    write(bytes, 0, bytes.length);
+  }
+
+  /**
+   * Attempts to write a string to the file using
+   * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
+   * encoding in a machine-independent manner.
+   * <p>
+   * First, two bytes are written to the memory, starting at the
+   * current file pointer, as if by the
+   * <code>writeShort</code> method giving the number of bytes to
+   * follow. This value is the number of bytes actually written out,
+   * not the length of the string. Following the length, each character
+   * of the string is output, in sequence, using the modified UTF-8 encoding
+   * for each character.
+   * <p>
+   * The <code>String</code> will be written to the file only after a
+   * commit operation call
+   *
+   * @param      str   a string to be written.
+   * @exception  IOException  if an I/O error occurs
+   * @see XAFile#readUTF()
+   */
+  public void writeUTF(String str) throws IOException {
+    DataOutputStream.writeUTF(str, this);
+  }
+
+  /**
+   * Returns the current offset in this file.
+   *
+   * @return     the offset from the beginning of the file, in bytes,
+   *             at which the next attempt of read or write occurs.
+   * @exception  IOException  if an I/O error occurs.
+   */
+  public long getFilePointer() throws IOException {
+    return raf.getFilePointer();
+  }
+
+  /**
+   * Attempts to skip over <code>n</code> bytes of input discarding the
+   * skipped bytes.
+   * <p>
+   * This method may skip over some smaller number of bytes, possibly zero.
+   * This may result from any of a number of conditions; reaching end of
+   * file before <code>n</code> bytes have been skipped is only one
+   * possibility. This method never throws an <code>EOFException</code>.
+   * The actual number of bytes skipped is returned.  If <code>n</code>
+   * is negative, no bytes are skipped.
+   *
+   * @param      n   the number of bytes to be skipped.
+   * @return     the actual number of bytes skipped.
+   * @exception  IOException  if an I/O error occurs.
+   */
+  public int skipBytes(int n) throws IOException {
+    return raf.skipBytes(n);
+  }
+
+  /**
+   * Returns the length of this file.
+   *
+   * @return     the length of this file, measured in bytes.
+   * @exception  IOException  if an I/O error occurs.
+   */
+  public long length() throws IOException {
+    return raf.length();
+  }
+
+  /**
+   * Returns the current thread id. If this id was not used to
+   * register a Transaction before an <code>IOException</code> will
+   * be thrown.
+   * @return the current thread's id registered with a Transaction
+   * @exception IOException if the current thread is not associated
+   *                     with any Transaction
+   */
+  private long getCurrentThreadId() throws IOException {
+    Thread th = Thread.currentThread();
+    long th_id = th.getId();
+
+    if (xares.isEmpty() || !xares.containsKey(th_id)) {
+      throw new IOException("There is no thread-transaction association. " +
+          "\nCurrent thread with id=<" + th_id + "> has not been registered " +
+          "with any Transaction. Possibly a read/write operation happens outside " +
+          "the scope of TransactionManager (begin - commit/rollback.) or the " +
+          "\nnewTransaction() method has not been called after the TransactionManager " +
+          "has begun.");
+    }
+    return th_id;
+  }
+
+  /**
+   * Used by <code>XAResourceManager</code> after starting-up
+   * recovery procedure
+   * @exception FileNotFoundException if the File does not exist
+   */
+  protected void initRAF() throws FileNotFoundException {
+    raf = new RandomAccessFile(filename, mode);
+  }
+
+  /**
+   * Converts an array of type <code>int</code> to an array of
+   * type <code>byte</code> and returns that.
+   *
+   * @param ints the array to convert into a <code>byte</code> array
+   * @return an array of bytes containing the values from the
+   *         <code>ints</code> array
+   */
+  protected static byte[] getBytesFromInts(int[] ints) {
+    byte[] bytes = new byte[ints.length];
+    for (int b = 0; b < ints.length; b++) {
+      bytes[b] = (byte) ints[b];
+    }
+    return bytes;
+  }
+
+  /**
+   * Converts an array of type <code>byte</code> to an array of
+   * type <code>int</code> and returns that.
+   *
+   * @param bytes the array to convert into an <code>int</code> array
+   * @return an array of <code>int</code> containing the values from the
+   *         <code>bytes</code> array.
+   */
+  protected static int[] getIntsFromBytes(byte[] bytes) {
+    int[] ints = new int[bytes.length];
+    for (int i = 0; i < bytes.length; i++) {
+      ints[i] = bytes[i];
+    }
+    return ints;
+  }
+
+  protected void finalize() throws Throwable {  //todo comments
+  try {
+    if (raf != null)
+      raf.close();        // close if file is open
+  } finally {
+      super.finalize();
+    }
+  }
+}
\ No newline at end of file

Added: labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txfiles/file/XAResourceManager.java
===================================================================
--- labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txfiles/file/XAResourceManager.java	                        (rev 0)
+++ labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txfiles/file/XAResourceManager.java	2008-08-29 12:58:31 UTC (rev 22026)
@@ -0,0 +1,469 @@
+/*     JBoss, Home of Professional Open Source Copyright 2008, Red Hat
+ *  Middleware LLC, and individual contributors as indicated by the
+ *  @author tags.
+ *     See the copyright.txt in the distribution for a full listing of
+ *  individual contributors. This copyrighted material is made available
+ *  to anyone wishing to use, modify, copy, or redistribute it subject to
+ *  the terms and conditions of the GNU Lesser General Public License, v. 2.1.
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY
+ *  or FITNESS FOR A PARTICULAR PURPOSE.
+ *     See the GNU Lesser General Public License for more details. You should
+ *  have received a copy of the GNU Lesser General Public License, v.2.1
+ *  along with this distribution; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA  02110-1301, USA.
+ *
+ *  (C) 2008,
+ *  @author Red Hat Middleware LLC.
+ */
+package org.jboss.jbossts.fileio.xalib.txfiles.file;
+
+import org.jboss.jbossts.fileio.xalib.txfiles.logging.LogEntry;
+import org.jboss.jbossts.fileio.xalib.txfiles.logging.RecordsLogger;
+import org.jboss.jbossts.fileio.xalib.Globals;
+import org.jboss.jbossts.fileio.xalib.txfiles.file.DataRecord;
+
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+import javax.transaction.xa.XAException;
+import java.io.IOException;
+import java.io.Serializable;
+import java.io.ObjectInputStream;
+import java.util.*;
+
+/**
+ * This class implements methods of the standard {@link javax.transaction.xa.XAResource} interface
+ * which acts like a contract between a Resource Manager and a Transaction
+ * Manager.
+ * <p>
+ * Each instance of an <code>XAResourceManager</code> has its own {@link javax.transaction.xa.Xid}
+ * which distinguishes by the other objects of this class and is associated
+ * with a Transaction. Each <code>XAResourceManager</code> instance has also
+ * a <code>log</code> ({@link RecordsLogger} object) to write information
+ * about the bytes that have been updated by <code>XAFile</code>. The updates
+ * are also added into a hashtable (depending on the starting position of the bytes
+ * that make up a {@link DataRecord} each time. If no crash has occured the
+ * Resource manager will retrieve information about the requested records using
+ * its hashtable in memory. In a situation where a system failure occured and
+ * the system tries to recover, the logs will be used to obtain the requested
+ * information.
+ * <p>
+ * The requested information will be written back to the original file only if
+ * Transaction Manager decides to commit and asks from the Resource Manager to
+ * commit and delete the log file. If Transaction Manager decides a rollback
+ * operation the Resource Manager invokes its own rollback operation which will
+ * cause all updates made so far to be removed and the log file to be deleted. 
+ * When the log is deleted (either in commit or rollback invocations) the thread
+ * is disassociated from the corresponding transaction.
+ *
+ * @author Ioannis Ganotis
+ * @version Jun 13, 2008
+ *
+ * @see XAFile
+ * @see RecordsLogger
+ * @see DataRecord
+ */
+public class XAResourceManager implements XAResource, Serializable
+{
+  private Xid currentXid;
+  private int timeout;
+  private XAFile xaFile;
+  private RecordsLogger log;
+  private long th_id;
+  transient private final int DEFAULT_TIMEOUT = 60;
+  private boolean recovers;
+  transient private Hashtable<Long, Integer> updatedBytes;
+
+  /**
+   * Constructor to create Resource Manager objects. Each of these
+   * objects, at transaction time, are informed by the Transaction
+   * Manager to prepare, commit or rollback (depending on the outcome
+   * of the 2PC protocol). Each of these Resource Manager objects are
+   * kept in a hashtable in the XAFile and are associated with the
+   * thread id that created the corresponding Transaction.
+   * @param xaFile the file instance on which updates take place
+   * @param log the logger object which keeps update-relative information
+   * @param th_id the thread id that created the transaction in which
+   *              this <code>XAResourceManager</code> object has been
+   *              enlisted.
+   * @throws IOException if an I/O error occurs
+   */
+  protected XAResourceManager(XAFile xaFile, RecordsLogger log,
+                              long th_id) throws IOException {
+    this.xaFile = xaFile;
+    this.log = log;
+    this.th_id = th_id;
+    timeout = DEFAULT_TIMEOUT;
+    recovers = false;
+    updatedBytes = new Hashtable<Long, Integer>(89);
+  }
+
+  /**
+   * Method to prepare a transaction with the given <code>xid</code> to
+   * commit.
+   * <p>
+   * The method forces system-memory buffers to write their data to the
+   * log file to ensure all the updates that are to be applied to the
+   * file are included in the log. The log file is then closed.
+   *
+   * @param xid a global Transaction id
+   * @return  <code>XA_OK</code> after synchronizing the log
+   * @exception XAException if an error occured while synchronizing the log
+   */
+  public int prepare(Xid xid) throws XAException {
+    // flush data on disk here
+    System.out.println("XAResourceManager.prepare(Xid=" + xid + "), th_id=" + th_id);
+    try {
+      log.flush();
+      log.close();
+    } catch (IOException e) {
+      throw new XAException("Unable to flush data to the log file <" +
+          log.getFilename() + ">.");
+    }
+    return XAResource.XA_OK;
+  }
+
+  /**
+   * Method to commit the global transaction with the given <code>xid</code>.
+   * <p>
+   * If this method is not invoked by a Recovery Manager, then the updated
+   * bytes will be read from the hashtable that contains them and will be
+   * written back to the original source file. In case there was a system
+   * failure, the same procedure will be followed but the updated bytes
+   * will be read from the log file instead of the memory, as memory will
+   * contain no relative information during recovery.
+   *
+   * @param xid a global Transaction id
+   * @param onePhase If true, the resource manager should use a one-phase
+   *                 commit protocol to commit the work done on behalf of xid
+   * @exception XAException if an I/O error occurs when calling the
+   *                        <code>commitChanges</code> method
+   */
+  public void commit(Xid xid, boolean onePhase) throws XAException {
+    System.out.println("XAResourceManager.commit(Xid=" + xid + ", onePhase=" + onePhase + "), th_id=" + th_id);
+    if (!xid.equals(currentXid)) {
+      System.out.println("XAResourceManager.commit - wrong Xid!");
+    }
+//System.exit(1);            // todo testcode ----------------------#################################---------------------
+
+//    try {
+//    if (th_id == 10l) {
+//      Thread.sleep(3000);
+//    }
+//    if (th_id == 11l) {
+//      Thread.sleep(3000);
+//    }
+////    if (th_id == 12l) {
+////      System.exit(1);
+////    }
+//  } catch (InterruptedException e) {
+//    e.printStackTrace();
+//  }
+    try {
+      commitChanges();
+//      if (th_id == 12l)
+//        throw new IOException("stupid exception!");
+    } catch (IOException ioe)
+    {
+      ioe.printStackTrace();
+      throw new XAException("Commit failed! Possibly an I/O error occurd while " +
+          "using the log file <" + log.getFilename() + ">" );
+    }
+
+    log.delete();
+    System.out.println("Original File Updated Successfully.");
+
+    currentXid = null;
+
+  }
+
+  /**
+   * Ends the work performed on behalf of a transaction branch.
+   *
+   * @param xid a global transaction identifier that is the same as what was used
+   *            previously in the start method
+   * @param flags (can be anything)
+   */
+  public void end(Xid xid, int flags) {
+    System.out.println("XAResourceManager.end(Xid=" + xid + ", flags=" + flags + "), th_id=" + th_id);
+  }
+
+  /**
+   * Forget about a heuristically completed transaction branch.
+   * The <code>currentXid</code> is set to null
+   * @param xid a global Transaction id
+   */
+  public void forget(Xid xid) {
+    System.out.println("XAResourceManager.forget(Xid=" + xid + ")");
+    if (!xid.equals(currentXid)) {
+      System.out.println("XAResourceManager.forget - wrong Xid!");
+    }
+    currentXid = null;
+  }
+
+  /**
+   * Obtain the current transaction timeout value set for this
+   * <code>XAResourceManager</code> instance. If
+   * <code>XAResourceManager.setTransactionTimeout</code> was not used prior to 
+   * invoking this method, the return value is the default timeout set for
+   * the resource manager; otherwise, the value used in the previous
+   * <code>setTransactionTimeout</code> call is returned.
+   *
+   * @return the transaction timeout value in seconds
+   */
+  public int getTransactionTimeout() {
+    System.out.println("XAResourceManager.getTransactionTimeout() [returning " + timeout + "]");
+    return timeout;
+  }
+
+  /*
+  * No implementation.
+  * @param xares an XAResource object whose resource manager instance is to
+  *              be compared with the resource manager instance of the target
+  *              object
+  * @return always false
+  */
+  public boolean isSameRM(XAResource xares) {
+    System.out.println("XAResourceManager.isSameRM(xares=" + xares + ")");
+    return false;
+  }
+
+  /*
+   * No implementation.
+   * @param flag
+   * @return always zero xids
+   */
+  public Xid[] recover(int flag) {
+    System.out.println("XAResourceManager.recover(flag=" + flag + ")");
+    return new Xid[0];
+  }
+
+  /**
+   * Rollback any updates attempted to be written to the file.
+   * <p>
+   * The method closes the log file and deletes it as it is not
+   * useful anymore. It also deletes the bytes from the hashtable
+   * and disassociates the transaction with the given <code>xid</code>
+   * from the thread that initiated it, if not called by the Recovery
+   * Manager.
+   *
+   * @param xid a global Transaction id
+   * @exception XAException
+   *            if an error occured while trying to disassociate the
+   *            the given <code>xid</code> from its initiator thread
+   */
+  public void rollback(Xid xid) throws XAException {
+    System.out.println("XAResourceManager.rollback(Xid=" + xid + "), th_id=" + th_id);
+    long th_id = Globals.RECOVERY_ID;
+    if (!xid.equals(currentXid)) {
+      System.out.println("XAResourceManager.rollback - wrong Xid!");
+    }
+
+    if (!recovers) { // normal operation (memory)
+      th_id = this.th_id;
+      updatedBytes.clear();
+    }
+    try {
+      xaFile.removeTransaction(currentXid, recovers);
+    } catch (IOException e) {
+      e.printStackTrace();
+      throw new XAException("Rollback failed. Could not disassociate " +
+          "the current thread " + th_id + "from the transaction with xid=<" + xid);
+    }
+    log.close();
+    log.delete();
+    currentXid = null;
+  }
+
+  /**
+   * Set the current transaction <code>timeout</code> value for this
+   * <code>XAResourceManager</code> instance. Once set, this timeout value is
+   * effective until <code>setTransactionTimeout</code> is invoked again with
+   * a different value. To reset the timeout value to the default value used by
+   * the resource manager, set the value to zero. If the timeout operation is
+   * performed successfully, the method returns true; otherwise false. If a
+   * resource manager does not support transaction timeout value to be set
+   * explicitly, this method returns false
+   * @param seconds transaction timeout value in seconds
+   * @return true if transaction timeout value is set successfully;
+   *         otherwise false
+   */
+  public boolean setTransactionTimeout(int seconds) {
+    System.out.println("XAResourceManager.setTransactionTimeout(timeout=" + seconds + ")");
+      if (seconds >= 0) {
+        timeout = seconds;
+        if (timeout == 0)
+          timeout = DEFAULT_TIMEOUT;
+        return true;
+      }
+    return false;
+  }
+
+  /**
+   * Start work on behalf of a transaction branch specified in <code>xid</code>.
+   * @param xid a global Transaction id to be associated with this
+   *            Resource Manager instance
+   * @param flags (can be anything)
+   * @throws XAException if there is already a Transaction
+   */
+  public void start(Xid xid, int flags) throws XAException {
+    System.out.println("XAResourceManager.start(Xid=" + xid + ", flags=" +
+        flags + "), th_id=" + th_id);
+    if (currentXid != null) {
+      System.out.println("XAResourceManager.start - wrong Xid!");
+      throw new XAException("Current Transaction is: <" + currentXid +
+          ">\nCannot start the new Transaction.");
+    }
+    currentXid = xid;
+  }
+
+  /**
+   * The method is invoked by the <code>commit</code> method
+   * of the <code>XAResourceManager</code> and performs the
+   * work as specified in that method.
+   *
+   * @exception IOException If an I/O error occurs while reading the log
+   */
+  private void commitChanges() throws IOException {
+    long th_id = this.th_id;
+    if (recovers) { // after a crash occured
+      th_id = Globals.RECOVERY_ID;
+    }
+    LinkedList<DataRecord> records = retrieveRecords();
+
+    for (DataRecord dr : records) {
+      xaFile.commitUpdates(dr.getStartPosition(),
+          dr.getRecordLength(), dr.getRecordBytes(), th_id);
+    }
+    xaFile.sync(); // Force updates to be written to the file
+    if (!recovers) { // normal operation(memory)
+      updatedBytes.clear();
+    }
+    xaFile.removeTransaction(currentXid, recovers);
+  }
+
+  /**
+   * Returns a list with the records (updates) written by some write
+   * operation in the <code>XAFile</code>. It either reads the records
+   * from the hashtable in memory (if not in recover phase), or from
+   * the <code>log</code> file which contains all the updates (if the
+   * system tries to recover).
+   *
+   * @return a list with <code>DataRecord</code> objects that contain
+   *         the updated data
+   * @exception IOException if an I/O error occurs
+   */
+  private LinkedList<DataRecord> retrieveRecords() throws IOException {
+    LinkedList<DataRecord> records = new LinkedList<DataRecord>();
+    if (recovers) {
+      LinkedList<LogEntry> logRecords = log.readAllRecords();
+      for (LogEntry entry : logRecords) {
+        try {
+          DataRecord dr = new DataRecord(entry.getPosition(), entry.getRecordLength(),
+              XAFile.getIntsFromBytes(entry.getData()));
+          records.add(dr);
+        } catch (Exception ioe) {
+          ioe.printStackTrace();
+        }
+      }
+    } else {
+      Set<Map.Entry<Long, Integer>> set = updatedBytes.entrySet();
+      Iterator<Map.Entry<Long, Integer>> it = set.iterator();
+
+      while (it.hasNext()) {
+        int[] bs = new int[set.size()];
+        Map.Entry<Long, Integer> kvPair = it.next();
+        long position = kvPair.getKey();
+        int b = kvPair.getValue();
+        int index = bs.length-1;
+        bs[index] = b;
+        while (it.hasNext()) {
+          kvPair = it.next();
+          if (position - kvPair.getKey() == 1) {
+            index--;
+            bs[index] = kvPair.getValue();
+            position = kvPair.getKey();
+          } else
+            break;
+        }
+        int[] bytes = new int[bs.length - index];
+        System.arraycopy(bs, 0, bytes, 0, bytes.length);
+        records.add(new DataRecord(position-index, bytes.length, bytes));
+      }
+    }
+    return records;
+  }
+
+  /**
+   * Adds adequate information to the <code>log</code>. Each entry
+   * consists of the start position of the record in the file, its
+   * length and the data (updates)
+   * @param dr the record by which information will be written to the log
+   * @exception IOException if an I/O error occurs
+   */
+  protected void add2Log(DataRecord dr) throws IOException {
+    LogEntry le = new LogEntry(dr.getStartPosition(), dr.getRecordLength(), dr.getRecordBytes());
+    log.addInfo(le);
+  }
+
+  /**
+   * Returns the global Transaction id associated with this
+   * <code>XAResourceManager</code>
+   * @return the global Transaction id associated with this
+   *         XAResourceManager
+   */
+  protected Xid getXid() {
+    return currentXid;
+  }
+
+  /**
+   * Returns all the updated bytes that have been modified by the
+   * transaction with <code>currentXid</code>.
+   * @return all the updated bytes that have been stored in the
+   *         table by previous <code>write</code> operations.
+   */
+  protected Hashtable<Long, Integer> getUpdatedBytes() {
+    return updatedBytes;
+  }
+
+  /**
+   * Adds the given <code>bytes</code> to the table that keeps all
+   * the <code>updatedBytes</code>. The array is treated as a group
+   * of modified bytes (record) with its first byte located at
+   * <code>startPosition</code> in the Transactional File.
+   *
+   * @param startPosition the position in the file where the record starts
+   * @param bytes an array that includes all the updated bytes to be stored
+   */
+  protected void addUpdatedBytes(long  startPosition, int[] bytes) {
+    for (int b : bytes)
+      updatedBytes.put(startPosition++, b);
+  }
+
+  /**
+   * This method is invoked when trying to deserialize an <code>XAResourceManager</code>
+   * object.
+   * <p>
+   * The method will read the non-static and non-transient fields of the current class and
+   * will set the <code>recovers</code> value to <code>true</code>. This will allow the
+   * rest of the methods in this class to be aware that the system is in its recovery
+   * phase and aact properly.
+   * <p>
+   * The method also initializes the <code>RandomAccessFile</code> object used in the
+   * <Code>XAFile</code> as well as the <code>XALockManager</code> objects to obtain the
+   * list of held locks.
+   *
+   * @param in input stream to read from
+   * @exception IOException if an I/O error occurs
+   * @exception ClassNotFoundException if the class of the Serialized object cannot be
+   *                                   found
+   */
+  private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
+  {
+    in.defaultReadObject();
+    recovers = true;
+    xaFile.initRAF();
+    xaFile.initLocksHeld();
+  }
+}
\ No newline at end of file

Added: labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txfiles/locking/XALock.java
===================================================================
--- labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txfiles/locking/XALock.java	                        (rev 0)
+++ labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txfiles/locking/XALock.java	2008-08-29 12:58:31 UTC (rev 22026)
@@ -0,0 +1,380 @@
+/*     JBoss, Home of Professional Open Source Copyright 2008, Red Hat
+ *  Middleware LLC, and individual contributors as indicated by the
+ *  @author tags.
+ *     See the copyright.txt in the distribution for a full listing of
+ *  individual contributors. This copyrighted material is made available
+ *  to anyone wishing to use, modify, copy, or redistribute it subject to
+ *  the terms and conditions of the GNU Lesser General Public License, v. 2.1.
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY
+ *  or FITNESS FOR A PARTICULAR PURPOSE.
+ *     See the GNU Lesser General Public License for more details. You should
+ *  have received a copy of the GNU Lesser General Public License, v.2.1
+ *  along with this distribution; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA  02110-1301, USA.
+ *
+ *  (C) 2008,
+ *  @author Red Hat Middleware LLC.
+ */
+package org.jboss.jbossts.fileio.xalib.txfiles.locking;
+
+import com.arjuna.ats.txoj.LockMode;
+import javax.transaction.xa.Xid;
+import java.io.Serializable;
+import java.util.Hashtable;
+
+import org.jboss.jbossts.fileio.xalib.Globals;
+
+/**
+ * Instances of this class allow accessing the information held by each lock.
+ * The <em>byte-range</em> to lock, the <code>mode</code> as well as the
+ * <code>xid</code> are the ones that define a lock.
+ * <p>
+ * Each lock object has a separate mode for each byte in its byte-range. When
+ * initialised all of these bytes have the mode passed in the constructor during
+ * initialisation. Computations by the <code>adjustWith</code> method determine
+ * which of the bytes within the byte-range needs to change mode. This will allow
+ * more concurrent operations acting on the same lock.
+ * <p>
+ * The class implements {@link java.io.Serializable} as the objects need to be
+ * stored in a file by the {@link XALockManager}. It also implements the
+ * {@link Comparable} interface to allow comparisons between <code>XALock</code>
+ * objects.
+ *
+ * @author Ioannis Ganotis
+ * @version Jul 23, 2008
+ */
+public class XALock implements Serializable, Comparable<XALock>
+{
+  private Xid xid;
+  private long startPosition;
+  private long lockLength;
+  private Hashtable<Long, Integer> byteModes;
+
+  /**
+   * Constructor to create <code>XALock</code> objects. These objects are
+   * managed by the {@link XALockManager} and are stored in a <em>locks file</em>.
+   *
+   * @param xid the global Transaction id which was used when the lock was acquired
+   * @param mode the mode (<code>LockMode.READ</code or <code>LockMode.WRITE) in which
+   *             the bytes in the byte-range will be initialised
+   * @param startPosition the position in the file of the first byte in the byte-range
+   * @param lockLength the number of bytes to lock
+   */
+  public XALock(Xid xid, int mode, long startPosition, long lockLength) {
+    this.xid = xid;
+    this.startPosition = startPosition;
+    this.lockLength = lockLength;
+
+    initModes(mode);
+  }
+
+  /**
+   * The method is used to initialise all the bytes in the byte range to the
+   * given <code>mode</code>.
+   *
+   * @param mode the mode in which the bytes will be initialised
+   */
+  private void initModes(int mode) {
+    byteModes = new Hashtable<Long, Integer>(89);
+    long sp = startPosition;
+    while (sp < getEndPosition()) {
+      byteModes.put(sp++, mode);
+    }
+  }
+
+  /**
+   * Returns the global id used when this lock was acquired.
+   *
+   * @return the global Transaction id used when the lock was
+   *         acquired
+   */
+  protected Xid getXid() {
+    return xid;
+  }
+
+  /**
+   * This method sets a <code>newMode</code> at <code>position</code>
+   *
+   * @param position the position at which the new mode will be set
+   * @param newMode the new mode to set to the byte at <code>position</code>
+   */
+  private void setModeAt(long position, int newMode) {
+    byteModes.put(position, newMode);
+  }
+
+  /**
+   * This method sets a <code>newMode</code> to a byte-range.
+   *
+   * @param position the position of the first byte in the byte range
+   * @param len the number of bytes that will change mode
+   * @param newMode the new mode to set to a range of bytes
+   */
+  private void setModeStartingAt(long position, long len, int newMode) {
+    long ps = position;
+    while (ps < len+position) {
+      setModeAt(ps++, newMode);
+    }
+  }
+
+  /**
+   * Returns the position in the file where this lock starts.
+   *
+   * @return the start position of this lock
+   */
+  private long getStartPosition() {
+    return startPosition;
+  }
+
+  /**
+   * This method sets a new start position of this lock. The
+   * method is especially useful when the bounds of the lock
+   * have to be moved.
+   *
+   * @param startPosition the new start position of this lock
+   */
+  private void setStartPosition(long startPosition) {
+    long len_difference = this.startPosition - startPosition;
+    lockLength += len_difference;
+    this.startPosition = startPosition;
+  }
+
+  /**
+   * Returns the length of the locked (by this lock) region in the
+   * Transactional file.
+   *
+   * @return a <code>long</code> which specifies how many bytes have
+   *         been locked by this lock
+   */
+  private long getLockLength() {
+    return lockLength;
+  }
+
+  /**
+   * This method modifies the amount of bytes locked by this lock
+   *
+   * @param lockLength how many bytes to lock
+   */
+  private void setLockLength(long lockLength) {
+    this.lockLength = lockLength;
+  }
+
+  /**
+   * Returns the end position in the file of this lock.
+   *
+   * @return a <code>long</code> which represents the end
+   *         of this lock within the Transactional file
+   */
+  private long getEndPosition() {
+    return getStartPosition() + getLockLength();
+  }
+
+  /**
+   * This method returns true if the <code>mode</code> is contained
+   * in the byte-range of this lock; otherwise returns false.
+   *
+   * @param mode the mode to check if exists
+   * @return true if the <code>mode</code> exists in the byte-range;
+   *         false otherwise
+   */
+  private boolean containsMode(int mode) {
+    return byteModes.containsValue(mode);
+  }
+
+  /**
+   * This method checks if the <code>mode</code> is contained within a
+   * specified range (sub-range) in the byte-range of this lock.
+   *
+   * @param sp the start position of the sub-range to search
+   * @param ep the end position of the sub-range
+   * @param mode the mode to search if exists
+   * @return true if the mode exists within the given sub-range
+   */
+  private boolean containsModeBetween(long sp, long ep, int mode) {
+    for (long p=sp; p<ep; p++) {
+      if (byteModes.get(sp) == mode)
+        return true;
+    }
+    return false;
+  }
+
+  /**
+   * This method returns true if the <code>newLock</code> conflicts with this
+   * lock; false otherwise.
+   *
+   * @param newLock the lock trying to add
+   * @return true if there is a conflict between <code>this</code> lock and the
+   *         <code>newLock</code>; false otherwise
+   */
+  private boolean conflictsWith(XALock newLock) {
+    return newLock == null                   || this.wraps(newLock)                ||
+           this.isWrappedBy(newLock)         || this.equals(newLock)               ||
+           this.intersectedFromLeft(newLock) || this.intersectedFromRight(newLock);
+  }
+
+  /**
+   * This method performs some calculations to return a result whether
+   * a conflict exists or not. If the conflict exists then it tries to
+   * check the byte-range to see if the lock can be granted or not. If
+   * needed the method will modify the bounds of existing locks so the
+   * new one can fit next to it.
+   *
+   * @param neighLock the lock located next to this lock
+   * @return <code>Globals.UPDATE_OLD_LOCK</code>, <code>Globals.ADD_NEW_LOCK</code>
+   *         <code>Globals.MOVE_LOCK_BOUNDS</code>, <code>Globals.REFUSE_LOCK</code>,
+   *         <code>Globals.NO_MOD_LOCK</code>, depending on the outcome of computations 
+   */
+  protected int adjustWith(XALock neighLock) {
+    final int R_M = LockMode.READ;
+    final int W_M = LockMode.WRITE;
+    int result = Globals.REFUSE_LOCK;
+
+    if (neighLock != null && neighLock.conflictsWith(this)) {
+      if (neighLock.getXid() == this.getXid()) {
+        if (this.equals(neighLock) || neighLock.wraps(this)) {
+          if (!this.containsMode(W_M))
+            result = Globals.NO_MOD_LOCK;
+          if (!this.containsMode(R_M)) {
+            neighLock.setModeStartingAt(this.getStartPosition(), this.getLockLength(), W_M);
+            result = Globals.UPDATE_OLD_LOCK;
+          }
+        } else if (neighLock.intersectedFromLeft(this)) {
+          long neighSP = neighLock.getStartPosition();
+          long conflict_length = this.getEndPosition() - neighSP;
+          if (!this.containsMode(R_M)) // the new Lock is in W_M
+            neighLock.setModeStartingAt(neighSP, conflict_length, W_M);
+          this.setLockLength(this.getLockLength() - conflict_length);
+          result = Globals.MOVE_LOCK_BOUNDS;
+        } else if (neighLock.intersectedFromRight(this)) {
+          long neighEP = neighLock.getEndPosition();
+          long conflict_length = neighEP - this.getStartPosition();
+          if (!this.containsMode(R_M)) // the new lock is in W_M
+            neighLock.setModeStartingAt(this.getStartPosition(), conflict_length, W_M);
+          this.setStartPosition(neighEP); // lock length will be calculated by this method
+          result = Globals.MOVE_LOCK_BOUNDS;
+        } else if (neighLock.isWrappedBy(this)) {
+          if (!this.containsMode(R_M)) {
+            neighLock.setStartPosition(this.getStartPosition());
+            neighLock.setLockLength(this.getLockLength());
+            neighLock.initModes(W_M);
+            result = Globals.UPDATE_OLD_LOCK;
+          }
+        }
+      } else { //different Transaction
+        if (this.containsMode(W_M) || neighLock.containsMode(W_M)) {
+          result = Globals.REFUSE_LOCK;
+        } else if (neighLock.intersectedFromLeft(this)) {
+          if (!this.containsMode(W_M)) {
+            if (neighLock.containsModeBetween(neighLock.getStartPosition(), this.getEndPosition(), R_M))
+              result = Globals.NO_MOD_LOCK;
+            else
+              result = Globals.REFUSE_LOCK;
+          }
+        } else if (neighLock.intersectedFromRight(this)) {
+          if (!this.containsMode(W_M)) {
+            if (neighLock.containsModeBetween(this.getStartPosition(), neighLock.getEndPosition(), R_M))
+              result = Globals.NO_MOD_LOCK;
+            else
+              result = Globals.REFUSE_LOCK;
+          }
+        }
+      }
+    } else {
+      return Globals.ADD_NEW_LOCK;
+    }
+    return result;
+  }
+
+  /**
+   * The method returns true if an existing lock surrounds the new lock;
+   * false otherwise.
+   *
+   * @param newLock the lock trying to add
+   * @return true if the existing lock surrounds the new lock; false othewise
+   */
+  private boolean wraps(XALock newLock) {
+    return (this.getStartPosition() <= newLock.getStartPosition() &&
+            this.getEndPosition() > newLock.getEndPosition()) ||
+           (this.getStartPosition() < newLock.getStartPosition() &&
+            this.getEndPosition() >= newLock.getEndPosition());
+  }
+
+  /**
+   * The method returns true if the existing lock is surrounded by the
+   * new lock; false otherwise.
+   *
+   * @param newLock the lock trying to add
+   * @return true if the existing lock is surrounded by the new lock;
+   *         false otherwise
+   */
+  private boolean isWrappedBy(XALock newLock) {
+    return (this.getStartPosition() >= newLock.getStartPosition() &&
+            this.getEndPosition() < newLock.getEndPosition()) ||
+           (this.getStartPosition() > newLock.getStartPosition() &&
+            this.getEndPosition() <= newLock.getEndPosition());
+  }
+
+  /**
+   * Returns true if the existing lock conflicts from the left hand side
+   * with the new lock; false otherwise.
+   *
+   * @param newLock the lock trying to add
+   * @return true if the existing lock conflicts from the left hand side
+   *         with the new lock; false otherwise
+   */
+  private boolean intersectedFromLeft(XALock newLock) {
+    return newLock.getStartPosition() < this.getStartPosition() &&
+           newLock.getEndPosition() <= this.getEndPosition();
+  }
+
+  /**
+   * Returns true if the existing lock conflicts from the right hand side
+   * with the new lock; false otherwise.
+   *
+   * @param newLock the lock trying to add
+   * @return true if the existing lock conflicts from the right hand side
+   *         with the new lock; false otherwise
+   */
+  private boolean intersectedFromRight(XALock newLock) {
+    return newLock.getStartPosition() >= this.getStartPosition() &&
+           newLock.getEndPosition() > this.getEndPosition();
+  }
+
+  /**
+   * This method compares two locks.
+   * <p>It will return:
+   * <code>-1</code> if the new lock is on the right side of the existing lock
+   * <p>
+   * <code>0</code> if both of the locks are starting at the same position
+   * <p>
+   * <code>1</code> if the new lock is on the left side of the existing lock
+   *
+   * @param newXALock the lock trying to add
+   * @return  <code>-1</code> if the new lock is on the right side of the existing lock
+   *          <code>0</code> if both of the locks are starting at the same position
+   *          <code>1</code> if the new lock is on the left side of the existing lock
+   */
+  public int compareTo(XALock newXALock) {
+    if (getStartPosition() < newXALock.getStartPosition()) {
+      return 1;
+    } else if (getStartPosition() > newXALock.getStartPosition()) {
+      return -1;
+    }
+    return 0;
+  }
+
+  /**
+   * This method checks the equality of two locks. It will return
+   * true if both of the locks start at the same point in the
+   * Transactional file and they have the same length; false
+   * otherwise.
+   * 
+   * @param newLock the lock trying to add
+   * @return true if the locks are equal; false otherwise
+   */
+  private boolean equals(XALock newLock) {
+    return (this.compareTo(newLock) == 0 &&
+        getLockLength() == newLock.getLockLength());
+  }
+}

Added: labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txfiles/locking/XALockManager.java
===================================================================
--- labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txfiles/locking/XALockManager.java	                        (rev 0)
+++ labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txfiles/locking/XALockManager.java	2008-08-29 12:58:31 UTC (rev 22026)
@@ -0,0 +1,333 @@
+/*     JBoss, Home of Professional Open Source Copyright 2008, Red Hat
+ *  Middleware LLC, and individual contributors as indicated by the
+ *  @author tags.
+ *     See the copyright.txt in the distribution for a full listing of
+ *  individual contributors. This copyrighted material is made available
+ *  to anyone wishing to use, modify, copy, or redistribute it subject to
+ *  the terms and conditions of the GNU Lesser General Public License, v. 2.1.
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY
+ *  or FITNESS FOR A PARTICULAR PURPOSE.
+ *     See the GNU Lesser General Public License for more details. You should
+ *  have received a copy of the GNU Lesser General Public License, v.2.1
+ *  along with this distribution; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA  02110-1301, USA.
+ *
+ *  (C) 2008,
+ *  @author Red Hat Middleware LLC.
+ */
+package org.jboss.jbossts.fileio.xalib.txfiles.locking;
+
+import com.arjuna.ats.txoj.LockResult;
+import javax.transaction.xa.Xid;
+import java.io.*;
+import java.util.*;
+
+import org.jboss.jbossts.fileio.ObjectOutputStreamAppend;
+import org.jboss.jbossts.fileio.xalib.Globals;
+
+/**
+ * This class is used to manage Locking on a {@link org.jboss.jbossts.fileio.xalib.txfiles.file.XAFile}. When methods
+ * like read/write are invoked from within the <code>XAFile</code> class
+ * locks are acquired automatically in read or write modes, respectively.
+ * <p>
+ * The class uses a list to maintain all the locks held by the VM. If
+ * multiple VMs act on the same Transactional file simultaneously the
+ * locks are kept in a file, so every VM is aware of which regions of the
+ * file are locked. Processing a different <code>XAFile</code> will
+ * produce another <em>lock file</em> containing the locked regions of
+ * that Transactional file.
+ * <p>
+ * When a lock is acquired through the <code>tryLock</code> method, depending
+ * on the outcome of the <code>manageLocks</code> a lock will either be
+ * <em>GRANTED</em> or <em>REFUSED</em>. Internally, computations happen to
+ * either add a new lock, update an existing one (by moving its bounds or
+ * changing its access mode), or do nothing at all.
+ *
+ * @author Ioannis Ganotis
+ * @version Jul 23, 2008
+ */
+public class XALockManager implements Serializable
+{
+  private String filename = Globals.LOCKS_FOLDER_PATH;
+  transient private LinkedList<XALock> heldLocks;
+
+  /**
+   * Constructor to create <code>XALockManager</code> objects. Using such
+   * an object <code>XAFile</code> can acquire read/write locks on specific
+   * regions of any Transactional file.
+   * <p>
+   * The constructor also invokes a method to get all the locks that have
+   * been held so far, before going any further.
+   *
+   * @param xaFilename the Transactional file on which to apply locks
+   */
+  public XALockManager(String xaFilename) {
+    filename += getProcessedName(xaFilename);
+    heldLocks = new LinkedList<XALock>();
+    try {
+      File f = new File(filename);
+      if (f.exists()) {
+        obtainHeldLocksWith(null);
+      }
+    } catch (IOException ioe) {
+      ioe.printStackTrace();
+    }
+  }
+
+  private String getProcessedName(String xaFilename) {
+    xaFilename = xaFilename.replace('/', '_');
+    xaFilename = xaFilename.replace('\\', '_');
+    return xaFilename.concat("_locks.log"); 
+  }
+
+  /**
+   * This method opens an existing <em>locks file</em> and retrieves its existing
+   * {@link XALock} objects. These objects now are kept in memory and can be used
+   * for further processing.
+   *
+   * @param xid the global Transaction id that was used when a lock was acquired.
+   *            if <code>xid</code> is <code>null</code> then all the locks that
+   *            are in a file will be returned.
+   * @return a list of {@link XALock} objects acquired by a Transaction with the
+   *         given <code>xid</code>. If <code>xid</code> is <code>null</code> then
+   *         all the locks that are stored in that file will be returned.
+   * @exception IOException if an I/O error occurs
+   */
+  public synchronized LinkedList<XALock> obtainHeldLocksWith(Xid xid) throws IOException {
+    File file = new File (filename);
+    if (file.exists()) {
+      FileInputStream fIn = new FileInputStream(filename);
+      ObjectInputStream in = new ObjectInputStream(fIn);
+
+      boolean eof = false;
+      do {
+        try {
+          Object obj = in.readObject();
+          XALock xaLock = (XALock) obj;
+          if (xaLock.getXid() == xid || xid == null) {
+            insertLockAt(binarySearch(xaLock), xaLock);
+          }
+        } catch (EOFException eofe) {
+          eof = true;
+        } catch (ClassNotFoundException cnfe) {
+          cnfe.printStackTrace();
+        }
+      } while (!eof);
+      in.close();
+      fIn.close();
+    }
+    return heldLocks;
+  }
+
+  /**
+   * The method is used to keep the memory locks synchronized
+   * with the ones that already exist in the file. Non existing
+   * ones will be just added to the <em>locks file</em>.
+   */
+  private synchronized void syncLocks() {
+    try {
+      FileOutputStream fOut = new FileOutputStream(filename);
+      ObjectOutputStream out = new ObjectOutputStream(fOut);
+
+      for (XALock lock : heldLocks) {
+        out.writeObject(lock);
+      }
+      out.close();
+      fOut.close();
+    } catch (IOException ioe) {
+      ioe.printStackTrace();
+    }
+  }
+
+  /**
+   * This method tries to set a given <code>lock</code>. If the lock to
+   * be set is <code>null</code> the outcome is to <em>REFUSE</em> that
+   * lock. In other cases the lock is added, the <em>locks file</code>
+   * is synchronized, or both apply.
+   * @param lock the lock trying to set
+   * @return <code>LockResult.GRANTED</code> if the lock can be granted
+   *         or <code>LockResult.REFUSED</code> fail to grant the lock
+   *
+   * @exception IOException if an I/O error occurs while adding new locks
+   */
+  public synchronized int tryLock(XALock lock) throws IOException {
+    if (lock != null) {
+      int index = binarySearch(lock);
+      int vResult = manageLocks(index, lock);
+      if (vResult != Globals.REFUSE_LOCK) { // allowed to add the new lock
+        if (vResult == Globals.ADD_NEW_LOCK || vResult == Globals.MOVE_LOCK_BOUNDS) {
+          if (vResult == Globals.MOVE_LOCK_BOUNDS)
+                syncLocks();
+          insertLockAt(index, lock);
+          FileOutputStream fOut;
+          ObjectOutputStream out;
+          File lockFile = new File(filename);
+
+          if (lockFile.exists()) { // Append the file, write new locks at the end
+            fOut = new FileOutputStream(filename, true);
+            out = new ObjectOutputStreamAppend(fOut);
+          } else {
+            fOut = new FileOutputStream(filename);
+            out = new ObjectOutputStream(fOut);
+          }
+          out.writeObject(lock);
+          out.close();
+          fOut.close();
+        } else if (vResult == Globals.UPDATE_OLD_LOCK) {
+          syncLocks();
+        }
+        return LockResult.GRANTED;
+      }
+    }
+    return LockResult.REFUSED;
+  }
+
+  /**
+   * Searches the list of locks in memory to find at which index the
+   * <code>newLock</code> should be added. The list is sorted, so
+   * when finds the appropriate index, returns it.
+   *
+   * @param newLock the lock to add in the locks list
+   * @return an index at which the <code>newLock</code> is about to be added
+   */
+  private int binarySearch(XALock newLock) {  //todo fix comment
+    int mid;
+    int res = 0;
+    int low = 0;
+    int high = heldLocks.size() - 1;
+
+    while( low <= high )
+    {
+      mid = ( low + high ) / 2;
+      XALock curLock = heldLocks.get(mid);
+      int compRes = curLock.compareTo(newLock);
+
+      if( compRes > 0 ) {
+        low = mid + 1;
+        res = mid+1;
+      }
+      else if( compRes < 0 ) {
+        high = mid - 1;
+        res = mid;
+      }
+      else
+        return mid;
+    }
+    return res;     // NOT_FOUND = -1
+  }
+
+  /**
+   * Inserts the given <code>newLock</code> at the specified <code>index</code>.
+   *
+   * @param index the index to add the new lock
+   * @param newLock the lock to be added
+   */
+  private void insertLockAt(int index, XALock newLock) {
+    if (index >= 0) {
+      heldLocks.add(index, newLock);
+    }
+  }
+
+  /**
+   * The method takes the given <code>xaLock</code> and checks any of its
+   * existing neighbours. If any of the neighbours deny to add the new lock,
+   * it will be <em>REFUSED</em> from being added. Other possible cases is
+   * to return <code>Globals.UPDATE_OLD_LOCK</code>, <code>Globals.MOVE_LOCK_BOUNDS</code>,
+   * or <code>Globals.ADD_NEW_LOCK</code>.
+   * <p>
+   * If one of the neighbours is <code>null</code> the result of the other neighbour is
+   * returned instead. if both of them are <code>null</code> the method returns
+   * <code>Globals.ADD_NEW_LOCK</code>, as this means there are no neighbours and as
+   * a result there are no conflicts, so the new lock can be added safely.
+   *
+   * @param it the index at which the lock will be added. Before adding the lock this index
+   *           points to the right neighbour, or to a <code>null</code> cell, if the
+   *           neighbour does not exist.
+   * @param xaLock the lock trying to add
+   * @return returns <code>Globals.ADD_NEW_LOCK</code>, <code>Globals.UPDATE_OLD_LOCK</code>,
+   *                 <code>Globals.MOVE_LOCK_BOUNDS</code>, or <code>Globals.REFUSE_LOCK</code>
+   *                 depending on the result of computations.
+   */
+  private int manageLocks(int it, XALock xaLock) {
+    if (xaLock.getXid() != null) {
+      XALock leftLock  = null;
+      XALock rightLock = null;
+
+      if (it > 0)
+        leftLock = heldLocks.get(it-1);
+      if (it < heldLocks.size())
+        rightLock = heldLocks.get(it);
+
+      if (leftLock != null && rightLock != null) {
+        int leftResult = xaLock.adjustWith(leftLock);
+        int rightResult = xaLock.adjustWith(rightLock);
+
+        if (leftResult == Globals.REFUSE_LOCK || rightResult == Globals.REFUSE_LOCK)
+          return Globals.REFUSE_LOCK;
+        else {
+          if (leftResult == Globals.MOVE_LOCK_BOUNDS || rightResult == Globals.MOVE_LOCK_BOUNDS) {
+            return Globals.MOVE_LOCK_BOUNDS;
+          } else if (leftResult == Globals.UPDATE_OLD_LOCK || rightResult == Globals.UPDATE_OLD_LOCK) {
+            return Globals.UPDATE_OLD_LOCK;
+          } else if (leftResult == Globals.ADD_NEW_LOCK || rightResult == Globals.ADD_NEW_LOCK) {
+            return Globals.ADD_NEW_LOCK;
+          }
+        }
+      } else
+      {
+        if (leftLock == null && rightLock == null) {
+          return Globals.ADD_NEW_LOCK;
+        } else if (leftLock == null) {
+          return xaLock.adjustWith(rightLock);
+        } else {
+          return xaLock.adjustWith(leftLock);
+        }
+      }
+    }
+    return Globals.REFUSE_LOCK;
+  }
+
+  /**
+   * This method releases all the locks that have been held by
+   * a Transaction with the given <code>xid</code>.
+   * <p>
+   * The method removes existing locks from the memory and then
+   * synchronizes the <em>locks file</em>.
+   *
+   * @param xid the global Transaction id which was used for
+   *            the locks trying to release
+   */
+  public void releaseLocks(Xid xid) {
+    XALock[] locks = new XALock[heldLocks.size()];
+    heldLocks.toArray(locks);
+    for (XALock lock : locks) {
+      if (lock.getXid() == xid) {
+        heldLocks.remove(lock);
+      }
+    }
+    syncLocks();
+//    System.out.println("--- Locks participating in transaction with xid=" + xid +
+//        " have been released!");
+  }
+
+  /**
+   * Returns a list with all the held locks.
+   * @return a list with all the held locks
+   */
+  public LinkedList<XALock> getHeldLocks() {
+    return heldLocks;
+  }
+
+  /**
+   * This method deletes the <em>locks file</em> and
+   * is called by the <code>XAFile#close</code>, as it
+   * is no more needed.
+   */
+  public void deleteFile() {
+    File f = new File(filename);
+    if (f.exists())
+      f.delete();
+  }
+}

Added: labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txfiles/logging/LogEntry.java
===================================================================
--- labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txfiles/logging/LogEntry.java	                        (rev 0)
+++ labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txfiles/logging/LogEntry.java	2008-08-29 12:58:31 UTC (rev 22026)
@@ -0,0 +1,77 @@
+/*     JBoss, Home of Professional Open Source Copyright 2008, Red Hat
+ *  Middleware LLC, and individual contributors as indicated by the
+ *  @author tags.
+ *     See the copyright.txt in the distribution for a full listing of
+ *  individual contributors. This copyrighted material is made available
+ *  to anyone wishing to use, modify, copy, or redistribute it subject to
+ *  the terms and conditions of the GNU Lesser General Public License, v. 2.1.
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY
+ *  or FITNESS FOR A PARTICULAR PURPOSE.
+ *     See the GNU Lesser General Public License for more details. You should
+ *  have received a copy of the GNU Lesser General Public License, v.2.1
+ *  along with this distribution; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA  02110-1301, USA.
+ *
+ *  (C) 2008,
+ *  @author Red Hat Middleware LLC.
+ */
+package org.jboss.jbossts.fileio.xalib.txfiles.logging;
+
+/**
+ * This class represents an entry in a log file the information of which is
+ * handled by a {@link RecordsLogger} object.
+ * <p>
+ * The class is only a single representation of such entries and is not written
+ * in any of the log files. It is the information it includes that is written
+ * and there are appropriate <em>get</em> methods to support this.
+ *
+ * @author Ioannis Ganotis
+ * @version Jul 25, 2008
+ */
+public class LogEntry //implements Serializable
+{
+  private long position;
+  private int recordLength;
+  private byte[] data;
+
+  /**
+   * Constructor to create <code<LogEntry</code> objects to represent an
+   * entry in the log file.
+   *
+   * @param position the position in the Transactional file of the first byte
+   *                 in the <code>data</code> array of bytes
+   * @param recordLength the length of the <code>data</code> to read/write
+   * @param data an array of the updated bytes
+   */
+  public LogEntry(long position, int recordLength, byte[] data) {
+    this.position = position;
+    this.recordLength = recordLength;
+    this.data = data;
+  }
+
+  /**
+   * Returns the position of the first byte in the file.
+   * @return the position of the first byte in the file
+   */
+  public long getPosition() {
+    return position;
+  }
+
+  /**
+   * Returns the length of the <code>data</code> of this record.
+   * @return the length of the <code>data</code> of this record
+   */
+  public int getRecordLength() {
+    return recordLength;
+  }
+
+  /**
+   * Returns the actual updated bytes of this entry.
+   * @return the actual updated bytes of this entry
+   */
+  public byte[] getData() {
+    return data;
+  }
+}

Added: labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txfiles/logging/RecordsLogger.java
===================================================================
--- labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txfiles/logging/RecordsLogger.java	                        (rev 0)
+++ labs/jbosstm/workspace/transactionalFileIO/trunk/src_items/src/org/jboss/jbossts/fileio/xalib/txfiles/logging/RecordsLogger.java	2008-08-29 12:58:31 UTC (rev 22026)
@@ -0,0 +1,150 @@
+/*     JBoss, Home of Professional Open Source Copyright 2008, Red Hat
+ *  Middleware LLC, and individual contributors as indicated by the
+ *  @author tags.
+ *     See the copyright.txt in the distribution for a full listing of
+ *  individual contributors. This copyrighted material is made available
+ *  to anyone wishing to use, modify, copy, or redistribute it subject to
+ *  the terms and conditions of the GNU Lesser General Public License, v. 2.1.
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY
+ *  or FITNESS FOR A PARTICULAR PURPOSE.
+ *     See the GNU Lesser General Public License for more details. You should
+ *  have received a copy of the GNU Lesser General Public License, v.2.1
+ *  along with this distribution; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA  02110-1301, USA.
+ *
+ *  (C) 2008,
+ *  @author Red Hat Middleware LLC.
+ */
+package org.jboss.jbossts.fileio.xalib.txfiles.logging;
+
+import java.io.*;
+import java.util.LinkedList;
+
+/**
+ * This class is used to handle important information with log files.
+ * <p>
+ * The class provides both read and write operations to retrieve or
+ * add new information to a log file. To manage this an object of
+ * <code>RandomAccessFile</code> class is used and data are written
+ * in binary format (<code>writeLong, writeInt</code>). The option
+ * given by a <code>RandomAccessFile</code> object to define whether
+ * to open the file in <code>r</code> or <code>rw</code> mode is useful
+ * to disallow any writes when reading the <code>log</code>.
+ *
+ * @author Ioannis Ganotis
+ * @version Jun 17, 2008
+ */
+public class RecordsLogger implements Serializable
+{
+  private String filename;
+  transient private RandomAccessFile raf;
+
+  /**
+   * Constructor to create <code>RecordsLogger</code> objects that will
+   * allow to handle <code>log</code> related information.
+   * <p>
+   * The constructor creates file with the given <code>filename</code>.
+   * The access mode is defined to be in <code>rw</code> mode as when
+   * the <code>XAResourceManager</code> opens the log to write the
+   * <code>updatedBytes</code>. When it finishes, it closes the
+   * <code>log</code> and if in recovery phase, it re-opens the log
+   * in <code>r</code> mode and retrieves all the log entries.   *
+   *
+   * @param filename the name of the log file to store to or retrieve from,
+   *                 necessary information
+   * @throws IOException if an I/O error occurs
+   */
+  public RecordsLogger(String filename) throws IOException {
+    this.filename = filename;
+    raf = new RandomAccessFile(filename, "rw");
+  }
+
+  /**
+   * Returns the name used to create this log file.
+   * @return a <code>String</code> which represents the name of
+   *         the log file.
+   */
+  public String getFilename() {
+    return filename;
+  }
+
+  /**
+   * Opens the log file in <code>r</code> mode and reads all the
+   * log entries. After that, the file is closed.
+   *
+   * @return a list with all the log entries contained in the log file
+   * @throws IOException if an I/O error occurs
+   */
+  public synchronized LinkedList<LogEntry> readAllRecords() throws IOException {
+    close();
+    raf = new RandomAccessFile(filename, "r");
+    LinkedList<LogEntry> records = new LinkedList<LogEntry>();
+    boolean eof = false;
+    do {
+      try {
+        long pos = raf.readLong();
+        int len = raf.readInt();
+        byte[] data = new byte[len];
+        raf.read(data);
+        LogEntry le = new LogEntry(pos, len, data);
+        records.add(le);
+      } catch (EOFException eofe) {
+        eof = true;
+      }
+    } while (!eof);
+    raf.close();
+    return records;
+  }
+
+  /**
+   * Appends the log file by adding a new <code>LogEntry</code> at
+   * the end. It does not actually write the <code>LogEntry</code>
+   * as an object but only the necessary information it contains.
+   *
+   * @param le the <code>LogEntry</code> to write to the log file
+   * @throws IOException if an I/O error occurs
+   */
+  public synchronized void addInfo(LogEntry le) throws IOException {
+    raf.writeLong(le.getPosition());
+    raf.writeInt(le.getRecordLength());
+    raf.write(le.getData());
+  }
+
+  /**
+   * The method gets the <code>FileDescriptor</code> of the
+   * <code>raf</code> object and calls the <code>sync</code> method
+   * to force log data to be written to disk.
+   * <p>
+   * The method is used when preparing to commit, to ensure all the
+   * updates have been written to the log.
+   *
+   * @exception IOException if an I/O error occurs
+   */
+  public void flush() throws IOException {
+    FileDescriptor fd = raf.getFD();
+    fd.sync();
+  }
+
+  /**
+   * if the <code>raf</code> object exists close it.
+   */
+  public synchronized void close() {
+    try {
+      if (raf != null)
+        raf.close();
+    } catch (IOException ioe) {
+      System.out.println("XXXX Error while processing file: " + filename + " XXXX");
+    }
+  }
+
+  /**
+   * Method to delete the log file with name <code>filename</code>.
+   * Is used by the <code>XAResourceManager</code> when it has
+   * committed or rolledback and the log is not more needed.
+   */
+  public synchronized void delete() {
+    new File(filename).delete();
+  }
+}




More information about the jboss-svn-commits mailing list