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  import org.cb.jset.SetGameConnection;
24  import org.cb.jset.JSetGameImpl;
25  import org.cb.jset.CardSet;
26  import org.cb.jset.MatchingException;
27  import org.cb.jset.SetGamePlayer;
28  import org.cb.jset.CardProperties;
29  
30  import java.rmi.RemoteException;
31  import java.rmi.server.UnicastRemoteObject;
32  import java.io.Serializable;
33  
34  /***
35   * An implementation of a remote Game.
36   * <p>
37   * Contains several inner classes that act as wrappers, allowing to transparently use remote implementations locally.
38   *
39   * @author jerome@coffeebreaks.org - last modified by $LastChangedBy: jerome $
40   * @version $Id: JSetRemoteGameImpl.java 130 2004-04-15 05:18:07Z jerome $
41   */
42  public class JSetRemoteGameImpl extends UnicastRemoteObject implements RemoteSetGame
43  {
44    private final Logger _logger = Logger.getLogger(this.getClass().getName());
45  
46    private final JSetGameImpl _game;
47  
48    /***
49     * Constructs a remote game instance given the specified name and number of players.
50     * @param name
51     * @param nbPlayers
52     * @throws java.rmi.RemoteException upon communication related exception on this remote call
53     */
54    JSetRemoteGameImpl(final String name, final int nbPlayers) throws RemoteException
55    {
56      super();
57      _game = new JSetGameImpl(name, nbPlayers);
58      init();
59    }
60  
61    /***
62     * A remote Game connection that effectively wrapps a local one.
63     */
64    static class LocalConnectionWrapper extends UnicastRemoteObject implements Serializable, RemoteSetGameConnection
65    {
66      private final transient SetGameConnection _localConnection;
67  
68      /***
69       * Constructs an instance of <code>LocalConnectionWrapper</code>
70       * @param localConnection
71       * @throws java.rmi.RemoteException upon communication related exception on this remote call
72       */
73      public LocalConnectionWrapper(final SetGameConnection localConnection) throws RemoteException
74      {
75        _localConnection = localConnection;
76      }
77  
78      /***
79       * Used by a registered player to try to match a set of set.
80       * @param set the set to try to match.
81       * @throws MatchingException if the set doesn't match or if a card is not on the board.
82       * @see org.cb.jset.SetGameConnection#matchSet(org.cb.jset.CardSet)
83       */
84      public void matchSet(final CardSet set) throws MatchingException
85      {
86        _localConnection.matchSet(set);
87      }
88  
89      /***
90       * Close the game connection, effectively leaving the game.
91       * @see org.cb.jset.SetGameConnection#close()
92       */
93      public void close()
94      {
95        _localConnection.close();
96      }
97  
98      /***
99       * Say wether the game connection is closed or not.
100      * @return <code>true</code> if the connection is closed, <code>false</code> otherwise.
101      * @see org.cb.jset.SetGameConnection#isClosed()
102      */
103     public boolean isClosed()
104     {
105       return _localConnection.isClosed();
106     }
107   }
108 
109   /***
110    * Implementation of a player for a remote game.
111    * Effectively wraps a {@link RemoteSetGamePlayer}.
112    */
113   static class RemotePlayerWrapper implements SetGamePlayer
114   {
115     private final RemoteSetGamePlayer _remotePlayer;
116 //    private boolean _wasDisconnected;
117 //    private RemoteException _remoteException;
118 
119     /***
120      * Constructs an instance using the specified remotePlayer.
121      * @param remotePlayer
122      */
123     public RemotePlayerWrapper(final RemoteSetGamePlayer remotePlayer)
124     {
125       _remotePlayer = remotePlayer;
126     }
127 
128     private void treatConnectionProblem(final RemoteException e)
129     {
130 //      _wasDisconnected = true;
131 //      _remoteException = e;
132       throw new IllegalStateException("Failure to make a remote call... " + e.getMessage());
133     }
134 
135     /***
136      * @return the name of the player.
137      */
138     public String getName()
139     {
140       try
141       {
142         return _remotePlayer.getName();
143       }
144       catch (RemoteException e)
145       {
146         treatConnectionProblem(e);
147       }
148       return ""; // please compiler...
149     }
150 
151     /***
152      * Called by a game when the player should be blocked.
153      * @see #isBlocked()
154      */
155     public void block()
156     {
157       try
158       {
159         _remotePlayer.block();
160       }
161       catch (RemoteException e)
162       {
163         treatConnectionProblem(e);
164       }
165     }
166 
167     /***
168      * Called by a game when the player should be unblocked.
169      * @see #isBlocked()
170      */
171     public void unblock()
172     {
173       try
174       {
175         _remotePlayer.unblock();
176       }
177       catch (RemoteException e)
178       {
179         treatConnectionProblem(e);
180       }
181     }
182 
183     /***
184      * A blocked player doesn't have the right to play.
185      * @return <code>true</code> is the player is blocked, <code>false</code> otherwise.
186      */
187     public boolean isBlocked()
188     {
189       try
190       {
191         return _remotePlayer.isBlocked();
192       }
193       catch (RemoteException e)
194       {
195         treatConnectionProblem(e);
196       }
197       return false; // please compiler...
198     }
199 
200 
201     /***
202      * Called to notify a disconnection from a game.
203      */
204     public void disconnect()
205     {
206       try
207       {
208         _remotePlayer.disconnect();
209       }
210       catch (RemoteException e)
211       {
212         treatConnectionProblem(e);
213       }
214     }
215 
216     /***
217      * Called to notify that the specified cards were added to the board.
218      * @param cards the cards that were added to the board.
219      */
220     public void cardsAdded(final CardProperties[] cards)
221     {
222       try
223       {
224         _remotePlayer.cardsAdded(cards);
225       }
226       catch (RemoteException e)
227       {
228         treatConnectionProblem(e);
229       }
230     }
231 
232     /***
233      * Called to notify that the specified set was removed from the board.
234      * The set should be a {@link CardSet#isMatching() matching set}.
235      * @param set the set that was removed from the board
236      */
237     public void setRemoved(final CardSet set)
238     {
239       try
240       {
241         _remotePlayer.setRemoved(set);
242       }
243       catch (RemoteException e)
244       {
245         treatConnectionProblem(e);
246       }
247     }
248   }
249 
250   void init()
251   {
252     _game.start();
253   }
254 
255   void terminate()
256   {
257     _game.terminate();
258   }
259 
260   /***
261    * @inheritDoc
262    */
263   public String getName() throws RemoteException
264   {
265     return _game.getName();
266   }
267 
268   /***
269    * @inheritDoc
270    */
271   public int getCurrentNbPlayers() throws RemoteException
272   {
273     return _game.getCurrentNbPlayers();
274   }
275 
276   /***
277    * @inheritDoc
278    */
279   public int getMaxNbPlayers() throws RemoteException
280   {
281     return _game.getMaxNbPlayers();
282   }
283 
284   /***
285    * @inheritDoc
286    */
287   public RemoteSetGameConnection connect(final RemoteSetGamePlayer player) throws RemoteException
288   {
289     if (_logger.isInfoEnabled())
290     {
291       _logger.info("Connecting player:" + player.getName() + ">");
292     }
293     final SetGameConnection conn;
294     synchronized (this)
295     {
296       final SetGamePlayer playerWrapper = new RemotePlayerWrapper(player);
297       conn = _game.connect(playerWrapper);
298     }
299     return new LocalConnectionWrapper(conn);
300   }
301 
302   /***
303    * @inheritDoc
304    */
305   public int getID() throws RemoteException
306   {
307     return _game.getID();
308   }
309 }