directory-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From akaras...@apache.org
Subject svn commit: rev 10593 - in incubator/directory/rms/trunk/je/src/java/org/apache/rms/je: . profile
Date Tue, 11 May 2004 14:46:48 GMT
Author: akarasulu
Date: Tue May 11 07:46:47 2004
New Revision: 10593

Added:
   incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/LoggingJeIteratorMonitor.java   (contents, props changed)
   incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/JeProfile.java   (contents, props changed)
   incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/LoggingProfileRoleLinkDAOMonitor.java   (contents, props changed)
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/JeProfileBinding.java
   incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/JeProfileDAO.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/ProfileDAO.java
   incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/ProfileDAOMonitor.java
   incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/ProfileDAOMonitorAdapter.java
   incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/ProfileRoleLinkDAO.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
Log:
Commit changes ...

 o JeIterator closes/cleans up on finalize()
 o JeIterator throws NoSuchElementException as expected on next() call when
   hasNext() returns false
 o Added logging JeIteratorMonitor based on commons logging
 o Added logging ProfileRoleLinkDAOMonitor 
 o Added temporary JeProfile object for bindings
 o Completed the JeProfileRoleLinkDAO implementation along with the supporting
   interfaces and classes ProfileRoleLinkDAO, ProfileRoleLinkDAOMonitor, 
   ProfileRoleLinkDAOMonitorAdapter, LoggingProfileRoleLinkDAOMonitor et cetera
 o Started working on the ProfileDAO



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	Tue May 11 07:46:47 2004
@@ -19,6 +19,7 @@
 
 import java.util.Iterator ;
 import java.util.Observable ;
+import java.util.NoSuchElementException;
 
 import java.io.IOException ;
 
@@ -160,6 +161,11 @@
     {
         Object retval = prefetched ;
 
+        if ( ! hasNext )
+        {
+            throw new NoSuchElementException() ;
+        }
+
         try
         {
             prefetched = prefetch() ;
@@ -405,5 +411,14 @@
                 throw e ;
             }
         }
+    }
+
+
+    /**
+     * Finalizes this JeIterator by closing it.
+     */
+    public void finalize()
+    {
+        close() ;
     }
 }

Added: incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/LoggingJeIteratorMonitor.java
==============================================================================
--- (empty file)
+++ incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/LoggingJeIteratorMonitor.java	Tue May 11 07:46:47 2004
@@ -0,0 +1,277 @@
+/*
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.apache.rms.je ;
+
+
+import org.apache.commons.logging.Log ;
+import org.apache.commons.logging.LogFactory ;
+
+
+/**
+ * A logging JeIterator monitor implementation.
+ * 
+ * @author <a href="mailto:directory-dev@incubator.apache.org">Apache Directory Project</a>
+ * @version $Rev$
+ */
+public class LoggingJeIteratorMonitor implements JeIteratorMonitor
+{
+    /** the logger used by this monitor to log events */
+    private final Log log ;
+
+
+    // -----------------------------------------------------------------------
+    // C O N S T R U C T O R S
+    // -----------------------------------------------------------------------
+
+
+    /**
+     * Initializes this monitor's logger for the JeIterator class.
+     */
+    public LoggingJeIteratorMonitor()
+    {
+        log = LogFactory.getLog( JeIterator.class ) ;
+    }
+
+
+    /**
+     * Initializes this monitor's logger for a class of logged object.
+     *
+     * @param logged the class of object being logged which might not
+     * necesarily be a JeIterator but rather a class that instantiates one.
+     */
+    public LoggingJeIteratorMonitor( Class logged )
+    {
+        log = LogFactory.getLog( logged ) ;
+    }
+
+
+    /**
+     * Initializes this monitor's logger for a logged object channel.
+     *
+     * @param logged the logging channel for the logged objects which might
+     * not necesarily be a JeIterator but rather a class that instantiates
+     * one.
+     */
+    public LoggingJeIteratorMonitor( String logged )
+    {
+        log = LogFactory.getLog( logged ) ;
+    }
+
+
+    // -----------------------------------------------------------------------
+    // Monitor Methods
+    // -----------------------------------------------------------------------
+
+
+    /**
+     * Monitor callback for iterator close events.  Use the iterator's status
+     * and the hasFailed method to determine if the iterator closed because it
+     * was exhausted naturally or some failure caused it to close prematurely.
+     *
+     * @param iterator the iterator that got closed
+     */
+    public void closed( JeIterator iterator )
+    {
+        try
+        {
+            if ( log.isDebugEnabled() )
+            {
+                log.debug( iterator + ".close() successfully invoked" ) ;
+            }
+        }
+        catch ( Throwable t )
+        {
+            log.warn( "monitor failure", t ) ;
+        }
+    }
+
+
+    /**
+     * Monitor callback for successful prefetch events within the initializer
+     * of a JeIterator.
+     *
+     * @param iterator   the iterator that prefetched an item in constructor
+     * @param prefetched the item prefetched by the iterator
+     */
+    public void prefetch( JeIterator iterator, Object prefetched )
+    {
+        try
+        {
+            if ( log.isDebugEnabled() )
+            {
+                log.debug( iterator + ".prefetch() within constructor returned"
+                        + prefetched ) ;
+            }
+        }
+        catch ( Throwable t )
+        {
+            log.warn( "monitor failure", t ) ;
+        }
+    }
+
+
+    /**
+     * Monitor callback for successful prefetch events within a next() call.
+     *
+     * @param iterator   the iterator that prefetched an item in next() call
+     * @param prefetched the last item prefetched by the iterator
+     * @param retval     the 2nd to last prefetched item to return in next()
+     * call
+     */
+    public void prefetch( JeIterator iterator, Object prefetched,
+                          Object retval )
+    {
+        try
+        {
+            if ( log.isDebugEnabled() )
+            {
+                log.debug( iterator + ".prefetch() within next() returned "
+                        + prefetched + " and the previously fetched value of "
+                        + retval + " shall be returned by next()" ) ;
+            }
+        }
+        catch ( Throwable t )
+        {
+            log.warn( "monitor failure", t ) ;
+        }
+    }
+
+
+    /**
+     * Monitor callback for cleanup failure events.
+     *
+     * @param iterator the iterator that failed on a call to cleanup
+     * @param fault    the fault that caused the failure
+     */
+    public void cleanupFailure( JeIterator iterator, Throwable fault )
+    {
+        try
+        {
+            if ( log.isWarnEnabled() )
+            {
+                log.warn( "Failed to cleanup " + iterator + ": "
+                    + fault.getMessage(), fault ) ;
+            }
+        }
+        catch ( Throwable t )
+        {
+            log.warn( "monitor failure", t ) ;
+        }
+    }
+
+
+    /**
+     * Monitor callback for prefetch failure events within a next() call.
+     *
+     * @param iterator the iterator that failed on a prefetch() within next()
+     * @param retval   last value successfully prefetched to return from next()
+     */
+    public void prefetchFailure( JeIterator iterator, Object retval )
+    {
+        try
+        {
+            if ( log.isErrorEnabled() )
+            {
+                Throwable fault = iterator.getFault() ;
+                String msg = iterator + ".prefetch() failure" ;
+                if ( fault != null  )
+                {
+                    msg += ": " + fault.getMessage() + ". " ;
+                }
+                else
+                {
+                    msg += ". " ;
+                }
+                msg += "The JeIterator has been prematurely closed and next()"
+                        + " will return the last prefetched item of "
+                        + retval + "." ;
+                log.error( msg ) ;
+            }
+        }
+        catch ( Throwable t )
+        {
+            log.warn( "monitor failure", t ) ;
+        }
+    }
+
+
+    /**
+     * Monitor callback for prefetch failure events within the constructor.
+     *
+     * @param iterator the iterator that failed to prefetch() the first time
+     */
+    public void prefetchFailure( JeIterator iterator )
+    {
+        try
+        {
+            if ( log.isErrorEnabled() )
+            {
+                Throwable fault = iterator.getFault() ;
+                String msg = iterator + ".prefetch() failure in constructor" ;
+                if ( fault != null  )
+                {
+                    msg += ": " + fault.getMessage() + ". " ;
+                }
+                else
+                {
+                    msg += ". " ;
+                }
+                msg += "The JeIterator has been prematurely closed without any"
+                        + "prefetched items." ;
+                log.error( msg ) ;
+            }
+        }
+        catch ( Throwable t )
+        {
+            log.warn( "monitor failure", t ) ;
+        }
+    }
+
+
+    /**
+     * Monitor callback for attempts to call remove which is unsupported.
+     *
+     * @param iterator the iterator on which remove was invoked
+     */
+    public void removeAttempted( JeIterator iterator )
+    {
+        try
+        {
+            if ( log.isErrorEnabled() )
+            {
+                Throwable fault = iterator.getFault() ;
+                String msg = "Unsupported remove() operation called on "
+                        + iterator ;
+                if ( fault != null  )
+                {
+                    msg += ": " + fault.getMessage() + ". " ;
+                }
+                else
+                {
+                    msg += ". " ;
+                }
+                msg += "The JeIterator has been prematurely closed." ;
+                log.error( msg ) ;
+            }
+        }
+        catch ( Throwable t )
+        {
+            log.warn( "monitor failure", t ) ;
+        }
+    }
+}
+

Added: incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/JeProfile.java
==============================================================================
--- (empty file)
+++ incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/JeProfile.java	Tue May 11 07:46:47 2004
@@ -0,0 +1,68 @@
+/*
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.apache.rms.je.profile ;
+
+
+import org.apache.rms.DefaultProfile ;
+import org.apache.rms.Application;
+import org.apache.commons.lang.NotImplementedException;
+
+import java.util.Map;
+import java.util.Observable;
+
+
+/**
+ * A profile implementation for the Je provider.
+ * 
+ * @author <a href="mailto:directory-dev@incubator.apache.org">Apache Directory Project</a>
+ * @version $Rev$
+ */
+public class JeProfile extends DefaultProfile
+{
+    JeProfile( String userName, Application app, Map roles, byte[] grants, 
+               byte[] denials, byte[] permissions )
+    {
+        super( userName, app, roles, grants, denials, permissions ) ;
+    }
+
+
+    /* (non-Javadoc)
+     * @see java.util.Observer#update(java.util.Observable, java.lang.Object)
+     */
+    public void update( Observable o, Object arg )
+    {
+        throw new NotImplementedException( "STUB" ) ;
+    }
+
+
+    public byte[] getGrantBits()
+    {
+        return super.getGrantBits() ;
+    }
+
+
+    public byte[] getDenialBits()
+    {
+        return super.getDenialBits();
+    }
+
+
+    public byte[] getEffectiveBits()
+    {
+        return super.getEffectiveBits();
+    }
+}

Modified: incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/JeProfileBinding.java
==============================================================================
--- incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/JeProfileBinding.java	(original)
+++ incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/JeProfileBinding.java	Tue May 11 07:46:47 2004
@@ -16,24 +16,78 @@
  */
 package org.apache.rms.je.profile ;
 
+
 import com.sleepycat.je.DatabaseEntry ;
 import com.sleepycat.bind.tuple.TupleInput ;
 import com.sleepycat.bind.tuple.TupleOutput ;
 import com.sleepycat.bind.tuple.TupleBinding ;
 
+import java.util.Map ;
+import java.util.HashMap ;
+import java.util.Iterator ;
 import java.io.IOException ;
 
-import org.apache.commons.lang.NotImplementedException ;
+import org.apache.commons.lang.exception.NestableRuntimeException ;
+
+import org.apache.rms.Role ;
+import org.apache.rms.Application ;
+import org.apache.rms.RmsException ;
 
 
 /**
- * A JE Profile object binding.
- * 
+ * A JE Profile object binding.  Reading and writing multiple byte arrays to an
+ * entry presents a problem since terminators for arrays are required.
+ * Basically we need to know when a byte[] begins and when it ends.  For roles
+ * the problem was easilly solved by leaving the one byte[] field at the end of
+ * the entry.  Since we have three byte[] fields to serialize for a profile
+ * we need to have terminators for at least two of the byte arrays.  Rather
+ * than use a terminator control sequence we have decided to store the length
+ * of the byte[] before it.  This way we can read the length of the array first
+ * then read the appropriate number of bytes to reconstitute the byte[].  We
+ * have decided to encode the profile object using the following order:
+ *
+ * <ol>
+ *   <li>application name String</li>
+ *   <li>user name String</li>
+ *   <li>permissions byte array length as a 4 byte integer</li>
+ *   <li>permission array bytes</li>
+ *   <li>grants byte array length as a 4 byte integer</li>
+ *   <li>grant array bytes</li>
+ *   <li>denial array bytes</li>
+ * </ol>
+ *
+ * Note that the last byte[] for denials is not prefixed by a 4 byte array
+ * length integer.  We simply read the rest of the buffer to decode or write
+ * the rest of the bytes to encode.  Also the application name and the user
+ * name will be looked up more frequently for the sake of building secondary
+ * indices.  If the length:data fields for the byte arrays were encoded first
+ * we would have to decode them to get to the application and user name
+ * fields.  This would be an added overhead when populating secondary database
+ * entries.  Hence as a rule all bindings should encode the most frequently
+ * used fields first.
+ *
  * @author <a href="mailto:directory-dev@incubator.apache.org">Apache Directory Project</a>
  * @version $Rev$
  */
 public class JeProfileBinding extends TupleBinding
 {
+    /** thread local used to associate applications with threads */
+    private final static ThreadLocal apps = new ThreadLocal() ;
+    /** used to check for app roles associated with a profile */
+    private final ProfileRoleLinkDAO roleLinkDAO ;
+
+
+    /**
+     * Creates a profile binding using a role link DAO to determine the
+     * roles associated with a profile.
+     *
+     * @param roleLinkDAO the profile role link DAO used to find profile roles
+     */
+    JeProfileBinding( ProfileRoleLinkDAO roleLinkDAO )
+    {
+        this.roleLinkDAO = roleLinkDAO ;
+    }
+
 
     // -----------------------------------------------------------------------
     // TupleBinding implementations and overrides
@@ -45,11 +99,45 @@
      *
      * @param tupleInput the tuple data
      * @return the newly constructed Profile
-     * @throws java.io.IOException if there are any failures accessing the tuple data
+     * @throws java.io.IOException if there are any failures accessing the
+     * tuple data
      */
     public Object entryToObject( TupleInput tupleInput ) throws IOException
     {
-        throw new NotImplementedException( "STUB" ) ;
+        JeProfile profile = null ;
+        Map roles = null ;
+        Application app = getApplication() ;
+        String appName = tupleInput.readString() ;
+
+        if ( ! appName.equals( app.getName() ) )
+        {
+            throw new IllegalArgumentException( "Entry application "
+                + appName + " != application associated with the thread" ) ;
+        }
+
+        String userName = tupleInput.readString() ;
+        try
+        {
+            roles = getRoles( userName, app ) ;
+        }
+        catch ( RmsException e )
+        {
+            throw new NestableRuntimeException(
+                "Failed to extract roles for user " + userName
+                + " on application " + appName, e ) ;
+        }
+
+        int length = tupleInput.readInt() ;
+        byte[] permissions = new byte[length] ;
+        tupleInput.read( permissions ) ;
+        length = tupleInput.readInt() ;
+        byte[] grants = new byte[length] ;
+        tupleInput.read( grants ) ;
+        byte[] denials = new byte[tupleInput.available()] ;
+        tupleInput.read( denials ) ;
+        profile = new JeProfile( userName, app, roles, grants,
+            denials, permissions ) ;
+        return profile ;
     }
 
 
@@ -60,9 +148,52 @@
      * @param tupleOutput
      * @throws java.io.IOException
      */
-    public void objectToEntry( Object o, TupleOutput tupleOutput ) throws IOException
+    public void objectToEntry( Object o, TupleOutput tupleOutput )
+        throws IOException
     {
-        throw new NotImplementedException( "STUB" ) ;
+        JeProfile profile = ( JeProfile ) o ;
+        tupleOutput.writeString( profile.getApplicationName() ) ;
+        tupleOutput.writeString( profile.getUserName() ) ;
+
+        // check to see if permissions are null or of zero length, if so we use a
+        // single empty byte value of 0 to store a valid permission string
+        byte[] permissions = profile.getEffectiveBits() ;
+        if ( permissions == null || permissions.length == 0 )
+        {
+            tupleOutput.writeInt( 1 ) ;
+            tupleOutput.write( 0 ) ;
+        }
+        else
+        {
+            tupleOutput.writeInt( permissions.length ) ;
+            tupleOutput.write( permissions ) ;
+        }
+
+        // check to see if grants are null or zero length, if so we use a
+        // single empty byte value of 0 to store a valid permission string
+        byte[] grants = profile.getGrantBits() ;
+        if ( grants == null || grants.length == 0 )
+        {
+            tupleOutput.writeInt( 1 ) ;
+            tupleOutput.write( 0 ) ;
+        }
+        else
+        {
+            tupleOutput.writeInt( grants.length ) ;
+            tupleOutput.write( grants ) ;
+        }
+
+        // check to see if denials are null or zero length, if so we use a
+        // single empty byte value of 0 to store a valid permission string
+        byte[] denials = profile.getDenialBits() ;
+        if ( denials == null || denials.length == 0 )
+        {
+            tupleOutput.write( 0 ) ;
+        }
+        else
+        {
+            tupleOutput.write( profile.getDenialBits() ) ;
+        }
     }
 
 
@@ -82,7 +213,50 @@
                                String userName, byte[] grants, byte[] denials,
                                byte[] permissions ) throws IOException
     {
-        throw new NotImplementedException( "STUB" ) ;
+        TupleOutput tupleOutput = new TupleOutput() ;
+        tupleOutput.writeString( appName ) ;
+        tupleOutput.writeString( userName ) ;
+
+        // if permissons are null or an empty array we write a length integer
+        // of 1 and one data byte set to zero to have a valid permission set
+        if ( permissions == null || permissions.length == 0 )
+        {
+            tupleOutput.writeInt( 1 ) ;
+            tupleOutput.write( 0 ) ;
+        }
+        else
+        {
+            tupleOutput.writeInt( permissions.length ) ;
+            tupleOutput.write( permissions ) ;
+        }
+
+        // if grants are null or an empty array we write a length integer
+        // of 1 and one data byte set to zero to have a valid permission set
+        if ( grants == null || grants.length == 0 )
+        {
+            tupleOutput.writeInt( 1 ) ;
+            tupleOutput.write( 0 ) ;
+        }
+        else
+        {
+            tupleOutput.writeInt( grants.length ) ;
+            tupleOutput.write( grants ) ;
+        }
+
+        // if denials are null or an empty array we write a length integer
+        // of 1 and one data byte set to zero to have a valid permission set
+        if ( denials == null || denials.length == 0 )
+        {
+            tupleOutput.write( 0 ) ;
+        }
+        else
+        {
+            tupleOutput.write( denials ) ;
+        }
+
+        entry.setData( tupleOutput.getBufferBytes(),
+            tupleOutput.getBufferOffset(),
+            tupleOutput.getBufferLength() ) ;
     }
 
 
