You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by ak...@apache.org on 2004/05/01 19:53:08 UTC

svn commit: rev 10481 - in incubator/directory/rms/trunk/je/src: java/org/apache/rms/je java/org/apache/rms/je/profile test/org/apache/rms/je/profile

Author: akarasulu
Date: Sat May  1 10:53:07 2004
New Revision: 10481

Modified:
   incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/JeIterator.java
   incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/JeProfileRoleLinkBinding.java
   incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/JeProfileRoleLinkDAO.java
   incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/ProfileRoleLinkDAOMonitor.java
   incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/ProfileRoleLinkDAOMonitorAdapter.java
   incubator/directory/rms/trunk/je/src/test/org/apache/rms/je/profile/JeProfileRoleLinkDAOTest.java
Log:
Commit changes ...

 o completed the JeIterator with a work around for the JoinCursor.close() bug
 o removed iterator inner classes in link dao which are handled by JeIterator
 o completed the final monitor interface for ProfileRoleLinkDAO
 o implemented no-op monitor adapter methods 
 o moved binding constants to JeProfileRoleLinkBinding where they belong
 o cleaned up JeProfileRoleLinkDAOTest which again passes all green



Modified: incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/JeIterator.java
==============================================================================
--- incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/JeIterator.java	(original)
+++ incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/JeIterator.java	Sat May  1 10:53:07 2004
@@ -20,17 +20,28 @@
 import java.util.Iterator ;
 import java.util.Observable ;
 
-import com.sleepycat.je.OperationStatus ;
+import java.io.IOException ;
+
+import com.sleepycat.je.* ;
+import com.sleepycat.bind.EntryBinding ;
 
 
 /**
- * A special JE iterator implementation that tries to cleanup cursor resources
- * when consumed or failures result.
+ * A JE iterator that tries to cleanup cursor resources when consumed or
+ * failures result.
+ *
+ * Goals:
+ * <ul>
+ *   <li>Implement observable pattern to track open/closed cursors</li>
+ *   <li>Keep it simple - other Iterators can wrap this one to customize</li>
+ *   <li>Return raw pk or data or objects via optional binding</li>
+ *   <li>Allow access to raw pk or data</li>
+ * </ul>
  * 
  * @author <a href="mailto:directory-dev@incubator.apache.org">Apache Directory Project</a>
  * @version $Rev$
  */
