Advertisement
Guest User

Untitled

a guest
Aug 10th, 2017
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 12.61 KB | None | 0 0
  1. package soc.gwtServer;
  2.  
  3. import java.util.Map;
  4. import java.util.Random;
  5. import java.util.concurrent.ConcurrentHashMap;
  6. import java.util.concurrent.ConcurrentMap;
  7. import java.util.regex.Pattern;
  8.  
  9. import javax.servlet.ServletException;
  10. import javax.servlet.http.HttpSession;
  11.  
  12. import net.zschech.gwt.comet.server.CometServlet;
  13. import net.zschech.gwt.comet.server.CometSession;
  14. import soc.common.actions.Invalid;
  15. import soc.common.actions.Valid;
  16. import soc.common.actions.ValidateResult;
  17. import soc.common.actions.lobby.LobbyAction;
  18. import soc.common.actions.lobby.LobbyChat;
  19. import soc.common.actions.lobby.UserJoined;
  20. import soc.common.core.Core;
  21. import soc.common.lobby.GameInfo;
  22. import soc.common.lobby.Lobby;
  23. import soc.common.lobby.LobbyImpl;
  24. import soc.common.lobby.LoginResponse;
  25. import soc.common.server.GreetingService;
  26. import soc.common.server.LobbyServer;
  27. import soc.common.server.LoginResponseImpl;
  28. import soc.common.server.RegisterResult;
  29. import soc.common.server.entities.AnonymousUser;
  30. import soc.common.server.entities.Player;
  31. import soc.common.server.entities.RegisterResultImpl;
  32. import soc.common.server.entities.User;
  33. import soc.common.server.entities.UserProvider;
  34. import soc.common.server.lobbyActions.DefaultServerLobbyActionFactory;
  35. import soc.common.server.lobbyActions.ServerLobbyAction;
  36. import soc.common.server.lobbyActions.ServerLobbyActionFactory;
  37. import soc.gwtServer.database.OdbUserProvider;
  38.  
  39. import com.db4o.Db4oEmbedded;
  40. import com.db4o.ObjectContainer;
  41. import com.db4o.ObjectSet;
  42. import com.google.gwt.user.server.rpc.RemoteServiceServlet;
  43.  
  44. /** The server side implementation of the RPC service. */
  45. @SuppressWarnings("serial")
  46. public class GreetingServiceImpl extends RemoteServiceServlet implements
  47.                 GreetingService, LobbyServer
  48. {
  49.     private ConcurrentMap<User, CometSession> users = new ConcurrentHashMap<User, CometSession>();
  50.     private ConcurrentMap<User, GameInfo> games = new ConcurrentHashMap<User, GameInfo>();
  51.     private ObjectContainer database;
  52.     private ServerLobbyActionFactory factory = new DefaultServerLobbyActionFactory(
  53.                     this);
  54.     private Lobby lobby = new LobbyImpl();
  55.     private Random random = new Random();
  56.     private static final transient Valid valid = new Valid();
  57.     private UserProvider userProvider;
  58.  
  59.     /*
  60.      * (non-Javadoc)
  61.      *
  62.      * @see javax.servlet.GenericServlet#init()
  63.      */
  64.     @Override
  65.     public void init() throws ServletException
  66.     {
  67.         // Init database
  68.         database = Db4oEmbedded.openFile(Db4oEmbedded.newConfiguration(),
  69.                         "database.db");
  70.  
  71.         // Create db4o user provider
  72.         userProvider = new OdbUserProvider(database);
  73.     }
  74.  
  75.     /** @see net.zschech.gwt.chat.client.ChatService#send(java.lang.String) */
  76.     @Override
  77.     public ValidateResult send(LobbyAction action)
  78.     {
  79.         // check if there is a HTTP session setup.
  80.         HttpSession httpSession = getThreadLocalRequest().getSession(false);
  81.         if (httpSession == null)
  82.             return new Invalid("not logged in: no http session");
  83.  
  84.         // Grab user
  85.         User user = getUserById(action.getUserId());
  86.  
  87.         // Set the User reference on the action instance
  88.         if (user != null)
  89.             action.setUser(user);
  90.  
  91.         // get the user name for the HTTP session.
  92.         User userFromSession = (User) httpSession.getAttribute("user");
  93.         if (userFromSession == null)
  94.             return new Invalid("not logged in: no http session username");
  95.  
  96.         // Check if the user doesn't tamper with the data
  97.         if (user.getId() != action.getUserId())
  98.             return new Invalid(
  99.                             "UserID differs from userID in session. Something is baaaaad");
  100.  
  101.         // Only the ID is sent, not the user instance, so set the user on the LobbyAction
  102.         action.setUser(user);
  103.  
  104.         performLobbyAction(action);
  105.  
  106.         return valid;
  107.     }
  108.  
  109.     /*
  110.      * Returns a User having given userId. Returns null, if such a user is not logged in.
  111.      */
  112.     private User getUserById(int id)
  113.     {
  114.         for (User user : users.keySet())
  115.             if (user.getId() == id)
  116.                 return user;
  117.  
  118.         return null;
  119.     }
  120.  
  121.     /*
  122.      * Sends given action to all the users in the lobby
  123.      *
  124.      * @see soc.common.server.LobbyServer#sendToAll(soc.common.actions.lobby.LobbyAction)
  125.      */
  126.     @Override
  127.     public void sendToAll(LobbyAction action)
  128.     {
  129.         for (Map.Entry<User, CometSession> entry : users.entrySet())
  130.             entry.getValue().enqueue(action);
  131.     }
  132.  
  133.     /*
  134.      * Sends given action to all users in the lobby, except to given exlcuded user
  135.      *
  136.      * @see soc.common.server.LobbyServer#sendToAllExcept(soc.common.server.entities.User,
  137.      * soc.common.actions.lobby.LobbyAction)
  138.      */
  139.     @Override
  140.     public void sendToAllExcept(User excludedUser, LobbyAction action)
  141.     {
  142.         for (Map.Entry<User, CometSession> entry : users.entrySet())
  143.             if (!entry.getValue().equals(excludedUser))
  144.                 entry.getValue().enqueue(action);
  145.     }
  146.  
  147.     @Override
  148.     public LoginResponse login(String username, String password)
  149.     {
  150.         // Grab user from database
  151.         User user = userProvider.getUser(username, password);
  152.  
  153.         if (user == null)
  154.             return new LoginResponseImpl(new Invalid(
  155.                             "Could not find registered user with name \""
  156.                                             + username + "\""));
  157.  
  158.         // Get or create the HTTP session for the browser
  159.         HttpSession httpSession = getThreadLocalRequest().getSession();
  160.  
  161.         // Get or create the Comet session for the browser
  162.         CometSession cometSession = CometServlet.getCometSession(httpSession);
  163.  
  164.         // Remember the user
  165.         httpSession.setAttribute("user", user);
  166.  
  167.         // setup the mapping of user names to CometSessions
  168.         if (users.putIfAbsent(user, cometSession) != null)
  169.         {
  170.             // some one else has already logged in with this user name
  171.             httpSession.invalidate();
  172.             return new LoginResponseImpl(new Invalid("User: " + username
  173.                             + " already logged in"));
  174.         }
  175.  
  176.         notifyUserJoined(user);
  177.  
  178.         return createLoginResponse(user);
  179.     }
  180.     /*
  181.      * Notifies all other players that given player has joined the game
  182.      */
  183.     private void notifyUserJoined(User user)
  184.     {
  185.         // Create a new UserJoined LobbyAction
  186.         UserJoined userJoined = new UserJoined();
  187.         userJoined.setJoinedUser(user);
  188.         userJoined.setUser(user);
  189.  
  190.         // Send it to everyone but the joined user
  191.         sendToAllExcept(user, userJoined);
  192.     }
  193.  
  194.     /*
  195.      * Logs given username in as an anonymous user
  196.      *
  197.      * @see soc.common.server.GreetingService#loginAnonymous(java.lang.String)
  198.      */
  199.     @Override
  200.     public LoginResponse loginAnonymous(String username)
  201.     {
  202.         // Bugger out when the username already exists
  203.         if (userProvider.getUserByName(username) != null)
  204.             return new LoginResponseImpl(new Invalid("Username already exists"));
  205.  
  206.         User user = new AnonymousUser().setName(username);
  207.  
  208.         // Get or create the HTTP session for the browser
  209.         HttpSession httpSession = getThreadLocalRequest().getSession();
  210.  
  211.         // Get or create the Comet session for the browser
  212.         CometSession cometSession = CometServlet.getCometSession(httpSession);
  213.  
  214.         // Remember the user name for the
  215.         httpSession.setAttribute("user", user);
  216.  
  217.         // setup the mapping of user names to CometSessions
  218.         if (users.putIfAbsent(user, cometSession) != null)
  219.         {
  220.             // some one else has already logged in with this user name
  221.             httpSession.invalidate();
  222.             return new LoginResponseImpl(new Invalid("User: " + username
  223.                             + " already logged in"));
  224.         }
  225.  
  226.         notifyUserJoined(user);
  227.  
  228.         return createLoginResponse(user);
  229.     }
  230.  
  231.     /*
  232.      * Creates a new LoginResponse for a user logging in
  233.      */
  234.     private synchronized LoginResponse createLoginResponse(User user)
  235.     {
  236.         // Create a new instance
  237.         LoginResponse response = new LoginResponseImpl();
  238.  
  239.         // Copy list of users to it
  240.         for (Map.Entry<User, CometSession> entry : users.entrySet())
  241.             response.getLoggedInUsers().addUser(entry.getKey());
  242.  
  243.         // Copy list of games
  244.         for (GameInfo gameInfo : lobby.getGames())
  245.             response.getLobbyGames().add(gameInfo);
  246.  
  247.         response.setUser(user);
  248.  
  249.         return response;
  250.     }
  251.  
  252.     /*
  253.      * Create a server action, perform it and send it to clients
  254.      */
  255.     @Override
  256.     public void performLobbyAction(LobbyAction action)
  257.     {
  258.         // Grab ServerLobbyAction assocaited by the factory
  259.         ServerLobbyAction serverLobbyAction = action
  260.                         .createServerLobbyAction(factory);
  261.  
  262.         // Actualize lobby by performing the LobbyAction
  263.         serverLobbyAction.perform(lobby);
  264.  
  265.         // Notify clients
  266.         serverLobbyAction.sendToClients();
  267.     }
  268.  
  269.     @Override
  270.     public Lobby getLobby()
  271.     {
  272.         return lobby;
  273.     }
  274.  
  275.     /*
  276.      * Sends given action only to target user
  277.      *
  278.      * @see soc.common.server.LobbyServer#sendToUser(soc.common.server.entities.User,
  279.      * soc.common.actions.lobby.LobbyAction)
  280.      */
  281.     @Override
  282.     public void sendToUser(User exclusiveUser, LobbyAction action)
  283.     {
  284.         // Grab the session of the given user
  285.         CometSession session = users.get(exclusiveUser);
  286.  
  287.         // Send the action
  288.         if (session != null)
  289.             session.enqueue(action);
  290.     }
  291.  
  292.     /*
  293.      * Sends an error message to given user, disguised as a LobbyChat message
  294.      *
  295.      * @see soc.common.server.LobbyServer#sayError(soc.common.server.entities.User,
  296.      * java.lang.String)
  297.      */
  298.     @Override
  299.     public void sayError(User user, String error)
  300.     {
  301.         // Create a simple LobbyChat instance with the error
  302.         LobbyChat lobbyChat = new LobbyChat();
  303.         lobbyChat.setUser(user);
  304.         lobbyChat.setChatMessage(error);
  305.  
  306.         // Send it to given user
  307.         sendToUser(user, lobbyChat);
  308.     }
  309.  
  310.     /*
  311.      * Checks if registration can take place, if so, registers a user
  312.      *
  313.      * @see soc.common.server.GreetingService#register(java.lang.String, java.lang.String)
  314.      */
  315.     @Override
  316.     public RegisterResult register(String username, String password)
  317.     {
  318.         if (!isAvailableName(username))
  319.             return new RegisterResultImpl(
  320.                             new Invalid("Username ialready taken"));
  321.  
  322.         ValidateResult result = isValidName(username);
  323.         if (!result.isValid())
  324.             return new RegisterResultImpl(result);
  325.  
  326.         if (password == null || password.length() == 0 || password == "")
  327.             return new RegisterResultImpl(new Invalid("Password is empty"));
  328.  
  329.         // Create a new player
  330.         User player = new Player().setName(username).setPassword(password)
  331.                         .setRegistered(true);
  332.  
  333.         // Store the player
  334.         database.store(player);
  335.  
  336.         return new RegisterResultImpl(player);
  337.     }
  338.  
  339.     /*
  340.      * Checks store for existing players with given name, returns true when given name is available
  341.      *
  342.      * @see soc.common.server.GreetingService#isAvailableName(java.lang.String)
  343.      */
  344.     public boolean isAvailableName(String username)
  345.     {
  346.         // Get a list of players with given name.
  347.         User proto = new Player().setName(username);
  348.         ObjectSet availablePlayers = database.queryByExample(proto);
  349.  
  350.         // No names equal to given name exist when the list is empty
  351.         return availablePlayers.size() == 0;
  352.     }
  353.  
  354.     /*
  355.      * Returns invalid when the name is too short, starts with "bot" or contains non alphanumeric
  356.      * characters
  357.      */
  358.     public ValidateResult isValidName(String username)
  359.     {
  360.         if (username.length() < 4)
  361.             return new Invalid("Sorry, nickname must be at least 4 charcters");
  362.  
  363.         if (username.substring(0, 3).toLowerCase() == "bot")
  364.             return new Invalid("Sorry, nickname cannot start with \"bot\"");
  365.  
  366.         // Only allow A-Z, a-z, 0-9 for simplicity and security
  367.         Pattern pattern = Pattern.compile("^[0-9a-zA-Z]+$");
  368.         if (!pattern.matcher(username).matches())
  369.             return new Invalid(
  370.                             "Sorry, can only use characters [A-Z], [a-z] and [0-9].");
  371.  
  372.         return Core.valid;
  373.     }
  374. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement