You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@esme.apache.org by le...@apache.org on 2012/07/04 13:12:30 UTC

svn commit: r1357226 - in /esme/branches/akka: ./ project/ project/plugins/ src/main/resources/props/ src/main/scala/ src/main/scala/org/apache/esme/api/ src/main/scala/org/apache/esme/external/ src/main/scala/org/apache/esme/lib/ src/main/scala/org/ap...

Author: lester
Date: Wed Jul  4 11:12:27 2012
New Revision: 1357226

URL: http://svn.apache.org/viewvc?rev=1357226&view=rev
Log:
Merged latest changes from Trunk.

Added:
    esme/branches/akka/project/plugins.sbt
      - copied unchanged from r1357222, esme/trunk/server/project/plugins.sbt
Removed:
    esme/branches/akka/project/plugins/
Modified:
    esme/branches/akka/   (props changed)
    esme/branches/akka/build.sbt
    esme/branches/akka/pom.xml
    esme/branches/akka/project/   (props changed)
    esme/branches/akka/project/build.properties
    esme/branches/akka/src/main/resources/props/compass.filesystem.cfg.xml   (props changed)
    esme/branches/akka/src/main/scala/JettyLauncher.scala
    esme/branches/akka/src/main/scala/org/apache/esme/api/API2.scala
    esme/branches/akka/src/main/scala/org/apache/esme/external/RssFeed.scala
    esme/branches/akka/src/main/scala/org/apache/esme/lib/TagUtils.scala
    esme/branches/akka/src/main/scala/org/apache/esme/model/UserAuth.scala
    esme/branches/akka/src/main/scala/org/apache/esme/model/UserConvFollow.scala
    esme/branches/akka/src/main/scala/org/apache/esme/model/UserTagFollow.scala

Propchange: esme/branches/akka/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Wed Jul  4 11:12:27 2012
@@ -1,3 +1,4 @@
+.history
 target
 esme_db
 esme_test_db

Propchange: esme/branches/akka/
------------------------------------------------------------------------------
  Merged /esme/trunk/server:r1186845-1357222

Modified: esme/branches/akka/build.sbt
URL: http://svn.apache.org/viewvc/esme/branches/akka/build.sbt?rev=1357226&r1=1357225&r2=1357226&view=diff
==============================================================================
--- esme/branches/akka/build.sbt (original)
+++ esme/branches/akka/build.sbt Wed Jul  4 11:12:27 2012
@@ -8,7 +8,10 @@ version := "1.4"
 
 organization := "Apache Software Foundation"
 
-scalaVersion := "2.9.1"      
+scalaVersion := "2.9.1"    
+
+//scalacOptions ++= Seq("-unchecked", "-deprecation")  
+scalacOptions ++= Seq("-deprecation") 
 
 seq(webSettings :_*)
 
@@ -21,13 +24,13 @@ ivyXML :=
 
 libraryDependencies ++= {
   val scalaVersion = "2.9.1"
-  val liftVersion = "2.4-M4"
+  val liftVersion = "2.4"
   val compassVersion = "2.1.1"
   val luceneVersion = "2.4.0"
-  val scalazVersion = "6.0.3" 
+  val scalazVersion = "6.0.4"
   val eclipsejettyVersion = "7.3.1.v20110307"    
-  val mortbayjettyVersion = "[6.1.6,)"
-  val slf4jVersion = "1.6.1" 
+  val mortbayjettyVersion = "6.1.22"
+  val slf4jVersion = "1.6.4" 
   val scalatestVersion = "1.6.9"   
   Seq(
     "net.liftweb" %% "lift-util" % liftVersion % "compile->default",
@@ -70,10 +73,10 @@ resolvers += "Compass Repository" at "ht
 
 resolvers += "Twitter Repository" at "http://maven.twttr.com"
 
-resolvers +=  "Java.net Maven2 Repository" at "http://download.java.net/maven/2/"   
+resolvers += "Java.net Maven2 Repository" at "http://download.java.net/maven/2/"   
+
+resolvers += "Maven central" at "http://repo1.maven.org/maven2/"
 
 // Execute tests in the current project serially.
 // Tests from other projects may still run concurrently.
-//parallelExecution in Test := false
-
-//scalacOptions += "-Xprint:typer"
+parallelExecution in Test := false 
\ No newline at end of file

Modified: esme/branches/akka/pom.xml
URL: http://svn.apache.org/viewvc/esme/branches/akka/pom.xml?rev=1357226&r1=1357225&r2=1357226&view=diff
==============================================================================
--- esme/branches/akka/pom.xml (original)
+++ esme/branches/akka/pom.xml Wed Jul  4 11:12:27 2012
@@ -73,13 +73,14 @@
     </developer>
     </developers>
     <properties>
-        <lift.version>2.4-M4</lift.version>
+        <lift.version>2.4</lift.version>
         <scala.version>2.9.1</scala.version>
-        <scalaz.version>6.0.3</scalaz.version>
+        <scalaz.version>6.0.4</scalaz.version>
         <compass.version>2.1.1</compass.version>
         <lucene.version>2.4.0</lucene.version>
         <netbeans.hint.deploy.server>gfv3</netbeans.hint.deploy.server>
-        <scala.stats.version>1.3</scala.stats.version>
+        <scala.stats.version>1.3</scala.stats.version>    
+        <mortbay.jetty.version>6.1.22</mortbay.jetty.version>
     </properties>
 
     <repositories>
@@ -123,7 +124,6 @@
              <id>Apache Repo</id> 
               <name>Apache repository for Derby 10.5.1.1</name> 
               <url>http://people.apache.org/repo/m1-ibiblio-rsync-repository</url> 
-              <layout>legacy</layout> 
         </repository>           
     </repositories>
 
@@ -237,13 +237,7 @@
             <groupId>org.apache.derby</groupId>
             <artifactId>derby</artifactId>
             <version>10.5.3.0_1</version>
-        </dependency>       
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <version>3.8.1</version>
-            <scope>test</scope>
-        </dependency>     
+        </dependency>          
         <dependency>
           <groupId>org.eclipse.jetty</groupId>
             <artifactId>jetty-server</artifactId>
@@ -257,7 +251,7 @@
         <dependency>
           <groupId>org.mortbay.jetty</groupId>
             <artifactId>jetty</artifactId>
-            <version>[6.1.6,)</version>
+            <version>${mortbay.jetty.version}</version>
             <scope>test</scope>
         </dependency>
         <dependency>
@@ -331,6 +325,7 @@
             <plugin>
                 <groupId>org.apache.rat</groupId>
                 <artifactId>apache-rat-plugin</artifactId>
+                <version>0.8</version>
             </plugin>
             <plugin>
                 <groupId>org.scala-tools</groupId>
@@ -354,6 +349,7 @@
             <plugin>
                 <groupId>org.mortbay.jetty</groupId>
                 <artifactId>maven-jetty-plugin</artifactId>
+                <version>${mortbay.jetty.version}</version>
                 <configuration>
                     <contextPath>/</contextPath>
                     <scanIntervalSeconds>0</scanIntervalSeconds>
@@ -361,7 +357,8 @@
             </plugin>
             <plugin>
                 <groupId>net.sf.alchim</groupId>
-                <artifactId>yuicompressor-maven-plugin</artifactId>
+                <artifactId>yuicompressor-maven-plugin</artifactId>  
+                <version>0.7.1</version>
                 <executions>
                     <execution>
                         <goals>
@@ -377,7 +374,8 @@
             </plugin>
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-eclipse-plugin</artifactId>
+                <artifactId>maven-eclipse-plugin</artifactId> 
+                <version>2.9</version>
                 <configuration>
                     <downloadSources>true</downloadSources>
                     <excludes>
@@ -415,13 +413,13 @@
                 <dependency>
                   <groupId>org.mortbay.jetty</groupId>
                     <artifactId>jetty-plus</artifactId>
-                    <version>[6.1.6,)</version>
+                    <version>${mortbay.jetty.version}</version>
                     <scope>compile</scope>
                 </dependency>
                 <dependency>
                   <groupId>org.mortbay.jetty</groupId>
                     <artifactId>jetty-ldap-jaas</artifactId>
-                    <version>[6.1.6,)</version>
+                    <version>${mortbay.jetty.version}</version>
                     <scope>compile</scope>
                 </dependency>
             </dependencies>
@@ -477,7 +475,8 @@
         <plugins>
             <plugin>
                 <groupId>org.scala-tools</groupId>
-                <artifactId>maven-scala-plugin</artifactId>
+                <artifactId>maven-scala-plugin</artifactId> 
+                <version>2.14.1</version>
                 <configuration>
                     <jvmArgs>
                         <jvmArg>-Xmx1024m</jvmArg>

Propchange: esme/branches/akka/project/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Wed Jul  4 11:12:27 2012
@@ -1 +1,3 @@
 boot
+project
+target

Modified: esme/branches/akka/project/build.properties
URL: http://svn.apache.org/viewvc/esme/branches/akka/project/build.properties?rev=1357226&r1=1357225&r2=1357226&view=diff
==============================================================================
--- esme/branches/akka/project/build.properties (original)
+++ esme/branches/akka/project/build.properties Wed Jul  4 11:12:27 2012
@@ -1 +1 @@
-sbt.version=0.11.0
\ No newline at end of file
+sbt.version=0.11.2
\ No newline at end of file

Propchange: esme/branches/akka/src/main/resources/props/compass.filesystem.cfg.xml
------------------------------------------------------------------------------
  Merged /esme/trunk/server/src/main/resources/props/compass.filesystem.cfg.xml:r1186845-1357222

Modified: esme/branches/akka/src/main/scala/JettyLauncher.scala
URL: http://svn.apache.org/viewvc/esme/branches/akka/src/main/scala/JettyLauncher.scala?rev=1357226&r1=1357225&r2=1357226&view=diff
==============================================================================
--- esme/branches/akka/src/main/scala/JettyLauncher.scala (original)
+++ esme/branches/akka/src/main/scala/JettyLauncher.scala Wed Jul  4 11:12:27 2012
@@ -22,7 +22,7 @@
  import org.eclipse.jetty.server.nio.SelectChannelConnector
  import net.liftweb.http.LiftFilter
 
- object JettyLauncher extends Application {
+ object JettyLauncher extends App {
    val port = if(System.getenv("PORT") != null) System.getenv("PORT").toInt else 8080
    val server = new Server
    val scc = new SelectChannelConnector

Modified: esme/branches/akka/src/main/scala/org/apache/esme/api/API2.scala
URL: http://svn.apache.org/viewvc/esme/branches/akka/src/main/scala/org/apache/esme/api/API2.scala?rev=1357226&r1=1357225&r2=1357226&view=diff
==============================================================================
--- esme/branches/akka/src/main/scala/org/apache/esme/api/API2.scala (original)
+++ esme/branches/akka/src/main/scala/org/apache/esme/api/API2.scala Wed Jul  4 11:12:27 2012
@@ -250,7 +250,7 @@ object API2 extends ApiHelper with XmlHe
       } yield {
         val token: AuthToken = AuthToken.create
           .user(user)
-          .description(S.param("description"))
+          .description(S.param("description").openOr(""))
           .saveMe
         (200,Map(),Full(tokenToXml(token)))
       }
@@ -351,7 +351,7 @@ object API2 extends ApiHelper with XmlHe
                                        millis,
                                        xml match {
                                          case Full(x) => xml
-                                         case _ => Box({new Atom(S.param("metadata") openOr "")})
+                                         case _ => Full(new Atom(S.param("metadata").openOr("")))
                                        },
                                        from,
                                        S.param("replyto").map(toLong),

Modified: esme/branches/akka/src/main/scala/org/apache/esme/external/RssFeed.scala
URL: http://svn.apache.org/viewvc/esme/branches/akka/src/main/scala/org/apache/esme/external/RssFeed.scala?rev=1357226&r1=1357225&r2=1357226&view=diff
==============================================================================
--- esme/branches/akka/src/main/scala/org/apache/esme/external/RssFeed.scala (original)
+++ esme/branches/akka/src/main/scala/org/apache/esme/external/RssFeed.scala Wed Jul  4 11:12:27 2012
@@ -26,7 +26,7 @@ import org.apache.esme.model.User
 import org.apache.esme.model.Message
 import org.apache.esme.actor.Distributor.{UserCreatedMessage=>Msg}
 
-import net.liftweb.common.Empty
+import net.liftweb.common.{Empty,Full,Box}
 
 object RssFeed {
   val dateFormats = List(new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", US))
@@ -86,17 +86,16 @@ class RssFeed(user: User, rssURL: String
   */
 
   override def getLastSortedMessages(msgs: List[Msg], lastMessage: Option[Msg]): List[Msg] = {
-    import net.liftweb.common.Box
     lastMessage match {
       case Some(message: Msg) =>
         // a hack to format text identically- difference in urls & trailing whitespace
         val lastMessageText =
           Message.create.setTextAndTags(message.text, Nil, Empty).
-            choice((m: Message) => Box(m.body.trim))(Box("")).get
+            choice((m: Message) => Full(m.body.trim))(Full("")).get
             //get.body.trim
         msgs.takeWhile{ msg =>
           Message.create.setTextAndTags(msg.text, Nil, Empty).
-            choice((m: Message) => Box(m.body.trim))(Box("")).get != lastMessageText
+            choice((m: Message) => Full(m.body.trim))(Full("")).get != lastMessageText
             //get.body.trim != lastMessageText
         }
       case None => msgs

Modified: esme/branches/akka/src/main/scala/org/apache/esme/lib/TagUtils.scala
URL: http://svn.apache.org/viewvc/esme/branches/akka/src/main/scala/org/apache/esme/lib/TagUtils.scala?rev=1357226&r1=1357225&r2=1357226&view=diff
==============================================================================
--- esme/branches/akka/src/main/scala/org/apache/esme/lib/TagUtils.scala (original)
+++ esme/branches/akka/src/main/scala/org/apache/esme/lib/TagUtils.scala Wed Jul  4 11:12:27 2012
@@ -19,6 +19,9 @@
 
 package org.apache.esme.lib
 
+import scalaz._
+import Scalaz._
+
 object TagUtils {
 
   // Normalize the frequencies from arbitrary Integers to the range (0.0 - 1.0)
@@ -29,10 +32,8 @@ object TagUtils {
   }
   
   // Compounds a bunch of (String, Int) elements so that [(String1, Int1), (String1, Int2)] becomes [(String1, Int1+Int2)]
-  def compound(llsi: List[(String,Int)]): List[(String,Int)] =
-    llsi.foldLeft[Map[String, Int]](Map.empty) {
-      case (map, (str, cnt)) => map + (str -> (map.getOrElse(str, 0) + cnt))
-    }.toList
+  // foldMap with List as Foldable and append operation of Map Monoid
+  def compound(llsi: List[(String,Int)]): List[(String,Int)] = llsi.foldMap(Map(_)).toList
 
   
   def everyEven(x:List[(String, Int)]):List[(String, Int)] = everyOther(x)

Modified: esme/branches/akka/src/main/scala/org/apache/esme/model/UserAuth.scala
URL: http://svn.apache.org/viewvc/esme/branches/akka/src/main/scala/org/apache/esme/model/UserAuth.scala?rev=1357226&r1=1357225&r2=1357226&view=diff
==============================================================================
--- esme/branches/akka/src/main/scala/org/apache/esme/model/UserAuth.scala (original)
+++ esme/branches/akka/src/main/scala/org/apache/esme/model/UserAuth.scala Wed Jul  4 11:12:27 2012
@@ -49,8 +49,10 @@ import provider.servlet.HTTPRequestServl
 
 import scala.xml._
 
-import scalaz.{OptionW, Scalaz}
+import scalaz.{OptionW, Identity, IterV, Input, State, Scalaz}
+import scalaz.effects.{IO}
 import Scalaz._
+import IterV.{Empty => EmptyZ, Done => DoneZ, _}
 
 import org.apache.esme.actor._
 
@@ -126,7 +128,7 @@ trait FieldSet {
 object UserPwdAuthModule extends AuthModule {
   def loginPresentation: Box[NodeSeq] = {
     val ldapBind : CssBindFunc = "#ldapEnabled [value]" #> (Props.getBool("ldap.enabled") openOr false)
-    TemplateFinder.findAnyTemplate("templates-hidden" :: "upw_login_form" :: Nil) match {
+    Templates("templates-hidden" :: "upw_login_form" :: Nil) match {
       case Full(tpl) => Full(ldapBind(tpl))
       case _ => Empty
     }
@@ -175,7 +177,7 @@ object UserPwdAuthModule extends AuthMod
     private var email = ""
 
     def toForm: NodeSeq =
-    TemplateFinder.findAnyTemplate("templates-hidden" :: "upw_signup_form" :: Nil).map(
+    Templates("templates-hidden" :: "upw_signup_form" :: Nil).map(
       xhtml =>
       bind("signup", xhtml,
            "email" -%> SHtml.text(email, s => email = s.trim.toLowerCase),
@@ -216,8 +218,7 @@ object UserPwdAuthModule extends AuthMod
 }
 
 object OpenIDAuthModule extends AuthModule {
-  def loginPresentation: Box[NodeSeq] =
-  TemplateFinder.findAnyTemplate("templates-hidden" :: "openid_login_form" :: Nil)
+  def loginPresentation: Box[NodeSeq] = Templates("templates-hidden" :: "openid_login_form" :: Nil)
 
   def moduleName: String = "openid"
 
@@ -326,12 +327,13 @@ trait LDAPBase {
     myLdapVendor
   }
 
+  @deprecated("Use getAttributesMap.","01-01-2012")
   def getAttrs(dn : String) : Map[String, List[String]] = {
     var attrsMap = Map.empty[String, List[String]]
-    val attrs : Attributes = myLdap.attributesFromDn(dn)
-    if (attrs != null) {
-      val allAttrs = attrs.getAll();
-      if (allAttrs != null) {
+    val attributes = getLDAPAttributes(dn)
+    attributes.foreach(attrs => {
+      val allAttributes = Option(attrs.getAll());
+      allAttributes.foreach(allAttrs => {
         while(allAttrs.hasMore()) {
           val attribute = allAttrs.next().asInstanceOf[Attr];
           debug("Attribute name: '%s', has following values:".format(attribute.getID()))
@@ -342,9 +344,69 @@ trait LDAPBase {
           }
           attrsMap += (attribute.getID() -> attrValues)
         }
+      })
+    })
+    attrsMap
+  }
+
+  def getLDAPAttributes(dn: String): Option[Attributes] = {
+    //TODO: it's probably better to return Either or Validation
+    try {
+      // Ugly, but following operation
+      // throws NamingException in case
+      // given DN doesn't exist in LDAP
+      Option(myLdap.attributesFromDn(dn))
+    } catch {
+      case ne: javax.naming.NamingException => {
+        info("Naming Exception was thrown: %s".format(ne))
+        none
       }
     }
-    attrsMap
+  }
+
+  // Scalaz Iteratee was used
+  // returns pairs name->list of values
+  def getAttributesMap(dn: String) : Option[Map[String, List[String]]] = {
+    val attributes = getLDAPAttributes(dn)
+    attributes.flatMap(attrs => {
+      val allAttributes = Option(attrs.getAll());
+      allAttributes.map(allAttrs  => {
+        val res = enumNamingEnumeration(allAttrs, accum, get) map (_.run)
+        res.unsafePerformIO ~> Map.empty[String, List[String]]
+      })
+    })
+  }
+
+
+  def enumNamingEnumeration[E, A, T <: Attr](ne: NamingEnumeration[T], iter: IterV[E, A], constr: NamingEnumeration[T] => IO[E]): IO[IterV[E, A]] = {
+    def loop(i: IterV[E, A]): IO[IterV[E, A]] =
+      i.fold(done = (_, _) => i.pure[IO],
+        cont = k => next(ne) >>= (hasMore =>
+          if (!hasMore) i.pure[IO]
+          else constr(ne) >>= (t => loop(k(El(t))))))
+    loop(iter)
+  }
+
+  def next: NamingEnumeration[_ <: Attr] => IO[Boolean] = _.hasMore().pure[IO]
+
+  def get: NamingEnumeration[_ <: Attr] => IO[(String, List[String])] = ne => {
+    val attribute = ne.next().asInstanceOf[Attr];
+    debug("Attribute name: '%s', has following values:".format(attribute.getID()))
+    var attrValues = List.empty[String]
+    for(i <- 0 until attribute.size()) {
+      debug("Attribute value: '%s'".format(attribute.get(i)))
+      attrValues ::= attribute.get(i).toString
+    }
+    (attribute.getID() -> attrValues).pure[IO]
+  }
+
+  def accum: IterV[(String, List[String]), State[Map[String, List[String]], Unit]] = {
+    def step(s: State[Map[String, List[String]], Unit]): Input[(String, List[String])] => IterV[(String, List[String]), State[Map[String, List[String]], Unit]] = {
+      case El(x1, x2) => Cont(step(s.withs((_: Map[String, List[String]]) + (x1 -> x2))))
+      case EmptyZ() => Cont(step(s))
+      case EOF() => DoneZ(s, EOF[(String, List[String])])
+    }
+    Cont(step(state[Map[String, List[String]], Unit](s => (s, ()))))
   }
 
   def constructDistinguishedName(who : String, isGroup : Boolean = false) = {
@@ -391,52 +453,55 @@ object ContainerManagedAuthModule extend
             val httpRequest: HTTPRequest = req.request
             val hrs = httpRequest.asInstanceOf[HTTPRequestServlet]
             val hsr: HttpServletRequest = hrs.req
-            val username : String = hsr.getRemoteUser
+            val username = Option(hsr.getRemoteUser)
             debug("Username: '%s'".format(username))
-            if(username!=null){
-              val currentRoles = rolesToCheck.filter(hsr.isUserInRole(_))
-              debug("User from HTTP Request: %s has following roles=%s".format(username, currentRoles))
-              if(currentRoles.size == 0) {
-                debug("No roles have been found")
-                S.error(S.?("base_user_err_unknown_creds"))
-              } else {
-                currentRoles.map(cr => {
-                currentRole = cr
-                (for {
-                    user <- UserAuth.find(By(UserAuth.authKey, username),
-                                          By(UserAuth.authType, moduleName)).flatMap(_.user.obj) or
-                    User.find(By(User.nickname, username))
-                  } yield user) match {
-                    case Full(user) => {
-                      debug("User: '%s' has been found".format(user.niceName))
-                      logInUser(user)
-                    }
-                    case _ => {
-                      val usr = User.createAndPopulate.nickname(username).saveMe
-                      //find and save additional attributes in LDAP if it's enabled
-                      val ldapEnabled = Props.getBool("ldap.enabled") openOr false
-                      if(ldapEnabled) {
-                        val ldapAttrs = getAttrs(constructDistinguishedName(username))
-                        val firstName = ldapAttrs("givenName").head
-                        val lastName = ldapAttrs("sn").head
-                        val mail = ldapAttrs("mail").head
-                        debug("Attributes from LDAP for user '%s'. Firstname: '%s', lastname: '%s', email: '%s'".format(username, firstName, lastName, mail))
-                        usr.firstName(firstName).lastName(lastName).save
+            username.cata(uName => {
+              rolesToCheck.filter(hsr.isUserInRole(_)) match {
+                case Nil => {
+                  debug("No roles have been found")
+                  S.error(S.?("base_user_err_unknown_creds"))
+                }
+                case xs => {
+                  debug("User from HTTP Request: %s has following roles=%s".format(uName, xs))
+                  xs.map(cr => {
+                    currentRole = cr
+                    (for {
+                      user <- UserAuth.find(By(UserAuth.authKey, uName),
+                        By(UserAuth.authType, moduleName)).flatMap(_.user.obj) or
+                        User.find(By(User.nickname, uName))
+                    } yield user) match {
+                      case Full(user) => {
+                        debug("User: '%s' has been found".format(user.niceName))
+                        logInUser(user)
+                      }
+                      case _ => {
+                        val usr = User.createAndPopulate.nickname(uName).saveMe
+                        //find and save additional attributes in LDAP if it's enabled
+                        val ldapEnabled = Props.getBool("ldap.enabled") openOr false
+                        if(ldapEnabled) {
+                          getAttributesMap(constructDistinguishedName(uName)).map(ldapAttrs => {
+                            ldapAttrs.get("givenName").flatMap(_.headOption.map(usr.firstName(_)))
+                            ldapAttrs.get("sn").flatMap(_.headOption.map(usr.lastName(_)))
+                            //TODO: There's no corresponding property in User's Mapper
+                            //ldapAttrs.get("mail").flatMap(_.headOption.map(usr))
+                            debug("Attributes from LDAP for user '%s'. Firstname: '%s', lastname: '%s'".format(uName, usr.firstName, usr.lastName))
+                            usr.save
+                          })
+                        }
+                        UserAuth.create.authType(moduleName).user(usr).authKey(uName).save
+                        logInUser(usr)
                       }
-                      UserAuth.create.authType(moduleName).user(usr).authKey(username).save
-                      logInUser(usr)
                     }
-                  }
-                })
+                  })
+                }
               }
-            } else {
-              S.error(S.?("base_user_err_unknown_creds"))
-            }
-
+            },
+            S.error(S.?("base_user_err_unknown_creds")))
           }
           case Empty => {
             S.error(S.?("base_user_err_unknown_creds"))
-          }
+          }         
+          case _ => {}  
         }
 
         S.redirectTo(from)
@@ -455,7 +520,7 @@ object LDAPAuthModule extends AuthModule
 
   override def isDefault = false
 
-  def loginPresentation: Box[NodeSeq] = TemplateFinder.findAnyTemplate("templates-hidden" :: "ldap_login_form" :: Nil)
+  def loginPresentation: Box[NodeSeq] = Templates("templates-hidden" :: "ldap_login_form" :: Nil)
 
   def moduleName: String = "ldap"
 
@@ -468,7 +533,7 @@ object LDAPAuthModule extends AuthModule
       if(ldapEnabled) {
         val name = S.param("username").map(_.trim.toLowerCase) openOr ""
         val pwd = S.param("password").map(_.trim) openOr ""
-        if(myLdap.bindUser(constructNameWithPrefix(name), pwd) && checkRoles(constructDistinguishedName(name))) {
+        if(myLdap.bindUser(constructNameWithPrefix(name), pwd) && !checkRoles(constructDistinguishedName(name)).isEmpty) {
           (for {
               user <- UserAuth.find(By(UserAuth.authKey, name),
                                     By(UserAuth.authType, moduleName)).flatMap(_.user.obj) or
@@ -480,14 +545,17 @@ object LDAPAuthModule extends AuthModule
             case Empty =>
               val usr = User.createAndPopulate.nickname(name).saveMe
               //find and save additional attributes in LDAP if it's enabled
-              val ldapAttrs = getAttrs(constructDistinguishedName(name))
-              val firstName = ldapAttrs("givenName").head
-              val lastName = ldapAttrs("sn").head
-              val mail = ldapAttrs("mail").head
-              debug("Attributes from LDAP for user '%s'. Firstname: '%s', lastname: '%s', email: '%s'".format(name, firstName, lastName, mail))
-              usr.firstName(firstName).lastName(lastName).save
+              getAttributesMap(constructDistinguishedName(name)).map(ldapAttrs => {
+                ldapAttrs.get("givenName").flatMap(_.headOption.map(usr.firstName(_)))
+                ldapAttrs.get("sn").flatMap(_.headOption.map(usr.lastName(_)))
+                //TODO: There's no corresponding property in User's Mapper
+                //ldapAttrs.get("mail").flatMap(_.headOption.map(usr))
+                debug("Attributes from LDAP for user '%s'. Firstname: '%s', lastname: '%s'".format(name, usr.firstName, usr.lastName))
+                usr.save   
+              })
               UserAuth.create.authType(moduleName).user(usr).authKey(name).save
               logInUser(usr)
+            case _ => {}
           }
         } else {
           S.error(S.?("base_user_err_unknown_creds"))
@@ -498,18 +566,23 @@ object LDAPAuthModule extends AuthModule
     }
   }
 
-  def checkRoles(who : String) : Boolean = {
-    for (role <-rolesToCheck) {
-      val ldapAttrs = getAttrs(constructDistinguishedName(role, true))
-      val uniqueMember = ldapAttrs("uniqueMember").head
-      debug("'uniqueMember' attribute value: '%s'".format(uniqueMember))
-      if(who == uniqueMember) {
-        currentRole = role
-        return true
-      }
+  def checkRoles(who : String) : Option[String] = {
+    var matchedRoles: List[Option[String]] = Nil
+    for (role <- rolesToCheck) {
+        matchedRoles ::= getAttributesMap(constructDistinguishedName(role, true)).flatMap(ldapAttrs => {
+          ldapAttrs.get("uniqueMember").flatMap(_.headOption.flatMap(uniqueMember => {
+            if(who ≟ uniqueMember) {
+              currentRole = role
+              some(role)
+            } else {
+              none
+            }
+          }))
+      })
     }
-    debug("No roles have been found")
-    return false;
+    // At the moment only one (first matched) role is taken into account
+    // therefore First Option Monoid was used
+    matchedRoles.map(_.fst).asMA.sum.value
   }
 
   def createHolder(): FieldSet = new FieldSet {

Modified: esme/branches/akka/src/main/scala/org/apache/esme/model/UserConvFollow.scala
URL: http://svn.apache.org/viewvc/esme/branches/akka/src/main/scala/org/apache/esme/model/UserConvFollow.scala?rev=1357226&r1=1357225&r2=1357226&view=diff
==============================================================================
--- esme/branches/akka/src/main/scala/org/apache/esme/model/UserConvFollow.scala (original)
+++ esme/branches/akka/src/main/scala/org/apache/esme/model/UserConvFollow.scala Wed Jul  4 11:12:27 2012
@@ -27,6 +27,6 @@ object UserConvFollow extends UserConvFo
 class UserConvFollow extends LongKeyedMapper[UserConvFollow] with IdPK {  
   def getSingleton = UserConvFollow
 
-  object user extends LongMappedMapper(this, User)
-  object conversation extends LongMappedMapper(this, Message)
+  object user extends MappedLongForeignKey(this, User)
+  object conversation extends MappedLongForeignKey(this, Message)
 }
\ No newline at end of file

Modified: esme/branches/akka/src/main/scala/org/apache/esme/model/UserTagFollow.scala
URL: http://svn.apache.org/viewvc/esme/branches/akka/src/main/scala/org/apache/esme/model/UserTagFollow.scala?rev=1357226&r1=1357225&r2=1357226&view=diff
==============================================================================
--- esme/branches/akka/src/main/scala/org/apache/esme/model/UserTagFollow.scala (original)
+++ esme/branches/akka/src/main/scala/org/apache/esme/model/UserTagFollow.scala Wed Jul  4 11:12:27 2012
@@ -27,6 +27,6 @@ object UserTagFollow extends UserTagFoll
 class UserTagFollow extends LongKeyedMapper[UserTagFollow] with IdPK {  
   def getSingleton = UserTagFollow
 
-  object user extends LongMappedMapper(this, User)
-  object tag extends LongMappedMapper(this, Tag)
+  object user extends MappedLongForeignKey(this, User)
+  object tag extends MappedLongForeignKey(this, Tag)
 }
\ No newline at end of file