You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by ov...@apache.org on 2002/09/06 02:02:16 UTC

cvs commit: xml-cocoon2/src/webapp/samples/flow/examples/prefs/pages login.xsp registrationSuccessful.xsp userInfo.xsp welcome.xsp

ovidiu      2002/09/05 17:02:16

  Added:       src/webapp/samples/flow/examples/prefs prefs.js sitemap.xmap
               src/webapp/samples/flow/examples/prefs/logic User.java
                        UserRegistry.java
               src/webapp/samples/flow/examples/prefs/pages login.xsp
                        registrationSuccessful.xsp userInfo.xsp welcome.xsp
  Log:
  Simple example of how to handle user login and preferences using the control flow layer.
  
  Revision  Changes    Path
  1.1                  xml-cocoon2/src/webapp/samples/flow/examples/prefs/prefs.js
  
  Index: prefs.js
  ===================================================================
  /*
      prefs.js
  
      This file is the central controller piece in the preferences
      application. It receives the requests from the client browser (the
      View in the MVC pattern), and coordinates with the Model (written
      in Java, in the logic/ directory) to do the business logic.
  
      Author: Ovidiu Predescu <ov...@apache.org>
      Date: August 30, 2002
  
   */
  
  // The global user registry, through which we add new users or access
  // existing ones.
  var userRegistry = Packages.samples.flow.prefs.logic.UserRegistry.getUserRegistry();
  
  var user = null;
  
  // This top-level function is called from the sitemap to start the
  // process of registering a user.
  // 
  // This function takes care of all the steps required during the
  // registration of a new user. It is the controller is the MVC
  // pattern, an intermediary between the View, in our case the client's
  // browser, and the Model, in the case of this particular function the
  // code that maintains the registered users.
  //
  // The function collects the necessary information from the View, and
  // calls the Model to do the necessary work of checking whether the
  // user exists or not, and registering the new user.
  function registerUser()
  {
    var check = false;
    var errorMsg = null;
    
    var login = "";
    var password = "";
    var firstName = "";
    var lastName = "";
    var email = "";
  
    while (true) {
      // Present the user with addUser page. `check' indicates the XSP
      // template that it needs to check the registration parameters,
      // and print an indicator close to where the errors
      // are. `errorMsg' if not null is printed at the top of the page
      // as an error message.
      print ("calling registerUser");
      sendPage("userInfo.html",
               { "check" : check, "errorMsg" : errorMsg,
                   "title": "New User Registration",
                   "button" : "Register",
                   "login" : login, "password" : password,
                   "firstName" : firstName, "lastName" : lastName,
                   "email" : email});
  
      check = false;
      errorMsg = null;
  
      login = cocoon.request.get("login");
      password = cocoon.request.get("password");
      firstName = cocoon.request.get("firstName");
      lastName = cocoon.request.get("lastName");
      email = cocoon.request.get("email");
  
      if (login == "" || password == ""
          || firstName == "" || lastName == ""
          || email == "") {
        check = true;
        errorMsg = "Please correct the marked errors before continuing";
        continue;
      }
  
      // Check for the existence of an already registered user with the
      // same login name. There is a possibility of a race condition
      // here, with another user registering with the same login id
      // between this check and the creation of a new user few lines
      // below. We ignore this problem in this example.
      var existingUser = userRegistry.isLoginNameTaken(login);
      if (!existingUser) {
        user = new Packages.samples.flow.prefs.logic.User(login, password,
                                                          firstName, lastName,
                                                          email);
        userRegistry.addUser(user);
        break;
      }
      else {
        // TODO: I18N
        errorMsg = "Login name '" + login
          + "' is already in use, please choose another name";
      }
    }
  
    // The user has successfully registered, so we consider (s)he to be
    // already logged in. At this point we want to create a session, so
    // that all the JavaScript global variables are shared among
    // invocations of top-level functions. Up until this point, each
    // invocation had a separate global scope for the variables.
    cocoon.createSession();
  
    // Here we just send a response to the client browser and we don't
    // wait for any response. This is the last page generated by this
    // top-level function. In general is good to make sure a top-level
    // function, e.g. one that's invoked directly from the sitemap using
    // <map:call function="..."> sends a response page to the client at
    // all the exit points. Otherwise the user will get a blank page and
    // will be really confused.
    //
    // In the case of this particular function, this is the only exit
    // point.
    sendPageAndContinue("registrationSuccessful.html",
                        {"firstName" : firstName, "lastName" : lastName});
  }
  
  
  // This top-level function is used for user login.
  function login(errorMsg)
  {
    var login = "";
    var password = "";
  
    print("login function called");
    
    while (true) {
      sendPage("login.html",
               {"errorMsg" : errorMsg, "login" : login, "password" : password});
  
      errorMsg = null;
    
      login = cocoon.request.getParameter("login");
      password = cocoon.request.getParameter("password");
  
      print ("got login = " + login + ", passwd = " + password);
      user = userRegistry.getUserWithLogin(login, password);
      print ("got user = " + user);
      
      if (user != null)
        break;
      else {
        // TODO: I18N
        errorMsg = "No such user or bad password";
      }
    }
  
    print ("login successful as user " + user + " using password " + password);
  
    // The user has successfully signed in. At this point we want to
    // create a session, so that all the JavaScript global variables are
    // shared among invocations of top-level functions. Up until this
    // point, each invocation had a separate global scope for the
    // variables.
    cocoon.createSession();
  
    // We send to the user a welcome page which contains links back to
    // what (s)he can do. These links essentially point to other top
    // level functions in this script.
    sendPageAndContinue("welcome.html",
                        {"firstName" : user.firstName, "lastName" : user.lastName});
  }
  
  // This function is called to edit the preferences of an already
  // registered user. If this function was called without the user being
  // logged in first, the 'user' global variable is null. When this
  // happens the user is redirected to the login page first.
  function edit()
  {
    if (user == null)
      login("Please login before continuing");
  
    var login = user.login;
    var password = user.password;
    var firstName = user.firstName;
    var lastName = user.lastName;
    var email = user.email;
    var errorMsg = "";
    var check = false;
  
    while (true) {
      // Present the user with addUser page. `check' indicates the XSP
      // template that it needs to check the registration parameters,
      // and print an indicator close to where the errors
      // are. `errorMsg' if not null is printed at the top of the page
      // as an error message.
      print ("presenting user info");
      sendPage("userInfo.html",
               { "check" : check, "errorMsg" : errorMsg,
                   "title": "Edit account",
                   "button" : "Change", "cancel" : true,
                   "login" : login, "password" : password,
                   "firstName" : firstName, "lastName" : lastName,
                   "email" : email});
  
      if (cocoon.request.get("cancel"))
        break;
  
      check = false;
      errorMsg = null;
  
      login = cocoon.request.get("login");
      password = cocoon.request.get("password");
      firstName = cocoon.request.get("firstName");
      lastName = cocoon.request.get("lastName");
      email = cocoon.request.get("email");
  
      if (login == "" || password == ""
          || firstName == "" || lastName == ""
          || email == "") {
        check = true;
        errorMsg = "Please correct the marked errors before continuing";
        continue;
      }
      else {
        // Save the changes the user made in the User object
        user.login = login;
        user.password = password;
        user.firstName = firstName;
        user.lastName = lastName;
        user.email = email;
        break;
      }
    }
  
    sendPageAndContinue("welcome.html",
                        {"firstName" : user.firstName, "lastName" : user.lastName});
  }
  
  function logout()
  {
    user = null;
    login("You're successfully logged out. Please log in to continue");
  }
  
  
  
  1.1                  xml-cocoon2/src/webapp/samples/flow/examples/prefs/sitemap.xmap
  
  Index: sitemap.xmap
  ===================================================================
  <?xml version="1.0"?>
  
  <map:sitemap xmlns:map="http://apache.org/cocoon/sitemap/1.0">
  
    <map:components>
      <map:generators default="file"/>
      <map:transformers default="xslt"/>
      <map:readers default="resource"/>
      <map:serializers default="html"/>
      <map:matchers default="wildcard"/>
      <map:flow-interpreters default="JavaScript"/>
    </map:components>
  
    <map:resources>
      <map:resource name="flow">
        <map:script src="prefs.js"/>
      </map:resource>
    </map:resources>
  
    <map:pipelines>
  
      <map:pipeline>
        <map:match pattern="kont/*">
          <map:continue with="{1}"/>
        </map:match>
  
        <map:match pattern="">
          <map:redirect-to uri="login/"/>
        </map:match>
  
        <map:match pattern="login/">
          <map:call function="login"/>
        </map:match>
  
        <map:match pattern="register/">
          <map:call function="registerUser"/>
        </map:match>
  
        <map:match pattern="edit/">
          <map:call function="edit"/>
        </map:match>
  
        <map:match pattern="logout/">
          <map:call function="logout"/>
        </map:match>
  
      </map:pipeline>
  
    </map:pipelines>
  
  </map:sitemap>
  
  
  
  1.1                  xml-cocoon2/src/webapp/samples/flow/examples/prefs/logic/User.java
  
  Index: User.java
  ===================================================================
  /*
      User.java
  
      Representation of a user.
  
      Author: Ovidiu Predescu <ov...@apache.org>
      Date: August 28, 2002
  
   */
  
  package samples.flow.prefs.logic;
  
  public class User
  {
    String login;
    String password;
    String firstName;
    String lastName;
    String email;
  
    public User(String login, String password,
                String firstName, String lastName, String email)
    {
      this.login = login;
      this.password = password;
      this.firstName = firstName;
      this.lastName = lastName;
      this.email = email;
    }
  
    public int hashCode()
    {
      return login.hashCode();
    }
  
    public boolean equals(Object obj)
    {
      User anotherUser = (User)obj;
      return anotherUser.login.equals(login);
    }
    
    /**
     * Sets the value of login
     *
     * @param argLogin Value to assign to this.login
     */
    public void setLogin(String argLogin)
    {
      this.login = argLogin;
    }
    /**
     * Gets the value of login
     *
     * @return the value of login
     */
    public String getLogin() 
    {
      return this.login;
    }
  
    /**
     * Gets the value of password
     *
     * @return the value of password
     */
    public String getPassword() 
    {
      return this.password;
    }
  
    /**
     * Sets the value of password
     *
     * @param argPassword Value to assign to this.password
     */
    public void setPassword(String argPassword)
    {
      this.password = argPassword;
    }
  
    /**
     * Gets the value of firstName
     *
     * @return the value of firstName
     */
    public String getFirstName() 
    {
      return this.firstName;
    }
  
    /**
     * Sets the value of firstName
     *
     * @param argFirstName Value to assign to this.firstName
     */
    public void setFirstName(String argFirstName)
    {
      this.firstName = argFirstName;
    }
  
    /**
     * Gets the value of lastName
     *
     * @return the value of lastName
     */
    public String getLastName() 
    {
      return this.lastName;
    }
  
    /**
     * Sets the value of lastName
     *
     * @param argLastName Value to assign to this.lastName
     */
    public void setLastName(String argLastName)
    {
      this.lastName = argLastName;
    }
  
    /**
     * Gets the value of email
     *
     * @return the value of email
     */
    public String getEmail() 
    {
      return this.email;
    }
  
    /**
     * Sets the value of email
     *
     * @param argEmail Value to assign to this.email
     */
    public void setEmail(String argEmail)
    {
      this.email = argEmail;
    }
  }
  
  
  
  1.1                  xml-cocoon2/src/webapp/samples/flow/examples/prefs/logic/UserRegistry.java
  
  Index: UserRegistry.java
  ===================================================================
  /*
      UserRegistry.java
  
      Maintains a list of registered users.
  
      Author: Ovidiu Predescu <ov...@apache.org>
      Date: August 28, 2002
  
   */
  
  package samples.flow.prefs.logic;
  
  import java.util.HashMap;
  import java.util.Map;
  
  /**
   * Maintains a list of registered users. This is a very simple class,
   * there is no persistence of the users, but such thing should be easy
   * to add.
   *
   * @author <a href="mailto:ovidiu@apache.org">Ovidiu Predescu</a>
   * @since August 28, 2002
   */
  public class UserRegistry
  {
    static UserRegistry userRegistry = new UserRegistry();
  
    Map registeredUsers = new HashMap();
  
    public static UserRegistry getUserRegistry()
    {
      System.out.println("UserRegistry: obtaining user registry = "
                         + userRegistry);
      
      return userRegistry;
    }
  
    protected UserRegistry()
    {
    }
  
    public synchronized boolean addUser(User user)
    {
      if (registeredUsers.containsKey(user.getLogin()))
        return false;
  
      registeredUsers.put(user.getLogin(), user);
      return true;
    }
  
    public boolean removeUser(User user)
    {
      return registeredUsers.remove(user) != null;
    }
  
    /**
     * Checks is a particular login name is taken or not.
     *
     * @param loginName a <code>String</code> value
     * @return true if <code>loginName</code> is taken, false otherwise
     */
    public boolean isLoginNameTaken(String loginName)
    {
      return registeredUsers.get(loginName) != null;
    }
  
    /**
     * Returns the {@link User} object which represents an user. Note that
     * we require a password to be present, to avoid presenting private
     * information to anyone.
     *
     * @param loginName a <code>String</code> value
     * @param password a <code>String</code> value
     * @return an <code>User</code> value
     */
    public User getUserWithLogin(String loginName, String password)
    {
      User user = (User)registeredUsers.get(loginName);
  
      if (user == null)
        return null;
  
      return password.equals(user.getPassword()) ? user : null;
    }
  }
  
  
  
  1.1                  xml-cocoon2/src/webapp/samples/flow/examples/prefs/pages/login.xsp
  
  Index: login.xsp
  ===================================================================
  <?xml version="1.0"?>
  
  <!--
    Author: Ovidiu Predescu "ovidiu@apache.org"
  
    Date: August 30, 2002
   -->
  
  <xsp:page
    language="java"
    xmlns:xsp="http://apache.org/xsp"
    xmlns:jpath="http://apache.org/xsp/jpath/1.0"
    >
    
    <document>
  
      <header>
        <title>Login</title>
        <authors>
          <person name="Ovidiu Predescu" email="ovidiu@apache.org"/>
        </authors>
      </header>
  
      <body>
        <s1 title="Login">
  
          <jpath:if test="errorMsg">
            <strong><jpath:value-of select="errorMsg"/></strong>
          </jpath:if>
  
  
          <form><xsp:attribute name="action"><xsp:expr>"../kont/" + <jpath:continuation/></xsp:expr></xsp:attribute>
  
            <p>Login name:
              <input type="text" name="login">
                <xsp:attribute name="value"><jpath:value-of select="login"/></xsp:attribute>
              </input>
            </p>
  
            <p>Password: <input type="password" name="password"/></p>
  
            <input type="submit" name="submit" value="Login"/>
  
            <p>Not yet registered? <link href="../register/">Register now!</link></p>
  
          </form>
         </s1>
      </body>
  
    </document>
  
  </xsp:page>
  
  
  
  1.1                  xml-cocoon2/src/webapp/samples/flow/examples/prefs/pages/registrationSuccessful.xsp
  
  Index: registrationSuccessful.xsp
  ===================================================================
  <?xml version="1.0"?>
  
  <!--
    Author: Ovidiu Predescu "ovidiu@apache.org"
  
    Date: August 30, 2002
   -->
  
  <xsp:page
    language="java"
    xmlns:xsp="http://apache.org/xsp"
    xmlns:jpath="http://apache.org/xsp/jpath/1.0"
    >
    
    <document>
  
      <header>
        <title>New User Registration</title>
        <authors>
          <person name="Ovidiu Predescu" email="ovidiu@apache.org"/>
        </authors>
      </header>
  
      <body>
        <s1 title="Registration successful!">
  
          <p>Congratulations <strong><jpath:value-of select="firstName"/> <jpath:value-of select="lastName"/></strong>! You've successfully registered as a new user.</p>
  
          <p>| <link href="../edit/">Edit my preferences</link> | <link href="../logout/">Logout</link> |</p>
  
         </s1>
      </body>
  
    </document>
  
  </xsp:page>
  
  
  
  1.1                  xml-cocoon2/src/webapp/samples/flow/examples/prefs/pages/userInfo.xsp
  
  Index: userInfo.xsp
  ===================================================================
  <?xml version="1.0"?>
  
  <!--
    Author: Ovidiu Predescu "ovidiu@apache.org"
  
    Page to show the user information.
  
    This page is used for both user registration and editing the user
    information, depending on the information passed down in the page.
  
    Date: August 30, 2002
   -->
  
  <xsp:page
    language="java"
    xmlns:xsp="http://apache.org/xsp"
    xmlns:jpath="http://apache.org/xsp/jpath/1.0"
    >
    
    <document>
  
      <header>
        <title><jpath:value-of select="title"/></title>
        <authors>
          <person name="Ovidiu Predescu" email="ovidiu@apache.org"/>
        </authors>
      </header>
  
      <body>
        <s1>
          <xsp:attribute name="title"><jpath:value-of select="title"/></xsp:attribute>
  
          <jpath:choose>
            <jpath:when test="errorMsg">
              <p><strong><jpath:value-of select="errorMsg"/></strong></p>
            </jpath:when>
            <jpath:otherwise>
              <p>Please enter the following data</p>
            </jpath:otherwise>
          </jpath:choose>
  
          <form><xsp:attribute name="action"><xsp:expr>"../kont/" + <jpath:continuation/></xsp:expr></xsp:attribute>
  
            <p>
              <jpath:choose>
                <jpath:when test="check and firstName = ''">
                  <strong>First name cannot be empty</strong>
                </jpath:when>
                <jpath:otherwise>
                  First name:
                </jpath:otherwise>
              </jpath:choose>
              <input type="text" name="firstName">
                <xsp:attribute name="value"><jpath:value-of select="firstName"/></xsp:attribute>
              </input>
            </p>
  
            <p>
              <jpath:choose>
                <jpath:when test="check and lastName = ''">
                  <strong>Last name cannot be empty</strong>
                </jpath:when>
                <jpath:otherwise>
                  Last name:
                </jpath:otherwise>
              </jpath:choose>
              <input type="text" name="lastName">
                <xsp:attribute name="value"><jpath:value-of select="lastName"/></xsp:attribute>
              </input>
            </p>
  
            <p>
              <jpath:choose>
                <jpath:when test="check and email = ''">
                  <strong>Email address cannot be empty</strong>
                </jpath:when>
                <jpath:otherwise>
                  Email address:
                </jpath:otherwise>
              </jpath:choose>
              <input type="text" name="email">
                <xsp:attribute name="value"><jpath:value-of select="email"/></xsp:attribute>
              </input>
            </p>
  
            <p>
              <jpath:choose>
                <jpath:when test="check and login = ''">
                  <strong>Login name cannot be empty</strong>
                </jpath:when>
                <jpath:otherwise>
                  Login name:
                </jpath:otherwise>
              </jpath:choose>
              <input type="text" name="login">
                <xsp:attribute name="value"><jpath:value-of select="login"/></xsp:attribute>
              </input>
            </p>
  
  
            <p>
              <jpath:choose>
                <jpath:when test="check and password = ''">
                  <strong>Password cannot be empty</strong>
                </jpath:when>
                <jpath:otherwise>
                  Password:
                </jpath:otherwise>
              </jpath:choose>
              <input type="password" name="password">
                <xsp:attribute name="value"><jpath:value-of select="password"/></xsp:attribute>
              </input>
            </p>
  
  
            <input type="submit" name="submit">
              <xsp:attribute name="value"><jpath:value-of select="button"/></xsp:attribute>
            </input>
  
            <jpath:if test="cancel">
              <input type="submit" name="cancel" value="Cancel"/>
            </jpath:if>
  
          </form>
         </s1>
      </body>
  
    </document>
  
  </xsp:page>
  
  
  
  1.1                  xml-cocoon2/src/webapp/samples/flow/examples/prefs/pages/welcome.xsp
  
  Index: welcome.xsp
  ===================================================================
  <?xml version="1.0"?>
  
  <!--
    Author: Ovidiu Predescu "ovidiu@apache.org"
  
    Date: August 30, 2002
   -->
  
  <xsp:page
    language="java"
    xmlns:xsp="http://apache.org/xsp"
    xmlns:jpath="http://apache.org/xsp/jpath/1.0"
    >
    
    <document>
  
      <header>
        <title>Welcome!</title>
        <authors>
          <person name="Ovidiu Predescu" email="ovidiu@apache.org"/>
        </authors>
      </header>
  
      <body>
        <s1 title="Welcome back!">
  
          <p>Welcome back, <strong><jpath:value-of select="firstName"/> <jpath:value-of select="lastName"/></strong>!</p>
  
          <p>| <link href="../edit/">Edit my preferences</link> | <link href="../logout/">Logout</link> |</p>
  
         </s1>
      </body>
  
    </document>
  
  </xsp:page>
  
  
  

----------------------------------------------------------------------
In case of troubles, e-mail:     webmaster@xml.apache.org
To unsubscribe, e-mail:          cocoon-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: cocoon-cvs-help@xml.apache.org