@@ -95,7 +269,8 @@
      */
     public String getApplicationName( DatabaseEntry entry ) throws IOException
     {
-        throw new NotImplementedException( "STUB" ) ;
+        TupleInput in = new TupleInput( entry.getData() ) ;
+        return in.readString() ;
     }
 
 
@@ -108,7 +283,9 @@
      */
     public String getUserName( DatabaseEntry entry ) throws IOException
     {
-        throw new NotImplementedException( "STUB" ) ;
+        TupleInput in = new TupleInput( entry.getData() ) ;
+        in.readString() ; // advance past the appName field
+        return in.readString() ;
     }
 
 
@@ -122,7 +299,20 @@
      */
     public byte[] getGrants( DatabaseEntry entry ) throws IOException
     {
-        throw new NotImplementedException( "STUB" ) ;
+        TupleInput in = new TupleInput( entry.getData() ) ;
+        in.readString() ; // advance past the appName field
+        in.readString() ; // advance past the userName field
+
+        // advance past permissions byte[] unfortunately we need to read int
+        int length = in.readInt() ;
+        in.skip( length ) ;
+
+        // read the grants byte[] and return
+        length = in.readInt() ;
+        byte[] bites = new byte[length] ;
+        in.read( bites ) ;
+
+        return bites ;
     }
 
 
@@ -136,7 +326,23 @@
      */
     public byte[] getDenials( DatabaseEntry entry ) throws IOException
     {
-        throw new NotImplementedException( "STUB" ) ;
+        TupleInput in = new TupleInput( entry.getData() ) ;
+        in.readString() ; // advance past the appName field
+        in.readString() ; // advance past the userName field
+
+        // advance past permissions byte[] unfortunately we need to read int
+        int length = in.readInt() ;
+        in.skip( length ) ;
+
+        // advance past grants byte[]
+        length = in.readInt() ;
+        in.skip( length ) ;
+
+        // read the last remaining bytes and return them
+        byte[] bites = new byte[in.available()] ;
+        in.read( bites ) ;
+
+        return bites ;
     }
 
 
@@ -150,6 +356,52 @@
      */
     public byte[] getPermissions( DatabaseEntry entry ) throws IOException
     {
-        throw new NotImplementedException( "STUB" ) ;
+        TupleInput in = new TupleInput( entry.getData() ) ;
+        in.readString() ; // advance past the appName field
+        in.readString() ; // advance past the userName field
+
+        int length = in.readInt() ;
+        byte[] permissions = new byte[length] ;
+        in.read( permissions ) ;
+        return permissions ;
+    }
+
+
+    public Map getRoles( String userName, Application app )
+        throws RmsException
+    {
+        HashMap map = new HashMap() ;
+
+        Iterator list = roleLinkDAO.listRoleNames( app.getName(), userName ) ;
+        while( list.hasNext() )
+        {
+            String roleName = ( String ) list.next() ;
+            Role role = app.getRole( roleName ) ;
+            map.put( roleName, role ) ;
+        }
+
+        return map ;
+    }
+
+
+    /**
+     * Gets the application associated with the calling Thread.
+     *
+     * @return the application associated with the calling Thread
+     */
+    static Application getApplication()
+    {
+        return ( Application ) apps.get() ;
+    }
+
+
+    /**
+     * Sets the application associated with the calling Thread.
+     *
+     * @param app the application to associate with the current Thread
+     */
+    static void setApplication( Application app )
+    {
+        apps.set( app ) ;
     }
 }

Modified: incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/JeProfileDAO.java
==============================================================================
--- incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/JeProfileDAO.java	(original)
+++ incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/JeProfileDAO.java	Tue May 11 07:46:47 2004
@@ -20,10 +20,19 @@
 import org.apache.rms.Profile ;
 import org.apache.rms.Application ;
 import org.apache.rms.RmsException ;
