Hi Tim,

Excellent remarks. 

I have made the following changes to Guard in SVN 1.0 branch:
 - secrets is now a ConcurrentHashMap instance
 - getSecrets() lazily instantiates the secrets field in a synchronized
block:

    public Map<String, char[]> getSecrets() {
                if (this.secrets == null) {
                        synchronized (this) {
                                if (this.secrets == null) {
                                        this.secrets = new
ConcurrentHashMap<String, char[]>();
                                }
                        }
                }

                return this.secrets;
    }

In addition, the getSecrets() method in SVN trunk (future 1.1) returns a
ConcurrentMap instance instead of just Map. Also the "scheme" and "realm"
properties have setters in 1.1, so no reason to mark them final.

Best regards,
Jerome  

> -----Message d'origine-----
> De : [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] De la 
> part de Tim Peierls
> Envoyé : jeudi 4 octobre 2007 07:16
> À : [email protected]
> Objet : Thread-safety in Guard
> 
> There is a serious thread-safety problem in org.restlet.Guard 
> (Restlet 1.0.5). The secrets field is lazily initialized 
> without proper synchronization and the TreeMap used to 
> initialize it is not thread-safe 
> <http://java.sun.com/javase/6/docs/api/java/util/TreeMap.html>
>  . The simplest fix would be to use an eagerly-initialized 
> ConcurrentHashMap. 
> 
> In addition, the scheme and realm fields should be marked 
> final. They should probably be protected, too, instead of private.
> 
> If you want a thread-safe version of Guard without having to 
> wait for a fix, you could use something like this:
> 
> public class SafeGuard extends Guard { 
> 
>     ...
> 
>     @Override public ConcurrentMap<String, char[]> getSecrets() {
>         return secrets;
>     }
> 
>     private final ConcurrentMap<String, char[]> secrets =
>         new ConcurrentHashMap<String, char[]>();
> }
> 
> Using a covariant return type of ConcurrentMap allows callers 
> to use methods like putIfAbsent, which might be useful in an 
> environment where the logins and secrets are very dynamic. 
> 
> --tim
> 
> 

Reply via email to