View Javadoc

1   // START LICENSE
2   // JSet - a Java JSet card board game implementation
3   // Copyright (C) 2004 Jerome Lacoste
4   //
5   // This program is free software; you can redistribute it and/or modify
6   // it under the terms of the GNU General Public License as published by
7   // the Free Software Foundation; either version 2 of the License, or (at
8   // your option) any later version.
9   //
10  // This program is distributed in the hope that it will be useful, but
11  // WITHOUT ANY WARRANTY; without even the implied warranty of
12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  // General Public License for more details.
14  //
15  // You should have received a copy of the GNU General Public License
16  // along with this program; if not, write to the Free Software
17  // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18  // END LICENSE
19  
20  package org.cb.jset.server;
21  
22  import org.apache.log4j.Logger;
23  
24  import java.rmi.RemoteException;
25  import java.rmi.server.UnicastRemoteObject;
26  import java.util.Vector;
27  import java.util.List;
28  import java.net.MalformedURLException;
29  
30  /***
31   * Provides accesses to RemoteSetGame implementations.
32   *
33   * @author jerome@coffeebreaks.org - last modified by $LastChangedBy: jerome $
34   * @version $Id: JSetGameServer.java 130 2004-04-15 05:18:07Z jerome $
35   */
36  public class JSetGameServer extends UnicastRemoteObject implements RemoteSetGameServer
37  {
38    private static final Logger LOGGER = Logger.getLogger(JSetGameServer.class);
39  
40    /***
41     * A class used to register the different creates games.
42     */
43    private static class Games
44    {
45      private final List _games = new Vector();
46  
47      private synchronized void addGame(final RemoteSetGame game)
48      {
49        _games.add(game);
50      }
51  
52      /***
53       * @param game
54       * @todo ending remote games should deregister themselves
55       */
56      private synchronized void removeGame(final RemoteSetGame game)
57      {
58        _games.remove(game);
59      }
60  
61      private synchronized RemoteSetGame[] getGames()
62      {
63        RemoteSetGame[] games = new RemoteSetGame[_games.size()];
64        games = (RemoteSetGame[]) _games.toArray(games);
65        return games;
66      }
67  
68      private synchronized RemoteSetGame getGame(final int id) throws RemoteException
69      {
70        for (int i = 0; i < _games.size(); i++)
71        {
72          final RemoteSetGame game = (RemoteSetGame) _games.get(i);
73          if (game.getID() == id)
74          {
75            return game;
76          }
77        }
78        return null;
79      }
80  
81      private void closeGames()
82      {
83        for (int i = 0; i < _games.size(); i++)
84        {
85          final JSetRemoteGameImpl game = (JSetRemoteGameImpl) _games.get(i);
86          game.terminate();
87        }
88      }
89    }
90  
91    private final Games _games = new Games();
92  
93    /***
94     * Creates a new instance of JSetGameServer.
95     * @throws RemoteException if failed to export object
96     * @todo specify a port
97     */
98    public JSetGameServer() throws RemoteException
99    {
100     addShutdownHook();
101   }
102 
103   /***
104    * Create a game with the specified number of players.
105    * @param name the name of the game.
106    * @param nbPlayers the number of players.
107    * @return the new game id
108    * @throws java.rmi.RemoteException upon communication related exception on this remote call
109    */
110   public int createGame(final String name, final int nbPlayers) throws java.rmi.RemoteException
111   {
112     // FIXME search for games with existing name
113     final RemoteSetGame game = new JSetRemoteGameImpl(name, nbPlayers);
114     _games.addGame(game);
115     return game.getID();
116   }
117 
118   /***
119    * Returns the game identified by the specified id.
120    * @param id the id of the game to return
121    * @return the game if found, or <code>null</code> if none found.
122    * @throws java.rmi.RemoteException upon communication related exception on this remote call
123    */
124   public RemoteSetGame getGame(final int id) throws RemoteException
125   {
126     return _games.getGame(id);
127   }
128 
129   /***
130    * @return the different remote games known to this server.
131    * @throws java.rmi.RemoteException upon communication related exception on this remote call
132    */
133   public RemoteSetGame[] getGames() throws RemoteException
134   {
135     return _games.getGames();
136   }
137 
138   /***
139    * Make sure all games are closed when this game server dies.
140    */
141   private void addShutdownHook()
142   {
143     /***
144      * a Runnable that close all games.
145      */
146     class JSetShutdownHook implements Runnable
147     {
148       /***
149        * run this runnable
150        */
151       public void run()
152       {
153         LOGGER.debug("ShutdownHook: dying.");
154         _games.closeGames();
155       }
156     }
157     LOGGER.debug("Registering shutdown hook");
158     Runtime.getRuntime().addShutdownHook(new Thread(new JSetShutdownHook()));
159   }
160 
161   /***
162    * Starts a JSetGameServer.
163    * @param args no specific argument expected
164    */
165   public static void main(final String[] args)
166   {
167     //java.util.Properties props = System.getProperties();
168     //props.list(System.out);
169     org.apache.log4j.PropertyConfigurator.configure("log4j.properties");
170     LOGGER.info("CLASSPATH:" + System.getProperty("java.class.path"));
171     if (System.getSecurityManager() == null)
172     {
173       LOGGER.debug("adding RMISecurityManager");
174       System.setSecurityManager(new java.rmi.RMISecurityManager());
175     }
176     final String name = "//localhost/JSetServer";
177     RemoteSetGameServer server;
178     try
179     {
180       server = new JSetGameServer();
181     }
182     catch (RemoteException e)
183     {
184       LOGGER.error("JSetGameServer exception: failure to export game server object.", e);
185       System.exit(-1);
186       return; // please compiler
187     }
188     try
189     {
190       java.rmi.Naming.rebind(name, server);
191       LOGGER.info("JSetGameServer bound");
192     }
193     catch (RemoteException e)
194     {
195       LOGGER.error("JSetGameServer exception: couldn't connect to registry."
196       + " Check that the rmiregistry is running on the specified host.", e);
197       System.exit(-1);
198     }
199     catch (MalformedURLException e)
200     {
201       LOGGER.error("JSetGameServer exception: check your config " + name, e);
202       System.exit(-1);
203     }
204   }
205 }