+import org.apache.rms.je.JeRmsException ;
+import org.apache.rms.je.JeUtils;
+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 ;
+import java.io.UnsupportedEncodingException ;
+import java.io.IOException;
+
+import com.sleepycat.je.* ;
 
 
 /**
@@ -34,6 +43,156 @@
  */
 public class JeProfileDAO implements ProfileDAO
 {
+    /** the name of secondary db used to associate links with an appName */
+    public static final String APPNAME_SECDB  = "profileByAppName" ;
+    /** the name of secondary db used to associate links with an roleName */
+    public static final String USERNAME_SECDB = "profileByUserName" ;
+
+    /** the profile binding to use */
+    private final JeProfileBinding binding ;
+    /** the underlying JE profile database */
+    private final Database db ;
+    /** the sequence used to assign incremental rowIds */
+    private final Sequence sq ;
+    /** the secondary database for looking up links by appName */
+    private SecondaryDatabase byAppName ;
+    /** the secondary database for looking up links by roleName */
+    private SecondaryDatabase byUserName ;
+    /** monitor used for event callbacks */
+    private ProfileDAOMonitor monitor ;
+    /** the profile link data access object used to maintain constraints */
+    private final ProfileRoleLinkDAO roleLinkDAO ;
+
+
+    /**
+     * Creates a profile data access object for a JE database.
+     *
+     * @param db the underlying JE profile database
+     * @param sq the sequence used to assign incremental rowIds
+     */
+    public JeProfileDAO( Database db, Sequence sq, JeProfileBinding binding,
+                         ProfileRoleLinkDAO roleLinkDAO )
+        throws RmsException
+    {
+        this.db = db ;
+        this.sq = sq ;
+        this.binding = binding ;
+        this.monitor = new ProfileDAOMonitorAdapter() ;
+        this.roleLinkDAO = roleLinkDAO ;
+
+        try
+        {
+            List list = this.db.getSecondaryDatabases() ;
+
+            for ( int ii = 0; ii < list.size(); ii++ )
+            {
+                SecondaryDatabase secdb = ( SecondaryDatabase ) list.get( ii ) ;
+
+                if ( secdb.getDatabaseName().equals( APPNAME_SECDB ) )
+                {
+                    byAppName = secdb ;
+                }
+                else if ( secdb.getDatabaseName().equals( USERNAME_SECDB ) )
+                {
+                    byUserName = secdb ;
+                }
+            }
+        }
+        catch ( DatabaseException e )
+        {
+            throw new RmsException( e ) ;
+        }
+
+        Validate.notNull( byAppName ) ;
+        Validate.notNull( byUserName ) ;
+    }
+
+
+    /**
+     * Checks to see if a user profile exists for an application.
+     *
+     * @param appName  the name of the profile's application
+     * @param userName the name of the profile's user
+     * @return true if the user has a profile for the application,
+     * false otherwise
+     * @throws org.apache.rms.RmsException if there is a failure accessing the
+     * underlying database
+     */
+    public boolean has( String appName, String userName ) throws RmsException
+    {
+        OperationStatus status = null ;
+        DatabaseEntry key = new DatabaseEntry() ;
+        DatabaseEntry value = new DatabaseEntry() ;
+        DatabaseEntry appNameKey = new DatabaseEntry() ;
+        DatabaseEntry userNameKey = new DatabaseEntry() ;
+
+        try
+        {
+            appNameKey.setData( appName.getBytes( "UTF-8" ) ) ;
+            userNameKey.setData( userName.getBytes( "UTF-8" ) ) ;
+        }
+        catch ( UnsupportedEncodingException e )
+        {
+            monitor.failedOnHas( this, appName, userName, e ) ;
+            throw new RmsException( e ) ;
+        }
+
+        JoinCursor cursor = null ;
+        SecondaryCursor appNameCursor = null ;
+        SecondaryCursor userNameCursor = null ;
+
+        try
+        {
+            // -o- setup the application name cursor -o-
+            appNameCursor = byAppName.openSecondaryCursor( null, null ) ;
+            status = appNameCursor
+                .getSearchKey( appNameKey, value, LockMode.DEFAULT ) ;
+            if ( status != OperationStatus.SUCCESS )
+            {
+                throw new JeRmsException( status, "application " + appName
+                    + " lookup in secondary failed with status " + status )  ;
+            }
+
+            // -o- setup the user name cursor -o-
+            userNameCursor = byUserName.openSecondaryCursor( null, null ) ;
+            status = userNameCursor.getSearchKey( userNameKey, value,
+                LockMode.DEFAULT ) ;
+            if ( status != OperationStatus.SUCCESS )
+            {
+                throw new JeRmsException( status, "user " + userName
+                    + " lookup in secondary failed with status " + status )  ;
+            }
+
+            // -o- prepare the cursor array and the join cursor -o-
+            SecondaryCursor [] secCursors = {
+                appNameCursor,
+                userNameCursor
+            } ;
+
+            cursor = db.join( secCursors, null ) ;
+            status = cursor.getNext( key, LockMode.DEFAULT ) ;
+        }
+        catch ( DatabaseException e )
+        {
+            monitor.failedOnHas( this, appName, userName, e ) ;
+            throw new RmsException( e ) ;
+        }
+        finally
+        {
+            closeNoError( cursor ) ;
+            closeNoError( appNameCursor ) ;
+            closeNoError( userNameCursor ) ;
+        }
+
+        if ( status != OperationStatus.SUCCESS )
+        {
+            return false ;
+        }
+
+        return true ;
+    }
+
+
     /**
      * Creates a new Profile without any grants, denials, or Roles.
      *
@@ -45,7 +204,38 @@
      */
     public void create( String appName, String userName ) throws RmsException
     {
-        throw new NotImplementedException( "STUB" ) ;
+        if ( has( appName, userName ) )
+        {
+            monitor.profileExists( this, appName, userName ) ;
+            throw new RmsException( "A profile entry for user " + userName
+                + " on application " + appName + " already exists" ) ;
+        }
+
+        int rowId = sq.getNextValue() ;
+        DatabaseEntry pk = new DatabaseEntry( JeUtils.encodeInt( rowId ) ) ;
+        DatabaseEntry data = new DatabaseEntry() ;
+
+        try
+        {
+            binding.membersToEntry( data, appName, userName, null, null, null ) ;
+        }
+        catch ( IOException e )
+        {
+            monitor.failedOnCreate( this, appName, userName, e ) ;
+            throw new RmsException( "Bind failure for profile for user "
+                + userName + " on application " + appName ) ;
+        }
+
+        try
+        {
+            db.put( null, pk, data ) ;
+        }
+        catch ( DatabaseException e )
+        {
+            monitor.failedOnCreate( this, appName, userName, e ) ;
+            throw new RmsException( "Failed to put() profile entry for user " 
+                + userName + " on application " + appName, e ) ;
+        }
     }
 
 
@@ -60,7 +250,45 @@
      */
     public void delete( String appName, String userName ) throws RmsException
     {
-        throw new NotImplementedException( "STUB" ) ;
+        DatabaseEntry pk = null ;
+        
+        if ( roleLinkDAO.inAnyAppRole( appName, userName ) )
+        {
+            monitor.constraintViolationOnDelete( this, appName, userName ) ;
+            throw new RmsException( "Constraint violation: cannot delete user "
+                + userName + " who is currently in one or more roles for "
+                + "application " + appName ) ;
+        }
+
+        try
+        {
+            pk = getPkEntry( appName, userName ) ;
+        }
+        catch ( JeRmsException e )
+        {
+            monitor.failedOnDelete( this, e.getStatus(), appName, 
+                userName, e ) ;
+            throw e ;
+        }
+        catch ( RmsException e )
+        {
+            monitor.failedOnDelete( this, appName, userName, e ) ;
+            throw e ;
+        }
+
+        try
+        {
+            db.delete( null, pk ) ;
+        }
+        catch ( DatabaseException e )
+        {
+            monitor.failedOnDelete( this, appName, userName, e ) ;
+            throw new RmsException( "Failed delete operation on profile entry "
+                + "for the profile of user " + userName + " on applicatin "
+                + appName, e ) ;
+        }
+
+        monitor.profileDeleted( this, appName, userName ) ;
     }
 
 
@@ -128,5 +356,142 @@
             throws RmsException
     {
         throw new NotImplementedException( "STUB" ) ;
+    }
+
+
+    /**
+     * Looks up the primary key of a profile.
+     *
+     * @param appName  the name of the profile's application
+     * @param userName the name of the profile's user
+     * @return the primary key (rowId) entry of the link record
+     * @throws org.apache.rms.RmsException if there is a failure to access the
+     * underlying database, or the entry does not exist
+     */
+    public DatabaseEntry getPkEntry( String appName, String userName )
+        throws RmsException
+    {
+        OperationStatus status = null ;
+        DatabaseEntry key = new DatabaseEntry() ;
+        DatabaseEntry value = new DatabaseEntry() ;
+        DatabaseEntry appNameKey = new DatabaseEntry() ;
+        DatabaseEntry userNameKey = new DatabaseEntry() ;
+
+        try
+        {
+            appNameKey.setData( appName.getBytes( "UTF-8" ) ) ;
+            userNameKey.setData( userName.getBytes( "UTF-8" ) ) ;
+        }
+        catch ( UnsupportedEncodingException e )
+        {
+            monitor.failedOnLookup( this, appName, userName, e ) ;
+            throw new RmsException( e ) ;
+        }
+
+        JoinCursor cursor = null ;
+        SecondaryCursor appNameCursor = null ;
+        SecondaryCursor userNameCursor = null ;
+
+        try
+        {
+            // -o- setup the application name cursor -o-
+            appNameCursor = byAppName.openSecondaryCursor( null, null ) ;
+            status = appNameCursor
+                .getSearchKey( appNameKey, value, LockMode.DEFAULT ) ;
+            if ( status != OperationStatus.SUCCESS )
+            {
+                throw new JeRmsException( status, "application " + appName
+                    + " lookup in secondary failed with status " + status )  ;
+            }
+
+            // -o- setup the user name cursor -o-
+            userNameCursor = byUserName.openSecondaryCursor( null, null ) ;
+            status = userNameCursor.getSearchKey( userNameKey, value,
+                LockMode.DEFAULT ) ;
+            if ( status != OperationStatus.SUCCESS )
+            {
+                throw new JeRmsException( status, "user " + userName
+                    + " lookup in secondary failed with status " + status )  ;
+            }
+
+            // -o- prepare the cursor array and the join cursor -o-
+            SecondaryCursor [] secCursors = {
+                appNameCursor,
+                userNameCursor
+            } ;
+
+            cursor = db.join( secCursors, null ) ;
+            status = cursor.getNext( key, LockMode.DEFAULT ) ;
+        }
+        catch ( DatabaseException e )
+        {
+            monitor.failedOnLookup( this, appName, userName, e ) ;
+            throw new RmsException( e ) ;
+        }
+        finally
+        {
+            closeNoError( cursor ) ;
+            closeNoError( appNameCursor ) ;
+            closeNoError( userNameCursor ) ;
+        }
+
+        if ( status != OperationStatus.SUCCESS )
+        {
+            throw new JeRmsException( status, "profile for user " + userName
+                + " in application " + appName
+                + " not found due to join status of " + status )  ;
+        }
+
+        return key ;
+    }
+
+
+    /**
+     * Closes a cursor without throwing an error.
+     *
+     * @param cursor the cursor to close.
+     */
+    private void closeNoError( Cursor cursor )
+    {
+        if ( cursor == null )
+        {
+            return ;
+        }
+
+        try
+        {
+            cursor.close() ;
+        }
+        catch ( DatabaseException e )
+        {
+            monitor.failedOnCleanupOperation( this, "close", cursor, e ) ;
+        }
+
+        monitor.cleanedUp( this, "close", cursor ) ;
+    }
+
+
+    /**
+     * Closes a cursor without throwing an error.
+     *
+     * @param cursor the cursor to close.
+     */
+    private void closeNoError( JoinCursor cursor )
+    {
+        if ( cursor == null )
+        {
+            return ;
+        }
+
+        try
+        {
+            cursor.close() ;
+        }
+        catch ( DatabaseException e )
+        {
+            monitor.failedOnCleanupOperation( this, "close", cursor, e ) ;
+        }
+
+        monitor.cleanedUp( this, "close", cursor ) ;
     }
 }

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	Tue May 11 07:46:47 2004
@@ -21,6 +21,7 @@
 import org.apache.rms.RmsException ;
 import org.apache.rms.je.JeIterator ;
 import org.apache.rms.je.JeRmsException ;
