Dupont jean wrote:
> I'm effectively trying to lock access to a POP3 user mailbox using the J2SE
> 5.0 ReentrantLock implementation.
>
> this is the revelant part of my handler
>
> ------
> public class Pop3ProtocolHandler extends IoHandlerAdapter implements
> AbstractPop3Handler
> {
> ...
> public void messageReceived(IoSession session, Object message)
> throws Exception
> {
> log.info("Request processed by thread "+Thread.currentThread());
> String request = (String) message;
>
> if (request == null)
> {
> session.close();
> return;
> }
>
> log.info("C: " + request);
> String commandName = new StringTokenizer(request, "
> ").nextToken().toUpperCase();
> Pop3Command command = Pop3CommandRegistry.getCommand(commandName);
> MinaPop3Connection conn = (MinaPop3Connection)
> session.getAttribute(CONN_OBJECT);
>
> if (command == null)
> {
> conn.println("-ERR Command not recognized");
> return;
> }
>
> Pop3State state = (Pop3State) session.getAttribute(STATE_OBJECT);
> if (!command.isValidForState(state))
> {
> conn.println("-ERR Command not valid for this state");
> return;
> }
>
> command.execute(this, conn, state, request);
>
> if
> (((Boolean)session.getAttribute(PEER_CLOSED_SESSION)).booleanValue())
> session.close();
> }
> ....
> }
> -------
>
> messageReceived is actually where i get the problem : the
> command.execute(...) method locks the associated mailbox when user is
> authenticated (after a USER/PASS pair of commands or after a successfull APOP
> command) but i should also be able to unlock my ressources from the
> exceptionCaught and sessionIdle methods of the handler. So i must ensure that
> these 3 methods would always be served by the same thread (thread which was
> initially picked up from a pool) within a given session.
>
If a user logs in a second time that session should get a "-ERR Mailbox
locked" response to the PASS/APOP command, right?. I don't think you
need to use a ReentrantLock. A simple boolean flag per mailbox would do
fine (access to it must of course be properly synchronized).
This code should be executed whenever the PASS/APOP command is received
(pseudo-code):
synchronized (mailbox) {
if (mailbox.locked) {
// Another connection has the lock
session.write("-ERR Mailbox locked");
// Connection will still be in AUTHORIZATION state
} else {
// This connection acquires the lock
mailbox.locked = true;
session.write("-ERR Mailbox locked");
// Move to TRANSACTION state
}
}
The connection which gets the lock will move to the TRANSACTION state of
the POP3 protocol and will never have to check again if it has to lock,
just reset mailbox.lcoked to false when it ends (client sends QUIT,
exceptionCaught, sessionClosed, etc). All other connections which try to
authenticate as the same user will never make it beyond this state as
long as mailbox.locked is true. They will remain in the AUTHORIZATION
state of the POP3 protocol.
--
Niklas Therning
www.spamdrain.net