-public abstract class JeIterator extends Observable implements Iterator
+public class JeIterator extends Observable implements Iterator
 {
     /** tracks if we have another item to return */
     private boolean hasNext = true ;
@@ -43,13 +54,70 @@
     /** a failure if one has occurred */
     private Throwable fault ;
 
+    /** the Join cursor that we wrap */
+    private final JoinCursor cursor ;
+    /** the database entry primary key populated */
+    private final DatabaseEntry pk ;
+    /** the database entry data populated */
+    private final DatabaseEntry data ;
+    /** the optional entry binding to use */
+    private final EntryBinding binding ;
+    /** the secondary cursors for the JoinCursor */
+    private final SecondaryCursor[] secCursors ;
+
 
     /**
-     * Creates a JeIterator with an initial monitor adapter.
-     */
-    protected JeIterator()
-    {
+     * Creates a JeIterator that iterates over primary key entries, values or
+     * bound object using an optional binding.
+     *
+     * @param cursor the underlying join cursor being wrapped
+     * @param secCursors due to a bug we need them to close em our selves
+     * @param binding optional binding to apply to pk or data before it is
+     * returned in the prefetch operation
+     * @param getBoth whether or not to fetch both the pk and the data - if
+     * true the data is fetched as well
+     */
+    public JeIterator( JoinCursor cursor, SecondaryCursor[] secCursors,
+                       EntryBinding binding, boolean getBoth )
+            throws DatabaseException, IOException
+    {
+        this.pk = new DatabaseEntry() ;
+        this.cursor = cursor ;
+        this.secCursors = secCursors ;
         this.monitor = new JeIteratorMonitorAdapter() ;
+        this.binding = binding ;
+
+        if ( getBoth )
+        {
+            this.data = new DatabaseEntry() ;
+        }
+        else
+        {
+            this.data = null ;
+        }
+
+        try
+        {
+            prefetched = prefetch() ;
+        }
+        catch ( DatabaseException e )
+        {
+            close( e ) ;
+            monitor.prefetchFailure( this ) ;
+            throw e ;
+        }
+        catch ( IOException e )
+        {
+            close( e ) ;
+            monitor.prefetchFailure( this ) ;
+            throw e ;
+        }
+        catch ( Error e )
+        {
+            close( e ) ;
+            monitor.prefetchFailure( this ) ;
+            throw e ;
+        }
     }
 
 
@@ -74,7 +142,7 @@
     /**
      * Gets the boolean hasNext flag for this iterator.
      *
-     * @return whether or not another value is available by calling next()
+     * @return whether or not another data is available by calling next()
      */
     public final boolean hasNext()
     {
@@ -83,8 +151,8 @@
 
 
     /**
-     * Saves the last prefetched value which is returned but before returning
-     * it prefetches the next value.   Failures and succcesses are reported to
+     * Saves the last prefetched data which is returned but before returning
+     * it prefetches the next data.   Failures and succcesses are reported to
      * the monitor.
      *
      * @return the next item in the iteration
@@ -155,6 +223,17 @@
 
 
     /**
+     * Gets the optional binding for this iterator.
+     *
+     * @return the optional binding for this iterator
+     */
+    public final EntryBinding getBinding()
+    {
+        return binding ;
+    }
+
+
+    /**
      * Sets and returns the status for call chaining - closes this iterator if
      * status is not equal to OperationStatus.SUCCESS.
      *
@@ -240,11 +319,44 @@
 
 
     /**
+     * Gets the primary key entry.
+     *
+     * @return the primary key entry
+     */
+    public final DatabaseEntry getPrimaryKey()
+    {
+        return pk ;
+    }
+
+
+    /**
+     * Gets the record data if both pk and data fetches are enabled.
+     *
+     * @return the record data
+     */
+    public final DatabaseEntry getRecordData()
+    {
+        return data ;
+    }
+
+
+    /**
+     * Gets whether or not this iterator fetches record data.
+     *
+     * @return whether or not this iterator fetches record data
+     */
+    public final boolean hasRecordData()
+    {
+        return data != null ;
+    }
+
+
+    /**
      * Gets the monitor for this JeIterator.
      *
      * @return the monitor currently in use for sending event callbacks to
      */
-    protected JeIteratorMonitor getMonitor()
+    protected final JeIteratorMonitor getMonitor()
     {
         return this.monitor ;
     }
@@ -279,16 +391,71 @@
      * invoked.
      *
      * @return the a prefetched item from the iteration
-     * @throws Exception if there are any failures at all while prefetching
+     * @throws DatabaseException if any failures accessing the database
+     * @throws DatabaseException if any failures occur while binding
      */
-    protected abstract Object prefetch() throws Exception ;
+    protected final Object prefetch() throws DatabaseException, IOException
+    {
+        if ( data != null )
+        {
+            setStatus( cursor.getNext( pk, data, LockMode.DEFAULT ) ) ;
+
+            if ( binding != null )
+            {
+                return binding.entryToObject( data ) ;
+            }
+
+            return data ;
+        }
+        else
+        {
+            setStatus( cursor.getNext( pk, data, LockMode.DEFAULT ) ) ;
+
+            if ( binding != null )
+            {
+                return binding.entryToObject( pk ) ;
+            }
+
+            return pk ;
+        }
+    }
 
 
     /**
-     * Concrete JeIterators must cleanup within this method which most likely
-     * means closing JE Cursors.
+     * Cleans up by closing the JoinCursor for this iterator which in turn
+     * should close all the SecondaryCursors used but this does not seem to
+     * work.  This should be overridden to close all the SecondaryCursors
+     * used to construct the JoinCursor.
      *
-     * @throws Exception if there are any failures at all while cleaning up
+     * @throws DatabaseException on failures while closing the join cursor
      */
-    protected abstract void cleanup() throws Exception ;
+    protected void cleanup() throws DatabaseException
+    {
+        DatabaseException e = null ;
+
+        for( int ii = 0 ; ii < secCursors.length; ii++ )
+        {
+            try
+            {
+                if ( secCursors[ii] != null )
+                {
+                    secCursors[ii].close() ;
+                }
+            }
+            catch ( DatabaseException thrown )
+            {
+                e = thrown ;
+            }
+        }
+
+        if ( cursor != null )
+        {
+            cursor.close() ;
+
+            if ( e != null )
+            {
+                throw e ;
+            }
+        }
+    }
 }

Modified: incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/JeProfileRoleLinkBinding.java
==============================================================================
--- incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/JeProfileRoleLinkBinding.java	(original)
+++ incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/JeProfileRoleLinkBinding.java	Sat May  1 10:53:07 2004
@@ -20,6 +20,7 @@
 import com.sleepycat.bind.tuple.TupleInput ;
 import com.sleepycat.bind.tuple.TupleOutput ;
 import com.sleepycat.bind.tuple.TupleBinding ;
+import com.sleepycat.bind.EntryBinding;
 
 import java.io.IOException ;
 
@@ -37,6 +38,38 @@
  */
 public class JeProfileRoleLinkBinding extends TupleBinding
 {
+    /** the binding used by this profile role link DAO */
+    public static final JeProfileRoleLinkBinding BINDING =
+            new JeProfileRoleLinkBinding() ;
+    /** the binding used by iterators to get the role name from entries */
+    public static final EntryBinding ROLENAME_BINDING = new EntryBinding()
+    {
+        public Object entryToObject( DatabaseEntry entry )
+                throws IOException
+        {
+            return BINDING.getRoleName( entry ) ;
+        }
+
+        public void objectToEntry( Object object, DatabaseEntry entry )
+        {
+            throw new UnsupportedOperationException() ;
+        }
+    } ;
+    /** the binding used by iterators to get the user name from entries */
+    public static final EntryBinding USERNAME_BINDING = new EntryBinding()
+    {
+        public Object entryToObject( DatabaseEntry entry )
+                throws IOException
+        {
+            return BINDING.getUserName( entry ) ;
+        }
+
+        public void objectToEntry( Object object, DatabaseEntry entry )
+        {
+            throw new UnsupportedOperationException() ;
+        }
+    } ;
+
 
     // -----------------------------------------------------------------------
     // TupleBinding implementations and overrides

Modified: incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/JeProfileRoleLinkDAO.java
==============================================================================
--- incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/JeProfileRoleLinkDAO.java	(original)
+++ incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/JeProfileRoleLinkDAO.java	Sat May  1 10:53:07 2004
@@ -18,13 +18,12 @@
 
 
 import org.apache.rms.je.JeUtils ;
-import org.apache.rms.je.JeRmsException;
-import org.apache.rms.je.JeIterator;
 import org.apache.rms.RmsException ;
+import org.apache.rms.je.JeIterator ;
+import org.apache.rms.je.JeRmsException ;
 import org.apache.rms.je.sequence.Sequence ;
 
 import org.apache.commons.lang.Validate ;
-import org.apache.commons.lang.NotImplementedException;
 
 import java.util.List ;
 import java.util.Iterator ;
@@ -43,9 +42,6 @@
  */
 public class JeProfileRoleLinkDAO implements ProfileRoleLinkDAO
 {
-    /** the binding used by this profile role link DAO */
-    public static final JeProfileRoleLinkBinding BINDING =
-            new JeProfileRoleLinkBinding() ;
     /** the name of secondary db used to associate links with an appName */
     public static final String APPNAME_SECDB  = "roleLinkByAppName" ;
     /** the name of secondary db used to associate links with an roleName */
@@ -155,7 +151,7 @@
 
         try
         {
-            BINDING.membersToEntry( value, appName, userName, roleName ) ;
+            JeProfileRoleLinkBinding.BINDING.membersToEntry( value, appName, userName, roleName ) ;
             status = db.put( null, key, value ) ;
         }
         catch ( IOException e )
@@ -438,7 +434,89 @@
     public Iterator listRoleNames( String appName, String userName )
             throws RmsException
     {
-        return new RoleLinkRoleNameIterator( appName, userName ) ;
+        JoinCursor cursor = null ;
+        OperationStatus status = null ;
+        SecondaryCursor appNameCursor = null ;
+        SecondaryCursor userNameCursor = null ;
+        DatabaseEntry value = new DatabaseEntry() ;
+        DatabaseEntry appNameKey = new DatabaseEntry() ;
+        DatabaseEntry userNameKey = new DatabaseEntry() ;
+
+        // ---------------------------------------------------------------
+        // set the keys for both user and app name cursors
+        // ---------------------------------------------------------------
+
+        try
+        {
+            appNameKey.setData( appName.getBytes( "UTF-8" ) ) ;
+            userNameKey.setData( userName.getBytes( "UTF-8" ) ) ;
+        }
+        catch ( UnsupportedEncodingException e )
+        {
+            monitor.failedLinkBinding( JeProfileRoleLinkDAO.this,
+                    "RoleLinkRoleNameIterator(<init>)", appName, userName,
+                    "unknown", e ) ;
+            throw new RmsException( e ) ;
+        }
+
+        try
+        {
+            // ---------------------------------------------------------------
+            // setup the application name cursor
+            // ---------------------------------------------------------------
+
+            appNameCursor = byAppName.openSecondaryCursor( null, null ) ;
+            status = appNameCursor.getSearchKey( appNameKey, value, LockMode.DEFAULT ) ;
+            if ( status != OperationStatus.SUCCESS )
+            {
+                monitor.failedToListRoleNames( this, status, appName, userName ) ;
+                throw new JeRmsException( status, "application " + appName
+                    + " lookup in secondary failed with status " + status )  ;
+            }
+
+            // ---------------------------------------------------------------
+            // setup the user name cursor
+            // ---------------------------------------------------------------
+
+            userNameCursor = byUserName.openSecondaryCursor( null, null ) ;
+            status = userNameCursor.getSearchKey( userNameKey, value,
+                    LockMode.DEFAULT ) ;
+            if ( status != OperationStatus.SUCCESS )
+            {
+                monitor.failedToListRoleNames( this, status, appName,
+                        userName ) ;
+                throw new JeRmsException( status, "user " + userName
+                    + " lookup in secondary failed with status " + status )  ;
+            }
+
+            // ---------------------------------------------------------------
+            // prepare the cursor array and the join cursor
+            // ---------------------------------------------------------------
+
+            SecondaryCursor [] secCursors = { appNameCursor, userNameCursor } ;
+            cursor = db.join( secCursors, null ) ;
+
+            JeIterator iterator = new JeIterator( cursor, secCursors,
+                    JeProfileRoleLinkBinding.ROLENAME_BINDING, true ) ;
+            monitor.listingRoleNames( this, appName, userName, iterator ) ;
+            return iterator ;
+        }
+        catch ( DatabaseException e )
+        {
+            closeNoError( cursor ) ;
+            closeNoError( appNameCursor ) ;
+            closeNoError( userNameCursor ) ;
+            monitor.failedToListRoleNames( this, appName, userName, e ) ;
+            throw new RmsException( e ) ;
+        }
+        catch ( IOException e )
+        {
+            closeNoError( cursor ) ;
+            closeNoError( appNameCursor ) ;
+            closeNoError( userNameCursor ) ;
+            monitor.failedToListRoleNames( this, appName, userName, e ) ;
+            throw new RmsException( e ) ;
+        }
     }
 
 
@@ -456,7 +534,90 @@
     public Iterator listUserNames( String appName, String roleName )
             throws RmsException
     {
-        return new RoleLinkUserNameIterator( appName, roleName ) ;
+        JoinCursor cursor = null ;
+        OperationStatus status = null ;
+        SecondaryCursor appNameCursor = null ;
+        SecondaryCursor roleNameCursor = null ;
+        DatabaseEntry value = new DatabaseEntry() ;
+        DatabaseEntry appNameKey = new DatabaseEntry() ;
+        DatabaseEntry roleNameKey = new DatabaseEntry() ;
+
+        // ---------------------------------------------------------------
+        // set the keys for both user and app name cursors
+        // ---------------------------------------------------------------
+
+        try
+        {
+            appNameKey.setData( appName.getBytes( "UTF-8" ) ) ;
+            roleNameKey.setData( roleName.getBytes( "UTF-8" ) ) ;
+        }
+        catch ( UnsupportedEncodingException e )
+        {
+            monitor.failedLinkBinding( JeProfileRoleLinkDAO.this,
+                    "RoleLinkRoleNameIterator(<init>)", appName, roleName,
+                    "unknown", e ) ;
+            throw new RmsException( e ) ;
+        }
+
+        try
+        {
+            // ---------------------------------------------------------------
+            // setup the application name cursor
+            // ---------------------------------------------------------------
+
+            appNameCursor = byAppName.openSecondaryCursor( null, null ) ;
+            status = appNameCursor.getSearchKey( appNameKey, value,
+                    LockMode.DEFAULT ) ;
+            if ( status != OperationStatus.SUCCESS )
+            {
+                monitor.failedToListUserNames( this, status, appName,
+                        roleName ) ;
+                throw new JeRmsException( status, "application " + appName
+                    + " lookup in secondary failed with status " + status )  ;
+            }
+
+            // ---------------------------------------------------------------
+            // setup the user name cursor
+            // ---------------------------------------------------------------
+
+            roleNameCursor = byRoleName.openSecondaryCursor( null, null ) ;
+            status = roleNameCursor.getSearchKey( roleNameKey, value,
+                    LockMode.DEFAULT ) ;
+            if ( status != OperationStatus.SUCCESS )
+            {
+                monitor.failedToListUserNames( this, status, appName,
+                        roleName ) ;
+                throw new JeRmsException( status, "role " + roleName
+                    + " lookup in secondary failed with status " + status )  ;
+            }
+
+            // ---------------------------------------------------------------
+            // prepare the cursor array and the join cursor
+            // ---------------------------------------------------------------
+
+            SecondaryCursor [] secCursors = { appNameCursor, roleNameCursor } ;
+            cursor = db.join( secCursors, null ) ;
+            JeIterator iterator = new JeIterator( cursor, secCursors,
+                    JeProfileRoleLinkBinding.USERNAME_BINDING, true ) ;
+            monitor.listingUserNames( this, appName, roleName, iterator ) ;
+            return iterator ;
+        }
+        catch ( DatabaseException e )
+        {
+            closeNoError( cursor ) ;
+            closeNoError( appNameCursor ) ;
+            closeNoError( roleNameCursor ) ;
+            monitor.failedToListUserNames( this, appName, roleName, e ) ;
+            throw new RmsException( e ) ;
+        }
+        catch ( IOException e )
+        {
+            closeNoError( cursor ) ;
+            closeNoError( appNameCursor ) ;
+            closeNoError( roleNameCursor ) ;
+            monitor.failedToListUserNames( this, appName, roleName, e ) ;
+            throw new RmsException( e ) ;
+        }
     }
 
 
@@ -469,13 +630,9 @@
      */
     public void close( Iterator list )
     {
-        if ( list instanceof RoleLinkRoleNameIterator )
-        {
-            ( ( RoleLinkRoleNameIterator ) list ).close() ;
-        }
-        else if ( list instanceof RoleLinkUserNameIterator )
+        if ( list instanceof JeIterator )
         {
-            ( ( RoleLinkUserNameIterator ) list ).close() ;
+            ( ( JeIterator ) list ).close() ;
         }
     }
 
@@ -663,292 +820,5 @@
     public void setMonitor( ProfileRoleLinkDAOMonitor monitor )
     {
         this.monitor = monitor ;
-    }
-
-
-    // -----------------------------------------------------------------------
-    // Cursor Based Iterators
-    // -----------------------------------------------------------------------
-
-
-    /**
-     * An iterator over the set of role names a user application profile
-     * is associated with.
-     */
-    class RoleLinkRoleNameIterator extends JeIterator
-    {
-        final DatabaseEntry key = new DatabaseEntry() ;
-        final DatabaseEntry value = new DatabaseEntry() ;
-        final DatabaseEntry appNameKey = new DatabaseEntry() ;
-        final DatabaseEntry userNameKey = new DatabaseEntry() ;
-
-        final String appName ;
-        final String userName ;
-
-        JoinCursor cursor = null ;
-        SecondaryCursor appNameCursor = null ;
-        SecondaryCursor userNameCursor = null ;
-
-
-        /**
-         * An iterator over the set of role names a user application profile
-         * is associated with.
-         *
-         * @param appName the name of the application
-         * @param userName the name of the user
-         * @throws RmsException if there is a failure while accessing the
-         * backing store to setup this iterator
-         */
-        RoleLinkRoleNameIterator( String appName, String userName )
-                throws RmsException
-        {
-            this.appName = appName ;
-            this.userName = userName ;
-
-            // ---------------------------------------------------------------
-            // set the keys for both user and app name cursors
-            // ---------------------------------------------------------------
-
-            try
-            {
-                appNameKey.setData( appName.getBytes( "UTF-8" ) ) ;
-                userNameKey.setData( userName.getBytes( "UTF-8" ) ) ;
-            }
-            catch ( UnsupportedEncodingException e )
-            {
-                monitor.failedLinkBinding( JeProfileRoleLinkDAO.this,
-                        "RoleLinkRoleNameIterator(<init>)", appName, userName,
-                        "unknown", e ) ;
-                throw new RmsException( e ) ;
-            }
-
-            try
-            {
-                // ---------------------------------------------------------------
-                // setup the application name cursor
-                // ---------------------------------------------------------------
-
-                appNameCursor = byAppName.openSecondaryCursor( null, null ) ;
-                setStatus( appNameCursor.getSearchKey( appNameKey, value, LockMode.DEFAULT ) ) ;
-                if ( getStatus() != OperationStatus.SUCCESS )
-                {
-                    monitor.initFailure( JeProfileRoleLinkDAO.this, this,
-                            appName, userName ) ;
-                    throw new JeRmsException( getStatus(), "application " + appName
-                        + " lookup in secondary failed with status " + getStatus() )  ;
-                }
-
-                // ---------------------------------------------------------------
-                // setup the user name cursor
-                // ---------------------------------------------------------------
-
-                userNameCursor = byUserName.openSecondaryCursor( null, null ) ;
-                setStatus( userNameCursor.getSearchKey( userNameKey, value,
-                        LockMode.DEFAULT ) ) ;
-                if ( getStatus() != OperationStatus.SUCCESS )
-                {
-                    monitor.initFailure( JeProfileRoleLinkDAO.this, this,
-                            appName, userName ) ;
-                    throw new JeRmsException( getStatus(), "user " + userName
-                        + " lookup in secondary failed with status " + getStatus() )  ;
-                }
-
-                // ---------------------------------------------------------------
-                // prepare the cursor array and the join cursor
-                // ---------------------------------------------------------------
-
-                SecondaryCursor [] secCursors = {
-                    appNameCursor, userNameCursor
-                } ;
-                cursor = db.join( secCursors, null ) ;
-                setStatus( cursor.getNext( key, value, LockMode.DEFAULT ) ) ;
-            }
-            catch ( DatabaseException e )
-            {
-                close() ;
-                monitor.roleIteratorSetupFailure( this, appName, userName, e ) ;
-                throw new RmsException( e ) ;
-            }
-
-
-            if ( getStatus() == OperationStatus.SUCCESS )
-            {
-                try
-                {
-                    setPrefetched( BINDING.getRoleName( value ) ) ;
-                    getMonitor().prefetch( this, getPrefetched() ) ;
-                }
-                catch ( IOException e )
-                {
-                    close( e ) ;
-                    getMonitor().prefetchFailure( this ) ;
-                    throw new RmsException( e ) ;
-                }
-
-                getMonitor().prefetch( this, getPrefetched() ) ;
-            }
-            else
-            {
-                close() ;
-                monitor.roleIteratorEmpty( JeProfileRoleLinkDAO.this, this,
-                        appName, userName ) ;
-            }
-        }
-
-
-        protected void cleanup() throws Exception
-        {
-            closeNoError( cursor ) ;
-            closeNoError( appNameCursor ) ;
-            closeNoError( userNameCursor ) ;
-        }
-
-
-        protected Object prefetch() throws Exception
-        {
-            setStatus( cursor.getNext( key, value, LockMode.DEFAULT ) ) ;
-            return BINDING.getRoleName( value ) ;
-        }
-    }
-
-
-    /**
-     * An iterator over the set of user names an application role is
-     * associated with.
-     */
-    class RoleLinkUserNameIterator extends JeIterator
-    {
-        final DatabaseEntry key = new DatabaseEntry() ;
-        final DatabaseEntry value = new DatabaseEntry() ;
-        final DatabaseEntry appNameKey = new DatabaseEntry() ;
-        final DatabaseEntry roleNameKey = new DatabaseEntry() ;
-
-        final String appName ;
-        final String roleName ;
-
-        JoinCursor cursor = null ;
-        SecondaryCursor appNameCursor = null ;
-        SecondaryCursor roleNameCursor = null ;
-
-
-        /**
-         * An iterator over the set of user names an application profile is
-         * associated with.
-         *
-         * @param appName the name of the application
-         * @param roleName the name of the user
-         * @throws RmsException if there is a failure while accessing the
-         * backing store to setup this iterator
-         */
-        RoleLinkUserNameIterator( String appName, String roleName )
-                throws RmsException
-        {
-            this.appName = appName ;
-            this.roleName = roleName ;
-
-            // ---------------------------------------------------------------
-            // set the keys for both user and app name cursors
-            // ---------------------------------------------------------------
-
-            try
-            {
-                appNameKey.setData( appName.getBytes( "UTF-8" ) ) ;
-                roleNameKey.setData( roleName.getBytes( "UTF-8" ) ) ;
-            }
-            catch ( UnsupportedEncodingException e )
-            {
-                monitor.failedLinkBinding( JeProfileRoleLinkDAO.this,
-                        "RoleLinkUserNameIterator(<init>)", appName, roleName,
-                        "unknown", e ) ;
-                throw new RmsException( e ) ;
-            }
-
-            try
-            {
-                // ---------------------------------------------------------------
-                // setup the application name cursor
-                // ---------------------------------------------------------------
-
-                appNameCursor = byAppName.openSecondaryCursor( null, null ) ;
-                setStatus( appNameCursor.getSearchKey( appNameKey, value, LockMode.DEFAULT ) ) ;
-                if ( getStatus() != OperationStatus.SUCCESS )
-                {
-                    monitor.initFailure( JeProfileRoleLinkDAO.this, this,
-                            appName, roleName ) ;
-                    throw new JeRmsException( getStatus(), "application " + appName
-                        + " lookup in secondary failed with status " + getStatus() )  ;
-                }
-
-                // ---------------------------------------------------------------
-                // setup the role name cursor
-                // ---------------------------------------------------------------
-
-                roleNameCursor = byRoleName.openSecondaryCursor( null, null ) ;
-                setStatus( roleNameCursor.getSearchKey( roleNameKey, value,
-                        LockMode.DEFAULT ) ) ;
-                if ( getStatus() != OperationStatus.SUCCESS )
-                {
-                    monitor.initFailure( JeProfileRoleLinkDAO.this, this,
-                            appName, roleName ) ;
-                    throw new JeRmsException( getStatus(), "role " + roleName
-                        + " lookup in secondary failed with status " + getStatus() )  ;
-                }
-
-                // ---------------------------------------------------------------
-                // prepare the cursor array and the join cursor
-                // ---------------------------------------------------------------
-
-                SecondaryCursor [] secCursors = {
-                    appNameCursor, roleNameCursor
-                } ;
-                cursor = db.join( secCursors, null ) ;
-                setStatus( cursor.getNext( key, value, LockMode.DEFAULT ) ) ;
-            }
-            catch ( DatabaseException e )
-            {
-                close() ;
-                monitor.roleIteratorSetupFailure( this, appName, roleName, e ) ;
-                throw new RmsException( e ) ;
-            }
-
-
-            if ( getStatus() == OperationStatus.SUCCESS )
-            {
-                try
-                {
-                    setPrefetched( BINDING.getUserName( value ) ) ;
-                    getMonitor().prefetch( this, getPrefetched() ) ;
-                }
-                catch ( IOException e )
-                {
-                    close( e ) ;
-                    getMonitor().prefetchFailure( this ) ;
-                    throw new RmsException( e ) ;
-                }
-
-                getMonitor().prefetch( this, getPrefetched() ) ;
-            }
-            else
-            {
-                close() ;
-                monitor.roleIteratorEmpty( JeProfileRoleLinkDAO.this, this,
-                        appName, roleName ) ;
-            }
-        }
-
-
-        protected void cleanup() throws Exception
-        {
-            closeNoError( cursor ) ;
-            closeNoError( appNameCursor ) ;
-            closeNoError( roleNameCursor ) ;
-        }
-
-
-        protected Object prefetch() throws Exception
-        {
-            setStatus( cursor.getNext( key, value, LockMode.DEFAULT ) ) ;
-            return BINDING.getUserName( value ) ;
-        }
     }
 }

Modified: incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/ProfileRoleLinkDAOMonitor.java
==============================================================================
--- incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/ProfileRoleLinkDAOMonitor.java	(original)
+++ incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/ProfileRoleLinkDAOMonitor.java	Sat May  1 10:53:07 2004
@@ -17,9 +17,7 @@
 package org.apache.rms.je.profile ;
 
 
-import com.sleepycat.je.DatabaseException;
-
-import java.util.Iterator;
+import java.util.Iterator ;
 
 
 /**
@@ -199,34 +197,80 @@
     void roleLinkDeleted( ProfileRoleLinkDAO dao, String appName,
                           String userName, String roleName ) ;
 
-    void initFailure( ProfileRoleLinkDAO dao, Iterator list, String appName,
-                      String userName ) ;
-
-
-    void roleIteratorEmpty( JeProfileRoleLinkDAO jeProfileRoleLinkDAO,
-                            JeProfileRoleLinkDAO.RoleLinkRoleNameIterator roleLinkRoleNameIterator, String appName,
-                            String userName );
-
+    /**
+     * Monitor callback for failed attempts to get an iterator listing the set
+     * of role names a user's application profile is associated with.
+     *
+     * @param dao the dao that failed to produce a role name listing
+     * @param info extra impl dependent information about the failure
+     * @param appName the name of the application
+     * @param userName the name of the role
+     */
+    void failedToListRoleNames( ProfileRoleLinkDAO dao, Object info,
+                                String appName, String userName ) ;
 
-    void roleIteratorSetupFailure( JeProfileRoleLinkDAO.RoleLinkRoleNameIterator roleLinkRoleNameIterator,
-                                   String appName, String userName, DatabaseException e );
 
+    /**
+     * Monitor callback for failed attempts to get an iterator listing the set
+     * of role names a user's application profile is associated with.
+     *
+     * @param dao the dao that failed to produce a role name listing
+     * @param appName the name of the application
+     * @param userName the name of the role
+     * @param fault the fault that caused the failure
+     */
+    void failedToListRoleNames( ProfileRoleLinkDAO dao, String appName,
+                                String userName, Throwable fault ) ;
 
-    void roleIteratorSetupFailure( JeProfileRoleLinkDAO.RoleLinkUserNameIterator roleLinkUserNameIterator,
-                                   String appName, String roleName );
 
+    /**
+     * Monitor callback for failed attempts to get an iterator listing the set
+     * of users an application role is associated with.
+     *
+     * @param dao the dao that failed to produce a user name listing
+     * @param info extra impl dependent information about the failure
+     * @param appName the name of the application
+     * @param roleName the name of the role
+     */
+    void failedToListUserNames( ProfileRoleLinkDAO dao, Object info,
+                                String appName, String roleName ) ;
 
-    void roleIteratorReady( JeProfileRoleLinkDAO jeProfileRoleLinkDAO,
-                            JeProfileRoleLinkDAO.RoleLinkUserNameIterator roleLinkUserNameIterator, String appName,
-                            String roleName, String prefetched );
 
+    /**
+     * Monitor callback for failed attempts to get an iterator listing the set
+     * of users an application role is associated with.
+     *
+     * @param dao the dao that failed to produce a user name listing
+     * @param appName the name of the application
+     * @param roleName the name of the role
+     * @param fault the fault that caused the failure
+     */
+    void failedToListUserNames( ProfileRoleLinkDAO dao, String appName,
+                                String roleName, Throwable fault ) ;
 
-    void roleIteratorEmpty( JeProfileRoleLinkDAO jeProfileRoleLinkDAO,
-                            JeProfileRoleLinkDAO.RoleLinkUserNameIterator roleLinkRoleNameIterator, String appName,
-                            String roleName );
 
+    /**
+     * Monitor callback for events where an iterator is created over the role
+     * names of a user's application profile.
+     *
+     * @param dao the dao that created the iterator
+     * @param appName the name of the application
+     * @param userName the name of the user
+     * @param iterator the iterator created
+     */
+    void listingRoleNames( ProfileRoleLinkDAO dao, String appName,
+                           String userName, Iterator iterator ) ;
 
-    void roleIteratorSetupFailure( JeProfileRoleLinkDAO.RoleLinkUserNameIterator roleLinkRoleNameIterator,
-                                   String appName, String roleName, DatabaseException e );
 
+    /**
+     * Monitor callback for events where an iterator is created over the user
+     * names of profiles associated with an application role.
+     *
+     * @param dao the dao that created the iterator
+     * @param appName the name of the application
+     * @param userName the name of the user
+     * @param iterator the iterator created
+     */ 
+    void listingUserNames( ProfileRoleLinkDAO dao, String appName,
+                           String userName, Iterator iterator ) ;
 }

Modified: incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/ProfileRoleLinkDAOMonitorAdapter.java
==============================================================================
--- incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/ProfileRoleLinkDAOMonitorAdapter.java	(original)
+++ incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/ProfileRoleLinkDAOMonitorAdapter.java	Sat May  1 10:53:07 2004
@@ -17,9 +17,7 @@
 package org.apache.rms.je.profile ;
 
 
-import com.sleepycat.je.DatabaseException;
-
-import java.util.Iterator;
+import java.util.Iterator ; 
 
 
 /**
@@ -147,70 +145,40 @@
     }
 
 
-    /////////////////////////////////////////////////////////////////////////
-
-    //                           Crap from here on                         //
-
-
-    public void roleIteratorFailure( JeProfileRoleLinkDAO.RoleLinkRoleNameIterator roleLinkRoleNameIterator,
-                                     String appName, String userName, DatabaseException e )
-    {
-    }
-
-
-    public void roleIteratorReady( JeProfileRoleLinkDAO jeProfileRoleLinkDAO,
-                                   JeProfileRoleLinkDAO.RoleLinkRoleNameIterator roleLinkRoleNameIterator,
-                                   String appName, String userName, String prefetched )
-    {
-    }
-
-
-    public void roleIteratorSetupFailure( JeProfileRoleLinkDAO.RoleLinkRoleNameIterator roleLinkRoleNameIterator,
-                                          String appName, String userName, DatabaseException e )
-    {
-    }
-
-
-    public void roleIteratorEmpty( JeProfileRoleLinkDAO jeProfileRoleLinkDAO,
-                                   JeProfileRoleLinkDAO.RoleLinkRoleNameIterator roleLinkRoleNameIterator,
-                                   String appName, String userName )
+    public void failedToListRoleNames( ProfileRoleLinkDAO dao, Object info, String appName, String userName )
     {
     }
 
 
-    public void roleIteratorSetupFailure( JeProfileRoleLinkDAO.RoleLinkRoleNameIterator roleLinkRoleNameIterator,
-                                          String appName, String userName )
-    {
-    }
-
-
-    public void roleIteratorSetupFailure( JeProfileRoleLinkDAO.RoleLinkUserNameIterator roleLinkRoleNameIterator,
-                                          String appName, String roleName )
+    public void failedToListRoleNames( ProfileRoleLinkDAO dao, String appName, String userName, Throwable fault )
     {
+        if ( fault != null )
+        {
+            fault.printStackTrace() ;
+        }
     }
 
 
-    public void roleIteratorSetupFailure( JeProfileRoleLinkDAO.RoleLinkUserNameIterator roleLinkRoleNameIterator,
-                                          String appName, String roleName, DatabaseException e )
+    public void failedToListUserNames( ProfileRoleLinkDAO dao, Object info, String appName, String roleName )
     {
     }
 
 
-    public void roleIteratorReady( JeProfileRoleLinkDAO jeProfileRoleLinkDAO,
-                                   JeProfileRoleLinkDAO.RoleLinkUserNameIterator roleLinkRoleNameIterator,
-                                   String appName, String roleName, String prefetched )
+    public void failedToListUserNames( ProfileRoleLinkDAO dao, String appName, String userName, Throwable fault )
     {
+        if ( fault != null )
+        {
+            fault.printStackTrace() ;
+        }
     }
 
 
-    public void roleIteratorEmpty( JeProfileRoleLinkDAO jeProfileRoleLinkDAO,
-                                   JeProfileRoleLinkDAO.RoleLinkUserNameIterator roleLinkRoleNameIterator,
-                                   String appName, String roleName )
+    public void listingRoleNames( ProfileRoleLinkDAO dao, String appName, String userName, Iterator iterator )
     {
     }
 
 
-    public void initFailure( ProfileRoleLinkDAO dao, Iterator list, String appName, String userName )
+    public void listingUserNames( ProfileRoleLinkDAO dao, String appName, String userName, Iterator iterator )
     {
     }
 }

Modified: incubator/directory/rms/trunk/je/src/test/org/apache/rms/je/profile/JeProfileRoleLinkDAOTest.java
==============================================================================
--- incubator/directory/rms/trunk/je/src/test/org/apache/rms/je/profile/JeProfileRoleLinkDAOTest.java	(original)
+++ incubator/directory/rms/trunk/je/src/test/org/apache/rms/je/profile/JeProfileRoleLinkDAOTest.java	Sat May  1 10:53:07 2004
@@ -18,13 +18,14 @@
 
 
 import org.apache.rms.je.AbstractJeTest ;
-import org.apache.rms.je.sequence.JeSequenceDao;
-import org.apache.rms.je.sequence.Sequence;
-import org.apache.rms.je.sequence.JeSequenceFactory;
-import com.sleepycat.je.SecondaryConfig;
-import com.sleepycat.je.Database;
+import org.apache.rms.je.sequence.Sequence ;
+import org.apache.rms.je.sequence.JeSequenceDao ;
+import org.apache.rms.je.sequence.JeSequenceFactory ;
 
-import java.util.Iterator;
+import com.sleepycat.je.Database ;
+import com.sleepycat.je.SecondaryConfig ;
+
+import java.util.Iterator ;
 
 
 /**