+import org.apache.rms.je.LoggingJeIteratorMonitor;
 import org.apache.rms.je.sequence.Sequence ;
 
 import org.apache.commons.lang.Validate ;
@@ -49,6 +50,9 @@
     /** the name of secondary db used to associate links with an roleName */
     public static final String ROLENAME_SECDB = "roleLinkByRoleName" ;
 
+    private static final LoggingJeIteratorMonitor LIST_MONITOR
+            = new LoggingJeIteratorMonitor( JeProfileRoleLinkDAO.class ) ;
+
     /** the primary database used to store profile role links */
     private final Database db ;
     /** the sequence used for link row ids */
@@ -350,7 +354,7 @@
      * @throws org.apache.rms.RmsException if there is a failure to access the
      * underlying database
      */
-    public boolean has( String appName, String roleName ) throws RmsException
+    public boolean isRoleInUse( String appName, String roleName ) throws RmsException
     {
         OperationStatus status = null ;
         DatabaseEntry key = new DatabaseEntry() ;
@@ -365,7 +369,7 @@
         }
         catch ( UnsupportedEncodingException e )
         {
-            monitor.failedOnHas( this, appName, roleName, e ) ;
+            monitor.failedOnIsRoleInUse( this, appName, roleName, e ) ;
             throw new RmsException( e ) ;
         }
 
@@ -378,7 +382,7 @@
             // -o- setup the application name cursor -o-
             appNameCursor = byAppName.openSecondaryCursor( null, null ) ;
             status = appNameCursor
-                    .getSearchKey( appNameKey, value, LockMode.DEFAULT ) ;
+                .getSearchKey( appNameKey, value, LockMode.DEFAULT ) ;
             if ( status != OperationStatus.SUCCESS )
             {
                 return false ;
@@ -387,7 +391,7 @@
             // -o- setup the role name cursor -o-
             roleNameCursor = byRoleName.openSecondaryCursor( null, null ) ;
             status = roleNameCursor.getSearchKey( roleNameKey, value,
-                    LockMode.DEFAULT ) ;
+                LockMode.DEFAULT ) ;
             if ( status != OperationStatus.SUCCESS )
             {
                 return false ;
@@ -404,7 +408,7 @@
         }
         catch ( DatabaseException e )
         {
-            monitor.failedOnHas( this, appName, roleName, e ) ;
+            monitor.failedOnIsRoleInUse( this, appName, roleName, e ) ;
             throw new RmsException( e ) ;
         }
         finally
@@ -415,7 +419,86 @@
         }
 
         boolean haveIt = status == OperationStatus.SUCCESS ;
-        monitor.successOnHas( this, appName, roleName, haveIt ) ;
+        monitor.successOnIsRoleInUse( this, appName, roleName, haveIt ) ;
+        return haveIt ;
+    }
+
+
+    /**
+     * Quick check to see if a user's profile is in any application role.
+     *
+     * @param appName  the name of the profile's application
+     * @param userName the name of the profile's user
+     * @return true if the application role is in use, false otherwise
+     * @throws org.apache.rms.RmsException if there is a failure to access the
+     * underlying database
+     */
+    public boolean inAnyAppRole( String appName, String userName ) throws RmsException
+    {
+        OperationStatus status = null ;
+        DatabaseEntry key = new DatabaseEntry() ;
+        DatabaseEntry value = new DatabaseEntry() ;
+        DatabaseEntry appNameKey = new DatabaseEntry() ;
+        DatabaseEntry userNameKey = new DatabaseEntry() ;
+
+        try
+        {
+            appNameKey.setData( appName.getBytes( "UTF-8" ) ) ;
+            userNameKey.setData( userName.getBytes( "UTF-8" ) ) ;
+        }
+        catch ( UnsupportedEncodingException e )
+        {
+            monitor.failedOnInAnyAppRole( this, appName, userName, e ) ;
+            throw new RmsException( e ) ;
+        }
+
+        JoinCursor cursor = null ;
+        SecondaryCursor appNameCursor = null ;
+        SecondaryCursor userNameCursor = null ;
+
+        try
+        {
+            // -o- setup the application name cursor -o-
+            appNameCursor = byAppName.openSecondaryCursor( null, null ) ;
+            status = appNameCursor
+                .getSearchKey( appNameKey, value, LockMode.DEFAULT ) ;
+            if ( status != OperationStatus.SUCCESS )
+            {
+                return false ;
+            }
+
+            // -o- setup the role name cursor -o-
+            userNameCursor = byUserName.openSecondaryCursor( null, null ) ;
+            status = userNameCursor.getSearchKey( userNameKey, value,
+                LockMode.DEFAULT ) ;
+            if ( status != OperationStatus.SUCCESS )
+            {
+                return false ;
+            }
+
+            // -o- prepare the cursor array and the join cursor -o-
+            SecondaryCursor [] secCursors = {
+                appNameCursor,
+                userNameCursor
+            } ;
+
+            cursor = db.join( secCursors, null ) ;
+            status = cursor.getNext( key, LockMode.DEFAULT ) ;
+        }
+        catch ( DatabaseException e )
+        {
+            monitor.failedOnInAnyAppRole( this, appName, userName, e ) ;
+            throw new RmsException( e ) ;
+        }
+        finally
+        {
+            closeNoError( cursor ) ;
+            closeNoError( appNameCursor ) ;
+            closeNoError( userNameCursor ) ;
+        }
+
+        boolean haveIt = status == OperationStatus.SUCCESS ;
+        monitor.successOnInAnyAppRole( this, appName, userName, haveIt ) ;
         return haveIt ;
     }
 
@@ -499,6 +582,7 @@
             JeIterator iterator = new JeIterator( cursor, secCursors,
                     JeProfileRoleLinkBinding.ROLENAME_BINDING, true ) ;
             monitor.listingRoleNames( this, appName, userName, iterator ) ;
+            iterator.setMonitor( LIST_MONITOR ) ;
             return iterator ;
         }
         catch ( DatabaseException e )
@@ -600,6 +684,7 @@
             JeIterator iterator = new JeIterator( cursor, secCursors,
                     JeProfileRoleLinkBinding.USERNAME_BINDING, true ) ;
             monitor.listingUserNames( this, appName, roleName, iterator ) ;
+            iterator.setMonitor( LIST_MONITOR ) ;
             return iterator ;
         }
         catch ( DatabaseException e )
@@ -643,8 +728,7 @@
 
 
     /**
-     * Quick check to see if a user's application profile is associated with a
-     * specific role.
+     * Looks up the primary key of a profile role link.
      *
      * @param appName  the name of the profile's application
      * @param userName the name of the profile's user
@@ -653,7 +737,7 @@
      * @throws org.apache.rms.RmsException if there is a failure to access the
      * underlying database, or the entry does not exist
      */
-    public DatabaseEntry getPkEntry( String appName, String userName,
+    DatabaseEntry getPkEntry( String appName, String userName,
                                      String roleName ) throws RmsException
     {
         OperationStatus status = null ;

Added: incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/LoggingProfileRoleLinkDAOMonitor.java
==============================================================================
--- (empty file)
+++ incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/LoggingProfileRoleLinkDAOMonitor.java	Tue May 11 07:46:47 2004
@@ -0,0 +1,546 @@
+/*
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.apache.rms.je.profile ;
+
+
+import org.apache.commons.logging.Log ;
+import org.apache.commons.logging.LogFactory ;
+
+import java.util.Iterator ;
+
+
+/**
+ * A logging monitor for a profile role link data access object.
+ * 
+ * @author <a href="mailto:directory-dev@incubator.apache.org">Apache Directory Project</a>
+ * @version $Rev$
+ */
+public class LoggingProfileRoleLinkDAOMonitor
+        implements ProfileRoleLinkDAOMonitor
+{
+    /** the logger use by this monitor to log events */
+    private Log log = LogFactory.getLog( ProfileRoleLinkDAO.class ) ;
+
+
+    public void roleLinkExists( ProfileRoleLinkDAO dao, String op,
+                                String appName, String userName,
+                                String roleName )
+    {
+        try
+        {
+            if ( log.isErrorEnabled() )
+            {
+                log.error( dao + "." + op
+                    + "() failed because the link for role "
+                    + roleName + " in application "  + appName
+                    + " already exists for user " + userName ) ;
+            }
+        }
+        catch( Throwable t )
+        {
+            log.warn( "Monitor failure", t ) ;
+        }
+    }
+
+
+    public void failedLinkBinding( ProfileRoleLinkDAO dao, String op,
+                                   String appName, String userName,
+                                   String roleName, Throwable fault )
+    {
+        try
+        {
+            if ( log.isErrorEnabled() )
+            {
+                log.error( dao + "." + op + "() failed to bind the data "
+                        + "within a database entry for "
+                        + roleName + " in application "  + appName
+                        + " already exists for user " + userName + ": "
+                        + fault.getMessage(), fault ) ;
+            }
+        }
+        catch( Throwable t )
+        {
+            log.warn( "Monitor failure", t ) ;
+        }
+    }
+
+    public void roleLinkCreated( ProfileRoleLinkDAO dao, String appName,
+                                 String userName, String roleName )
+    {
+        try
+        {
+            if ( log.isDebugEnabled() )
+            {
+                log.debug( dao + " linked role " + roleName
+                        + " for application " + appName
+                        + " to profile for user " + userName ) ;
+            }
+        }
+        catch( Throwable t )
+        {
+            log.warn( "Monitor failure", t ) ;
+        }
+    }
+
+
+    public void failedOnCreate( ProfileRoleLinkDAO dao, String appName,
+                                String userName, String roleName,
+                                Throwable fault )
+    {
+        try
+        {
+            if ( log.isErrorEnabled() )
+            {
+                log.error( dao + ".create() failed to link role "
+                        + roleName + " for application " + appName
+                        + " to profile for user " + userName + ": "
+                        + fault.getMessage(), fault ) ;
+            }
+        }
+        catch( Throwable t )
+        {
+            log.warn( "Monitor failure", t ) ;
+        }
+    }
+
+
+    public void failedOnCreate( ProfileRoleLinkDAO dao, Object info,
+                                String appName, String userName,
+                                String roleName )
+    {
+        try
+        {
+            if ( log.isErrorEnabled() )
+            {
+                log.error( dao + ".create() failed to link role "
+                        + roleName + " for application " + appName
+                        + " to profile for user " + userName ) ;
+            }
+        }
+        catch( Throwable t )
+        {
+            log.warn( "Monitor failure", t ) ;
+        }
+    }
+
+
+    public void cleanedUp( ProfileRoleLinkDAO dao, String op, Object resource )
+    {
+        try
+        {
+            if ( log.isDebugEnabled() )
+            {
+                log.debug( dao + " invoked " + resource + "." + op
+                        + " to cleanup the resource." ) ;
+            }
+        }
+        catch( Throwable t )
+        {
+            log.warn( "Monitor failure", t ) ;
+        }
+    }
+
+
+    public void failedOnCleanupOperation( ProfileRoleLinkDAO dao,
+                                          String op, Object resource,
+                                          Throwable fault )
+    {
+        try
+        {
+            if ( log.isWarnEnabled() )
+            {
+                log.warn(  dao + " called " + resource + "." + op
+                        + " to cleanup resource but the call failed: "
+                        + fault.getMessage(), fault ) ;
+            }
+        }
+        catch( Throwable t )
+        {
+            log.warn( "Monitor failure", t ) ;
+        }
+    }
+
+
+    public void failedOnHas( ProfileRoleLinkDAO dao, String appName,
+                             String userName, String roleName,
+                             Throwable fault )
+    {
+        try
+        {
+            if ( log.isErrorEnabled() )
+            {
+                log.warn( dao
+                    + ".has() failed while checking for link on role "
+                    + roleName + " for application " + appName + " on "
+                    + userName + "'s profile" ) ;
+            }
+        }
+        catch( Throwable t )
+        {
+            log.warn( "Monitor failure", t ) ;
+        }
+    }
+
+
+    public void failedOnHas( ProfileRoleLinkDAO dao, String appName,
+                             String roleName, Throwable fault )
+    {
+        try
+        {
+            if ( log.isErrorEnabled() )
+            {
+                log.error( dao
+                    + ".has() failed while checking to see if role " + roleName
+                    + " for application " + appName
+                    + " is being used by a user's profile: "
+                    + fault.getMessage(), fault ) ;
+            }
+        }
+        catch( Throwable t )
+        {
+            log.warn( "Monitor failure", t ) ;
+        }
+    }
+
+
+    public void successOnHas( ProfileRoleLinkDAO dao, String appName,
+                              String userName, String roleName,
+                              boolean haveIt )
+    {
+        try
+        {
+            if ( log.isDebugEnabled() )
+            {
+                String msg = dao.toString() + ".has() succeeded and " ;
+                if ( haveIt )
+                {
+                    msg += "found " ;
+                }
+                else
+                {
+                    msg += "did NOT find " ;
+                }
+                msg += "link for application " + appName + "'s role "
+                    + roleName + " on user " + userName + "'s profile." ;
+                log.debug( msg ) ;
+            }
+        }
+        catch( Throwable t )
+        {
+            log.warn( "Monitor failure", t ) ;
+        }
+    }
+
+
+    public void successOnHas( ProfileRoleLinkDAO dao, String appName,
+                              String roleName, boolean haveIt )
+    {
+        try
+        {
+            if ( log.isDebugEnabled() )
+            {
+                String msg = dao.toString() + ".has() succeeded and " ;
+                if ( haveIt )
+                {
+                    msg += "found " ;
+                }
+                else
+                {
+                    msg += "did NOT find " ;
+                }
+                msg += "a link for application " + appName + "'s role "
+                    + roleName + " on one or more user's profile." ;
+                log.debug( msg ) ;
+            }
+        }
+        catch( Throwable t )
+        {
+            log.warn( "Monitor failure", t ) ;
+        }
+    }
+
+
+    public void roleLinkDoesNotExist( ProfileRoleLinkDAO dao, String op,
+                                      String appName, String userName,
+                                      String roleName )
+    {
+        try
+        {
+            if ( log.isErrorEnabled() )
+            {
+                log.error( dao + "." + op + " failed because a link for "
+                    + "application " + appName + "'s role " + roleName
+                    + " on user " + userName + " does not exist" ) ;
+            }
+        }
+        catch( Throwable t )
+        {
+            log.warn( "Monitor failure", t ) ;
+        }
+    }
+
+
+    public void failedOnDelete( ProfileRoleLinkDAO dao, String appName,
+                                String userName, String roleName,
+                                Throwable fault )
+    {
+        try
+        {
+            if ( log.isErrorEnabled() )
+            {
+                log.error( dao + ".delete() failed on the link for "
+                    + "application " + appName + "'s role " + roleName
+                    + " on user " + userName + "'s profile" ) ;
+            }
+        }
+        catch( Throwable t )
+        {
+            log.warn( "Monitor failure", t ) ;
+        }
+    }
+
+
+    public void roleLinkDeleted( ProfileRoleLinkDAO dao, String appName,
+                                 String userName, String roleName )
+    {
+        try
+        {
+            if ( log.isDebugEnabled() )
+            {
+                log.debug( dao + ".delete() succeeded on the link for "
+                    + "application " + appName + "'s role " + roleName
+                    + " on user " + userName + "'s profile" ) ;
+            }
+        }
+        catch( Throwable t )
+        {
+            log.warn( "Monitor failure", t ) ;
+        }
+    }
+
+
+    public void failedToListRoleNames( ProfileRoleLinkDAO dao, Object info,
+                                       String appName, String userName )
+    {
+        try
+        {
+            if ( log.isErrorEnabled() )
+            {
+                log.error( dao + " failed to list the role names linked to "
+                    + "user " + userName + "'s profile for application "
+                    + appName + ": " + info.toString() ) ;
+            }
+        }
+        catch( Throwable t )
+        {
+            log.warn( "Monitor failure", t ) ;
+        }
+    }
+
+
+    public void failedToListRoleNames( ProfileRoleLinkDAO dao, String appName,
+                                       String userName, Throwable fault )
+    {
+        try
+        {
+            if ( log.isErrorEnabled() )
+            {
+                log.error( dao + " failed to list the role names linked to "
+                    + "user " + userName + "'s profile for application "
+                    + appName + ": " + fault.getMessage(), fault ) ;
+            }
+        }
+        catch( Throwable t )
+        {
+            log.warn( "Monitor failure", t ) ;
+        }
+    }
+
+
+    public void failedToListUserNames( ProfileRoleLinkDAO dao, Object info,
+                                       String appName, String roleName )
+    {
+        try
+        {
+            if ( log.isErrorEnabled() )
+            {
+                log.error( dao + " failed to list the user names of profiles"
+                    + " linked to role " + roleName + " of application "
+                    + appName + ": " + info.toString() ) ;
+            }
+        }
+        catch( Throwable t )
+        {
+            log.warn( "Monitor failure", t ) ;
+        }
+    }
+
+
+    public void failedToListUserNames( ProfileRoleLinkDAO dao, String appName,
+                                       String roleName, Throwable fault )
+    {
+        try
+        {
+            if ( log.isErrorEnabled() )
+            {
+                log.error( dao + " failed to list the user names of profiles"
+                    + " linked to role " + roleName + " of application "
+                    + appName + ": " + fault.getMessage(), fault ) ;
+            }
+        }
+        catch( Throwable t )
+        {
+            log.warn( "Monitor failure", t ) ;
+        }
+    }
+
+
+    public void listingRoleNames( ProfileRoleLinkDAO dao, String appName,
+                                  String userName, Iterator iterator )
+    {
+        try
+        {
+            if ( log.isDebugEnabled() )
+            {
+                log.debug( dao + " successfully listed the roles linked "
+                    + "to the profile of " + userName + " for application "
+                    + appName + " with iterator " + iterator ) ;
+            }
+        }
+        catch( Throwable t )
+        {
+            log.warn( "Monitor failure", t ) ;
+        }
+    }
+
+
+    public void listingUserNames( ProfileRoleLinkDAO dao, String appName,
+                                  String userName, Iterator iterator )
+    {
+        try
+        {
+            if ( log.isDebugEnabled() )
+            {
+                log.debug( dao + " successfully listed the roles "
+                    + "associated with the profile of " + userName
+                    + " for application " + appName + " with iterator "
+                    + iterator ) ;
+            }
+        }
+        catch( Throwable t )
+        {
+            log.warn( "Monitor failure", t ) ;
+        }
+    }
+
+
+    public void successOnIsRoleInUse( ProfileRoleLinkDAO dao, String appName,
+                                      String roleName, boolean haveIt )
+    {
+        try
+        {
+            if ( log.isDebugEnabled() )
+            {
+                String msg = dao + " succeeded while checking to see if one "
+                    + "or more user profiles were linked to application "
+                    + appName + " role " + roleName ;
+
+                if ( haveIt )
+                {
+                    msg += ". At least one link found: the role is in use!" ;
+                }
+                else
+                {
+                    msg += ". No link found: the role is NOT in use!" ;
+                }
+                log.debug( msg ) ;
+            }
+        }
+        catch( Throwable t )
+        {
+            log.warn( "Monitor failure", t ) ;
+        }
+    }
+
+
+    public void failedOnInAnyAppRole( ProfileRoleLinkDAO dao, String appName,
+                                      String userName, Throwable fault )
+    {
+        try
+        {
+            if ( log.isErrorEnabled() )
+            {
+                log.error( dao + " failed while attempting to check if user "
+                    + userName + " is in any role for application " + appName
+                    + ": " + fault.getMessage(), fault ) ;
+            }
+        }
+        catch( Throwable t )
+        {
+            log.warn( "Monitor failure", t ) ;
+        }
+    }
+
+
+    public void successOnInAnyAppRole( ProfileRoleLinkDAO dao, String appName,
+                                       String userName, boolean haveIt )
+    {
+        try
+        {
+            if ( log.isDebugEnabled() )
+            {
+                String msg = dao + " succeeded while checking to see if user "
+                    + userName + " is in one or more application " + appName
+                    + " roles." ;
+
+                if ( haveIt )
+                {
+                    msg += ". The user is in at least one application role!" ;
+                }
+                else
+                {
+                    msg += ". The user is NOT in any application role!" ;
+                }
+                log.debug( msg ) ;
+            }
+        }
+        catch( Throwable t )
+        {
+            log.warn( "Monitor failure", t ) ;
+        }
+    }
+
+
+    public void failedOnIsRoleInUse( ProfileRoleLinkDAO dao, String appName,
+                                     String roleName, Throwable fault )
+    {
+        try
+        {
+            if ( log.isErrorEnabled() )
+            {
+                log.error( dao + " failed while attempting to check if role "
+                    + roleName + " for application " + appName
+                    + " is used by any user profile." + ": "
+                    + fault.getMessage(), fault ) ;
+            }
+        }
+        catch( Throwable t )
+        {
+            log.warn( "Monitor failure", t ) ;
+        }
+    }
+}

Modified: incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/ProfileDAO.java
==============================================================================
--- incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/ProfileDAO.java	(original)
+++ incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/ProfileDAO.java	Tue May 11 07:46:47 2004
@@ -36,6 +36,18 @@
 public interface ProfileDAO
 {
     /**
+     * Checks to see if a user profile exists for an application.
+     *
+     * @param appName the name of the profile's application
+     * @param userName the name of the profile's user
+     * @return true if the user has a profile for the application,
+     * false otherwise
+     * @throws RmsException if there is a failure accessing the underlying
+     * database
+     */
+    boolean has( String appName, String userName ) throws RmsException ;
+
+    /**
      * Creates a new Profile without any grants, denials, or Roles.
      *
      * @param appName the name of the profile's application

Modified: incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/ProfileDAOMonitor.java
==============================================================================
--- incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/ProfileDAOMonitor.java	(original)
+++ incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/ProfileDAOMonitor.java	Tue May 11 07:46:47 2004
@@ -17,6 +17,9 @@
 package org.apache.rms.je.profile ;
 
 
+import com.sleepycat.je.OperationStatus ;
+
+
 /**
  * The monitor interface for a Profile data access object.
  * 
@@ -25,4 +28,40 @@
  */
 public interface ProfileDAOMonitor
 {
+    void failedOnLookup( ProfileDAO dao, String appName, String userName,
+                         Throwable fault ) ;
+
+
+    void failedOnCleanupOperation( ProfileDAO dao, String op, Object resource,
+                                   Throwable fault ) ;
+
+
+    void cleanedUp( ProfileDAO dao, String op, Object resource ) ;
+
+
+    void failedOnHas( ProfileDAO dao, String appName, String userName,
+                      Throwable fault ) ;
+
+
+    void profileExists( ProfileDAO dao, String appName, String userName ) ;
+
+
+    void failedOnCreate( ProfileDAO dao, String appName, String userName,
+                         Throwable fault ) ;
+
+
+    void failedOnDelete( ProfileDAO dao, OperationStatus status,
+                         String appName, String userName, Throwable fault ) ;
+
+
+    void failedOnDelete( ProfileDAO dao, String appName, String userName,
+                         Throwable fault ) ;
+
+
+    void profileDeleted( ProfileDAO dao, String appName, String userName ) ;
+
+
+    void constraintViolationOnDelete( ProfileDAO dao, String appName,
+                                      String userName ) ;
+
 }

Modified: incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/ProfileDAOMonitorAdapter.java
==============================================================================
--- incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/ProfileDAOMonitorAdapter.java	(original)
+++ incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/ProfileDAOMonitorAdapter.java	Tue May 11 07:46:47 2004
@@ -17,6 +17,9 @@
 package org.apache.rms.je.profile ;
 
 
+import org.apache.commons.lang.NotImplementedException;
+
+
 /**
  * A no-op monitor adapter which at a bare minimum dumps exception stack
  * traces to stderr.
@@ -24,6 +27,29 @@
  * @author <a href="mailto:directory-dev@incubator.apache.org">Apache Directory Project</a>
  * @version $Rev$
  */
-public class ProfileDAOMonitorAdapter
+public class ProfileDAOMonitorAdapter implements ProfileDAOMonitor
 {
+    public void failedOnLookup( ProfileDAO dao, String appName,
+                                String userName, Throwable fault )
+    {
+        if ( fault != null )
+        {
+            fault.printStackTrace() ;
+        }
+    }
+
+
+    public void failedOnCleanupOperation( ProfileDAO dao, String op,
+                                          Object resource, Throwable fault )
+    {
+        if ( fault != null )
+        {
+            fault.printStackTrace() ;
+        }
+    }
+
+
+    public void cleanedUp( ProfileDAO dao, String op, Object resource )
+    {
+    }
 }

Modified: incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/ProfileRoleLinkDAO.java
==============================================================================
--- incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/ProfileRoleLinkDAO.java	(original)
+++ incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/ProfileRoleLinkDAO.java	Tue May 11 07:46:47 2004
@@ -77,7 +77,20 @@
      * @throws RmsException if there is a failure to access the
      * underlying database
      */
-    boolean has( String appName, String roleName ) throws RmsException ;
+    boolean isRoleInUse( String appName, String roleName )
+        throws RmsException ;
+
+    /**
+     * Quick check to see if a user profile is in any application role.
+     *
+     * @param appName the name of the profile's user
+     * @param userName the name of the profile's role
+     * @return true if the user is in an application role, false otherwise
+     * @throws RmsException if there is a failure to access the
+     * underlying database
+     */
+    boolean inAnyAppRole( String appName, String userName )
+        throws RmsException ;
 
     /**
      * Gets an Iterator over the names of roles a user's application profile

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	Tue May 11 07:46:47 2004
@@ -263,14 +263,64 @@
 
 
     /**
-     * Monitor callback for events where an iterator is created over the user
-     * names of profiles associated with an application role.
+     * Monitor callback for events where an iterator is created over the role
+     * names of an application's user profile.
      *
      * @param dao the dao that created the iterator
      * @param appName the name of the application
-     * @param userName the name of the user
+     * @param roleName the name of the role
      * @param iterator the iterator created
      */ 
     void listingUserNames( ProfileRoleLinkDAO dao, String appName,
-                           String userName, Iterator iterator ) ;
+                           String roleName, Iterator iterator ) ;
+
+    /**
+     * Monitor callback for events where there is a failure to check if a user
+     * is in any 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 fault the fault that caused the failure
+     */
+    void failedOnInAnyAppRole( ProfileRoleLinkDAO dao, String appName,
+                               String userName, Throwable fault ) ;
+
+    /**
+     * Monitor callback for events where the check to see if a user is in any
+     * application role succeeds.
+     *
+     * @param dao the dao that created the iterator
+     * @param appName the name of the application
+     * @param userName the name of the user
+     * @param haveIt true if a link exists to any application role for the
+     * profile, false otherwise
+     */
+    void successOnInAnyAppRole( ProfileRoleLinkDAO dao, String appName,
+                                String userName, boolean haveIt ) ;
+
+    /**
+     * Monitor callback for events where there is a failure to determine if a
+     * role is being used by one or more user profiles.
+     *
+     * @param dao the dao that created the iterator
+     * @param appName the name of the application
+     * @param roleName the name of the role to check for usage
+     * @param fault the fault that caused the failure
+     */
+    void failedOnIsRoleInUse( ProfileRoleLinkDAO dao, String appName,
+                              String roleName, Throwable fault ) ;
+
+    /**
+     * Monitor callback for events where the check to see if a role is in use
+     * by one or more user profiles succeeds.
+     *
+     * @param dao the dao that created the iterator
+     * @param appName the name of the application
+     * @param roleName the name of the role to check for usage
+     * @param haveIt true if one or more links exist to any profile for the
+     * role, false otherwise
+     */
+    void successOnIsRoleInUse( ProfileRoleLinkDAO dao, String appName,
+                               String roleName, boolean haveIt ) ;
 }

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	Tue May 11 07:46:47 2004
@@ -17,7 +17,7 @@
 package org.apache.rms.je.profile ;
 
 
-import java.util.Iterator ; 
+import java.util.Iterator ;
 
 
 /**
@@ -180,5 +180,33 @@
 
     public void listingUserNames( ProfileRoleLinkDAO dao, String appName, String userName, Iterator iterator )
     {
+    }
+
+
+    public void successOnIsRoleInUse( ProfileRoleLinkDAO dao, String appName, String roleName, boolean haveIt )
+    {
+    }
+
+
+    public void failedOnInAnyAppRole( ProfileRoleLinkDAO dao, String appName, String userName, Throwable fault )
+    {
+        if ( fault != null )
+        {
+            fault.printStackTrace() ;
+        }
+    }
+
+
+    public void successOnInAnyAppRole( ProfileRoleLinkDAO dao, String appName, String userName, boolean haveIt )
+    {
+    }
+
+
+    public void failedOnIsRoleInUse( ProfileRoleLinkDAO dao, String appName, String roleName, Throwable fault )
+    {
+        if ( fault != null )
+        {
+            fault.printStackTrace() ;
+        }
     }
 }

Mime
View raw message