Changeset 36 for chess


Ignore:
Timestamp:
02/10/09 20:01:59 (13 years ago)
Author:
BegemoT
Message:

threading

Location:
chess/src/chess
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • chess/src/chess/MSG.properties

    r34 r36  
    2626join-game.no-server-found.title =\u041d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u043e :( 
    2727join-game.no-server-found.message= \u041f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0438\u0433\u0440 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u043e 
     28join-game.search-interrupted.message= \u041f\u043e\u0438\u0441\u043a \u043f\u0440\u0435\u0440\u0432\u0430\u043d 
    2829join-game.scanning-network.title   = \u041f\u043e\u0438\u0441\u043a \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u0432... 
    2930join-game.scanning-network.message = \u0418\u0449\u0435\u043c \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 
     
    4748player.white = \u0411\u0435\u043b\u044b\u0435 
    4849player.black = \u0427\u0435\u0440\u043d\u044b\u0435 
     50 
     51alert.error = \u041e\u0448\u0438\u0431\u043a\u0430 
     52alert.warning = \u0412\u043d\u0438\u043c\u0430\u043d\u0438\u0435 
  • chess/src/chess/Util.java

    r29 r36  
    33import java.io.*; 
    44import javax.microedition.rms.RecordStore; 
     5import javax.microedition.lcdui.Alert; 
     6import javax.microedition.lcdui.AlertType; 
    57 
    68import chess.remote.IRemote; 
     
    5153        } 
    5254    } 
     55 
     56        public static Alert createErrorDialog( final Throwable e ) { 
     57                final String msg = e.getMessage(); 
     58                return createErrorDialog( msg ); 
     59        } 
     60 
     61        public static Alert createErrorDialog( final String msg ) { 
     62                return new Alert( 
     63                                                MSG.getMessage( "alert.error"), 
     64                                                msg, 
     65                                                null, 
     66                                                AlertType.ERROR 
     67                                ); 
     68        } 
    5369} 
  • chess/src/chess/control/BaseController.java

    r33 r36  
    66import javax.microedition.lcdui.Command; 
    77import javax.microedition.lcdui.Displayable; 
    8 import javax.microedition.lcdui.AlertType; 
    98 
    109import chess.game.*; 
     
    1514import chess.ui.GameCanvas; 
    1615import chess.ui.IUIListener; 
     16import chess.Util; 
    1717 
    1818 
     
    162162        final Throwable e = node.getError(); 
    163163        if ( e != null ) { 
    164             final Alert alert = new Alert( "Error", e.getMessage(), null, AlertType.ERROR ); 
     164            final Alert alert = Util.createErrorDialog( e ); 
    165165            app.getMidlet().display.setCurrent( alert ); 
    166166        } 
     
    169169    } 
    170170 
    171     public void post( final IDatagram data ) { 
     171        public void post( final IDatagram data ) { 
    172172        setStatus( WAITING_FOR_NETWORK ); 
    173173        node.send( data ); 
  • chess/src/chess/game/units/Pawn.java

    r33 r36  
    11package chess.game.units; 
    22 
    3 import chess.game.IGame; 
    4 import chess.game.IUnit; 
    5 import chess.game.Location; 
    6 import chess.game.Player; 
     3import chess.game.*; 
    74 
    85 
     
    1512public class Pawn extends AUnit { 
    1613 
    17     private int turnNum = 0; 
     14        private int turnNum = 0; 
    1815 
    19     public Pawn( final Player player, 
    20                  final IGame game, 
    21                  final Location location ) { 
    22         super( player, game, location ); 
    23     } 
     16        public Pawn( final Player player, 
     17                     final IGame game, 
     18                     final Location location ) { 
     19                super( player, game, location ); 
     20        } 
    2421 
    25     public Pawn( final Player player, 
    26                  final IGame game, 
    27                  final Location location, 
    28                  final int turnNum ) { 
    29         super( player, game, location ); 
    30         this.turnNum = turnNum; 
    31     } 
     22        public Pawn( final Player player, 
     23                     final IGame game, 
     24                     final Location location, 
     25                     final int turnNum ) { 
     26                super( player, game, location ); 
     27                this.turnNum = turnNum; 
     28        } 
    3229 
    33     public void setLocation( final Location location ) { 
    34         super.setLocation( location ); 
    35         turnNum++; 
    36     } 
     30        public void setLocation( final Location location ) { 
     31                super.setLocation( location ); 
     32                turnNum++; 
     33        } 
    3734 
    38     public int type() { 
    39         return PAWN; 
    40     } 
     35        public int type() { 
     36                return PAWN; 
     37        } 
    4138 
    42     public Location[] canMoveTo() { 
    43         final Location l = getLocation(); 
    44         _temp.removeAllElements(); 
    45         final int dir = player.getDirection(); 
     39        public Location[] canMoveTo() { 
     40                final Location l = getLocation(); 
     41                _temp.removeAllElements(); 
     42                final int dir = player.getDirection(); 
    4643 
    47         int x = l.x; 
    48         int y = l.y + dir; 
    49         if ( game.isValid( x, y ) && game.isFree( x, y ) ) { 
    50             _temp.addElement( new Location( x, y ) ); 
    51         } 
    52         x = l.x - 1; 
    53         if ( game.isValid( x, y ) ) { 
    54             final IUnit u = game.getUnit( x, y ); 
    55             if ( u != null && isOpponent( u ) ) { 
    56                 _temp.addElement( new Location( x, y ) ); 
    57             } 
    58         } 
    59         x = l.x + 1; 
    60         if ( game.isValid( x, y ) ) { 
    61             final IUnit u = game.getUnit( x, y ); 
    62             if ( u != null && isOpponent( u ) ) { 
    63                 _temp.addElement( new Location( x, y ) ); 
    64             } 
    65         } 
    66         //äëèííûé õîä 
    67         if ( turnNum == 0 ) { 
    68             x = l.x; 
    69             y = l.y + 2 * dir; 
    70             if ( game.isValid( x, y ) && game.isFree( x, y ) ) { 
    71                 _temp.addElement( new Location( x, y ) ); 
    72             } 
    73         } 
     44                int x = l.x; 
     45                int y = l.y + dir; 
     46                if( game.isValid( x, y ) && game.isFree( x, y ) ) { 
     47                        _temp.addElement( new Location( x, y ) ); 
     48                } 
     49                x = l.x - 1; 
     50                if( game.isValid( x, y ) ) { 
     51                        final IUnit u = game.getUnit( x, y ); 
     52                        if( u != null && isOpponent( u ) ) { 
     53                                _temp.addElement( new Location( x, y ) ); 
     54                        } 
     55                } 
     56                x = l.x + 1; 
     57                if( game.isValid( x, y ) ) { 
     58                        final IUnit u = game.getUnit( x, y ); 
     59                        if( u != null && isOpponent( u ) ) { 
     60                                _temp.addElement( new Location( x, y ) ); 
     61                        } 
     62                } 
     63                //äëèííûé õîä 
     64                if( turnNum == 0 ) { 
     65                        x = l.x; 
     66                        y = l.y + 2 * dir; 
     67                        if( game.isValid( x, y ) && game.isFree( x, y ) ) { 
     68                                _temp.addElement( new Location( x, y ) ); 
     69                        } 
     70                } 
    7471 
    75         x = l.x + 1; 
    76         y = l.y; 
    77         //âçÿòèå ïåøêè íà ïðîõîäå 
    78         { 
    79             if ( game.isValid( x, y ) ) { 
    80                 final IUnit u = game.getUnit( x, y ); 
    81                 if ( isOpponent( u ) 
    82                         && u.type() == PAWN 
    83                         && ( ( Pawn )u ).getTurnNum() == 1 ) { 
    84                     _temp.addElement( new Location( x, y ) ); 
    85                 } 
    86             } 
    87         } 
     72                x = l.x + 1; 
     73                y = l.y; 
     74                //âçÿòèå ïåøêè íà ïðîõîäå 
     75                { 
     76                        if( game.isValid( x, y ) ) { 
     77                                final IUnit u = game.getUnit( x, y ); 
     78                                if( u != null 
     79                                                && isOpponent( u ) 
     80                                                && u.type() == PAWN 
     81                                                && ( ( Pawn ) u ).getTurnNum() == 1 ) { 
     82                                        _temp.addElement( new Location( x, y ) ); 
     83                                } 
     84                        } 
     85                } 
    8886 
    89         x = l.x - 1; 
    90         y = l.y; 
    91         //âçÿòèå ïåøêè íà ïðîõîäå 
    92         { 
    93             if ( game.isValid( x, y ) ) { 
    94                 final IUnit u = game.getUnit( x, y ); 
    95                 if ( isOpponent( u ) 
    96                         && u.type() == PAWN 
    97                         && ( ( Pawn )u ).getTurnNum() == 1 ) { 
    98                     _temp.addElement( new Location( x, y ) ); 
    99                 } 
    100             } 
    101         } 
     87                x = l.x - 1; 
     88                y = l.y; 
     89                //âçÿòèå ïåøêè íà ïðîõîäå 
     90                { 
     91                        if( game.isValid( x, y ) ) { 
     92                                final IUnit u = game.getUnit( x, y ); 
     93                                if( u != null 
     94                                                && isOpponent( u ) 
     95                                                && u.type() == PAWN 
     96                                                && ( ( Pawn ) u ).getTurnNum() == 1 ) { 
     97                                        _temp.addElement( new Location( x, y ) ); 
     98                                } 
     99                        } 
     100                } 
    102101 
    103         return convertBuffer(); 
    104     } 
     102                return convertBuffer(); 
     103        } 
    105104 
    106     public boolean canTransform() { 
    107         return player.opponent().getBaseY( game ) == location.y; 
    108         //if ( player == Player.WHITE && location.y == game.getHeight() - 1 ) { 
    109         //    return true; 
    110         //} 
    111         //if ( player == Player.BLACK && location.y == 0 ) { 
    112         //    return true; 
    113         //} 
    114         //return false; 
    115     } 
     105        public boolean canTransform() { 
     106                return player.opponent().getBaseY( game ) == location.y; 
     107        } 
    116108 
    117     public IUnit transform() { 
    118         return new Queen( player, game, location ); 
    119     } 
     109        public IUnit transform() { 
     110                return new Queen( player, game, location ); 
     111        } 
    120112 
    121     public int getTurnNum() { 
    122         return turnNum; 
    123     } 
     113        public int getTurnNum() { 
     114                return turnNum; 
     115        } 
    124116 
    125     protected char getSymbol( final boolean white ) { 
    126         //if( white ) { 
    127         //      return '?'; 
    128         //} else { 
    129         //      return '?'; 
    130         //} 
    131         return 'P'; 
    132     } 
     117        protected char getSymbol( final boolean white ) { 
     118                //if( white ) { 
     119                //      return '?'; 
     120                //} else { 
     121                //      return '?'; 
     122                //} 
     123                return 'P'; 
     124        } 
    133125} 
  • chess/src/chess/remote/impl/BTNode.java

    r32 r36  
    2121 */ 
    2222public class BTNode implements IRemoteNode, Runnable { 
    23     /** 
    24      * êàíàë BT, èñïîëüçóåìûé íàøèì ïðèëîæåíèåì 
    25      * todo ïîíÿòü, êàêèå êàíàëû ñóùåñòâóþò 
    26      */ 
    27     private static final String BT_STREAM = "1"; 
    28  
    29     private String name; 
    30  
    31     private RemoteDevice device; 
    32     private IConnectionListener listener = null; 
    33     private StreamConnection connection = null; 
    34  
    35     private volatile boolean quitPump = false; 
    36  
    37     private transient InputStream in; 
    38     private transient OutputStream out; 
    39     private transient Thread pump; 
    40  
    41     private Throwable lastError = null; 
    42  
    43     /** 
    44      * ìîíèòîð îæèäàíèÿ îòêðûòèÿ ñîåäèíåíèÿ 
    45      */ 
     23        /** 
     24         * êàíàë BT, èñïîëüçóåìûé íàøèì ïðèëîæåíèåì 
     25         * todo ïîíÿòü, êàêèå êàíàëû ñóùåñòâóþò 
     26         */ 
     27        private static final String BT_STREAM = "1"; 
     28 
     29        private String name; 
     30 
     31        private RemoteDevice device; 
     32        private IConnectionListener listener = null; 
     33        private StreamConnection connection = null; 
     34 
     35        private volatile boolean quitPump = false; 
     36 
     37        private transient InputStream in; 
     38        private transient OutputStream out; 
     39        private transient Thread pump; 
     40 
     41        private Throwable lastError = null; 
     42 
     43        /** ìîíèòîð îæèäàíèÿ îòêðûòèÿ ñîåäèíåíèÿ */ 
    4644//      private final Object connectLock = new Object(); 
    4745 
    48     private final Object queueOverloadedLock = new Object(); 
    49     private final IDatagram[] postQueue = new IDatagram[2]; 
    50  
    51  
    52     public BTNode( final RemoteDevice device ) throws IOException { 
    53         this( device, null ); 
    54     } 
    55  
    56     public BTNode( final StreamConnection conn ) throws IOException { 
    57         this( null, null, conn ); 
    58     } 
    59  
    60     public BTNode( final RemoteDevice device, 
    61                    final StreamConnection conn ) throws IOException { 
    62         this( null, device, conn ); 
    63     } 
    64  
    65     public BTNode( final String name, 
    66                    final RemoteDevice device, 
    67                    final StreamConnection conn ) throws IOException { 
    68         if ( device == null && conn == null ) { 
    69             throw new IllegalArgumentException( "No-no-no, David Blain! device=null && conn=null" ); 
    70         } 
    71  
    72         if ( device == null ) { 
    73             this.device = RemoteDevice.getRemoteDevice( conn ); 
    74         } else { 
    75             this.device = device; 
    76         } 
    77         if ( name == null ) { 
    78             this.name = this.device.getFriendlyName( /*true*/false ); 
    79         } else { 
    80             this.name = name; 
    81         } 
    82         connection = conn; 
    83     } 
    84  
    85     public BTNode( final String name, 
    86                    final StreamConnection conn ) throws IOException { 
    87         this( name, null, conn ); 
    88     } 
    89  
    90     public String getName() { 
    91         return name; 
    92     } 
    93  
    94     public synchronized void start() { 
    95         checkNotClosed(); 
    96         if ( !isStartCalled() ) { 
    97             pump = new Thread( this, "network pump" ); 
    98             pump.start(); 
    99         } 
    100     } 
    101  
    102     public synchronized void setListener( final IConnectionListener l ) { 
    103         if ( l != null && isClosed() ) { 
    104             throw new IllegalStateException( "Node is closed - lsitener is useless" ); 
    105         } 
    106         this.listener = l; 
    107     } 
    108  
    109     public void send( final IDatagram data ) { 
    110         checkPumpActive(); 
    111         while ( true ) { 
    112             //áëîêèðóåì this ÷òîáû íàñ íå çàêðûëè íåâîâðåìÿ 
    113             synchronized ( this ) { 
    114                 checkConnected(); 
    115                 try { 
    116                     synchronized ( postQueue ) { 
    117                         //áëîêèðóåì î÷åðåäü, ÷òîáû ïðåäóïðåäèòü åå èçìåíåíèÿ 
    118                         for ( int i = 0; i < postQueue.length; i++ ) { 
    119                             if ( postQueue[i] == null ) { 
    120                                 postQueue[i] = data; 
    121                                 return; 
    122                             } 
    123                         } 
    124                     } 
    125                 } finally { 
    126                     notifyAll();//push pump to run 
    127                 } 
    128             } 
    129             //åñëè î÷åðåäü ïåðåïîëíåíà -- âûíóæäåíû æäàòü 
    130             synchronized ( queueOverloadedLock ) { 
    131                 try { 
    132                     queueOverloadedLock.wait( 250 ); 
    133                 } catch ( InterruptedException e ) { 
    134                     //e.printStackTrace(); 
    135                 } 
    136             } 
    137         } 
    138     } 
    139  
    140     public void run() { 
    141         try { 
    142             synchronized ( this ) { 
    143                 if ( isClosed() ) { 
    144                     return; 
    145                 } 
    146                 openPipeline(); 
    147             } 
    148             if ( listener != null ) { 
    149                 listener.connected(); 
    150             } 
    151             final GenericDatagram data = new GenericDatagram(); 
    152             while ( !isClosed() && !quitPump ) { 
    153                 synchronized ( this ) { 
    154                     final int timeout; 
    155                     //îòïðàâëÿåì íåîòïðàâëåííîå 
    156                     synchronized ( postQueue ) { 
    157                         for ( int i = 0; i < postQueue.length; i++ ) { 
    158                             final IDatagram packet = postQueue[i]; 
    159                             if ( packet != null ) { 
    160                                 data.setWrapped( packet ); 
    161                                 data.write( out ); 
    162                                 postQueue[i] = null; 
    163                                 if ( listener != null ) { 
    164                                     listener.wasSent( packet ); 
    165                                 } 
    166                             } 
    167                         } 
    168                     } 
    169                     synchronized ( queueOverloadedLock ) { 
    170                         //îïîâåùàåì, ÷òî î÷åðåäü îñâîáîäèëàñü 
    171                         queueOverloadedLock.notifyAll(); 
    172                     } 
    173                     //÷èòàåì íåäî÷èòàííîå 
    174                     if ( in.available() > 0 ) { 
    175                         data.read( in ); 
    176                         if ( listener != null ) { 
    177                             listener.received( data.wrapped() ); 
    178                         } 
    179                         timeout = 50; 
    180                     } else { 
    181                         timeout = 250; 
    182                     } 
    183                     try { 
    184                         wait( timeout ); 
    185                     } catch ( InterruptedException e ) { 
    186                     } 
    187                 } 
    188             } 
    189         } catch ( Throwable e ) { 
    190             e.printStackTrace(); 
    191             lastError = e; 
    192         } finally { 
    193             pump = null; 
    194             closeImpl(); 
    195         } 
    196     } 
    197  
    198     public void close( final boolean safe ) { 
    199         if ( isClosed() ) { 
    200             return; 
    201         } 
    202         if ( safe ) { 
    203             askPumpToQuit(); 
    204         } else { 
    205             closeImpl(); 
    206         } 
    207     } 
    208  
    209     public Throwable getError() { 
    210         return null; 
    211     } 
    212  
    213     private void closeImpl() { 
    214         try { 
    215             if ( in != null ) { 
    216                 try { 
    217                     in.close(); 
    218                 } catch ( IOException e ) { 
    219                     e.printStackTrace(); 
    220                 } finally { 
    221                     in = null; 
    222                 } 
    223             } 
    224             if ( out != null ) { 
    225                 try { 
    226                     out.close(); 
    227                 } catch ( IOException e ) { 
    228                     e.printStackTrace(); 
    229                 } finally { 
    230                     out = null; 
    231                 } 
    232             } 
    233             if ( connection != null ) { 
    234                 try { 
    235                     connection.close(); 
    236                 } catch ( IOException e ) { 
    237                     e.printStackTrace(); 
    238                 } finally { 
    239                     connection = null; 
    240                 } 
    241             } 
    242  
    243             if ( pump != null && pump.isAlive() ) { 
    244                 pump.interrupt(); 
    245                 if ( pump != Thread.currentThread() ) { 
    246                     try { 
    247                         pump.join(); 
    248                     } catch ( InterruptedException e ) { 
    249                         e.printStackTrace(); 
    250                     } 
    251                 } 
    252             } 
    253             for ( int i = 0; i < postQueue.length; i++ ) { 
    254                 postQueue[i] = null; 
    255             } 
    256         } finally { 
    257             pump = null; 
    258             device = null; 
    259             if ( listener != null ) { 
    260                 listener.closed(); 
    261             } 
    262         } 
    263     } 
    264  
    265     private void openPipeline() throws IOException { 
    266         if ( connection == null ) { 
    267             final String addr = getBluetoothURL( device ); 
    268             connection = ( StreamConnection )Connector.open( addr, Connector.READ_WRITE, true ); 
    269         } 
    270         if ( in == null ) { 
    271             try { 
    272                 in = connection.openInputStream(); 
    273             } catch ( IOException ex ) { 
    274                 ex.printStackTrace(); 
    275                 throw ex; 
    276                 //throw new IOException( "Can't open input stream:" + ex.getMessage() ); 
    277             } 
    278         } 
    279         if ( out == null ) { 
    280             try { 
    281                 out = connection.openOutputStream(); 
    282             } catch ( IOException ex ) { 
    283                 ex.printStackTrace(); 
    284                 throw ex; 
    285                 //throw new IOException( "Can't open output stream:" + ex.getMessage() ); 
    286             } 
    287         } 
    288     } 
    289  
    290     public String toString() { 
    291         return getName(); 
    292     } 
    293  
    294     private void checkNotClosed() { 
    295         if ( isClosed() ) { 
    296             throw new IllegalStateException( "Node already closed" ); 
    297         } 
    298     } 
    299  
    300     private void checkPumpActive() { 
    301         checkNotClosed(); 
    302         if ( !isStartCalled() ) { 
    303             throw new IllegalStateException( ".start() not called" ); 
    304         } 
    305     } 
    306  
    307     private void checkConnected() { 
    308         checkNotClosed(); 
    309         checkPumpActive(); 
    310         if ( !isConnected() ) { 
    311             throw new IllegalStateException( "Node not connected" ); 
    312         } 
    313     } 
    314  
    315     private boolean isClosed() { 
    316         return device == null; 
    317     } 
    318  
    319     private void askPumpToQuit() { 
    320         synchronized ( this ) { 
    321             quitPump = true; 
    322             notifyAll(); 
    323         } 
    324         //device = null; 
    325     } 
    326  
    327     private boolean isStartCalled() { 
    328         return pump != null; 
    329     } 
    330  
    331     private boolean isConnected() { 
    332         return connection != null && in != null && out != null; 
    333     } 
    334  
    335  
    336     private static String getBluetoothURL( final RemoteDevice device ) { 
    337         return BTRemote.BTSPP_SCHEME + device.getBluetoothAddress() + ":" + BT_STREAM; 
    338     } 
     46        private final Object queueOverloadedLock = new Object(); 
     47        private final IDatagram[] postQueue = new IDatagram[2]; 
     48 
     49 
     50        public BTNode( final RemoteDevice device ) throws IOException { 
     51                this( device, null ); 
     52        } 
     53 
     54        public BTNode( final StreamConnection conn ) throws IOException { 
     55                this( null, null, conn ); 
     56        } 
     57 
     58        public BTNode( final RemoteDevice device, 
     59                       final StreamConnection conn ) throws IOException { 
     60                this( null, device, conn ); 
     61        } 
     62 
     63        public BTNode( final String name, 
     64                       final RemoteDevice device, 
     65                       final StreamConnection conn ) throws IOException { 
     66                if( device == null && conn == null ) { 
     67                        throw new IllegalArgumentException( "No-no-no, David Blain! device=null && conn=null" ); 
     68                } 
     69 
     70                if( device == null ) { 
     71                        this.device = RemoteDevice.getRemoteDevice( conn ); 
     72                } else { 
     73                        this.device = device; 
     74                } 
     75                if( name == null ) { 
     76                        try { 
     77                                this.name = this.device.getFriendlyName( true ); 
     78                        } catch( IOException e ) { 
     79                                e.printStackTrace(); 
     80                                this.name = null; 
     81                        } 
     82                } else { 
     83                        this.name = name; 
     84                } 
     85                connection = conn; 
     86        } 
     87 
     88        public BTNode( final String name, 
     89                       final StreamConnection conn ) throws IOException { 
     90                this( name, null, conn ); 
     91        } 
     92 
     93        public String getName() { 
     94                return name; 
     95        } 
     96 
     97        public synchronized void start() { 
     98                checkNotClosed(); 
     99                if( !isStartCalled() ) { 
     100                        pump = new Thread( this, "network pump" ); 
     101                        pump.start(); 
     102                } 
     103        } 
     104 
     105        public synchronized void setListener( final IConnectionListener l ) { 
     106                if( l != null && isClosed() ) { 
     107                        throw new IllegalStateException( "Node is closed - lsitener is useless" ); 
     108                } 
     109                this.listener = l; 
     110        } 
     111 
     112        public void send( final IDatagram data ) { 
     113                checkPumpActive(); 
     114                while( true ) { 
     115                        //áëîêèðóåì this ÷òîáû íàñ íå çàêðûëè íåâîâðåìÿ 
     116                        synchronized( this ) { 
     117                                checkConnected(); 
     118                                try { 
     119                                        synchronized( postQueue ) { 
     120                                                //áëîêèðóåì î÷åðåäü, ÷òîáû ïðåäóïðåäèòü åå èçìåíåíèÿ 
     121                                                for( int i = 0; i < postQueue.length; i++ ) { 
     122                                                        if( postQueue[i] == null ) { 
     123                                                                postQueue[i] = data; 
     124                                                                return; 
     125                                                        } 
     126                                                } 
     127                                        } 
     128                                } finally { 
     129                                        notifyAll();//push pump to run 
     130                                } 
     131                        } 
     132                        //åñëè î÷åðåäü ïåðåïîëíåíà -- âûíóæäåíû æäàòü 
     133                        synchronized( queueOverloadedLock ) { 
     134                                try { 
     135                                        queueOverloadedLock.wait( 250 ); 
     136                                } catch( InterruptedException e ) { 
     137                                        //e.printStackTrace(); 
     138                                } 
     139                        } 
     140                } 
     141        } 
     142 
     143        public void run() { 
     144                try { 
     145                        synchronized( this ) { 
     146                                if( isClosed() ) { 
     147                                        return; 
     148                                } 
     149                                openPipeline(); 
     150                        } 
     151                        if( listener != null ) { 
     152                                listener.connected(); 
     153                        } 
     154                        final GenericDatagram data = new GenericDatagram(); 
     155                        while( !isClosed() && !quitPump ) { 
     156                                synchronized( this ) { 
     157                                        final int timeout; 
     158                                        //îòïðàâëÿåì íåîòïðàâëåííîå 
     159                                        synchronized( postQueue ) { 
     160                                                for( int i = 0; i < postQueue.length; i++ ) { 
     161                                                        final IDatagram packet = postQueue[i]; 
     162                                                        if( packet != null ) { 
     163                                                                data.setWrapped( packet ); 
     164                                                                data.write( out ); 
     165                                                                postQueue[i] = null; 
     166                                                                if( listener != null ) { 
     167                                                                        listener.wasSent( packet ); 
     168                                                                } 
     169                                                        } 
     170                                                } 
     171                                        } 
     172                                        synchronized( queueOverloadedLock ) { 
     173                                                //îïîâåùàåì, ÷òî î÷åðåäü îñâîáîäèëàñü 
     174                                                queueOverloadedLock.notifyAll(); 
     175                                        } 
     176                                        //÷èòàåì íåäî÷èòàííîå 
     177                                        if( in.available() > 0 ) { 
     178                                                data.read( in ); 
     179                                                if( listener != null ) { 
     180                                                        listener.received( data.wrapped() ); 
     181                                                } 
     182                                                timeout = 50; 
     183                                        } else { 
     184                                                timeout = 250; 
     185                                        } 
     186                                        try { 
     187                                                wait( timeout ); 
     188                                        } catch( InterruptedException e ) { 
     189                                        } 
     190                                } 
     191                        } 
     192                } catch( Throwable e ) { 
     193                        e.printStackTrace(); 
     194                        lastError = e; 
     195                } finally { 
     196                        pump = null; 
     197                        closeImpl(); 
     198                } 
     199        } 
     200 
     201        public void close( final boolean safe ) { 
     202                if( isClosed() ) { 
     203                        return; 
     204                } 
     205                if( safe ) { 
     206                        askPumpToQuit(); 
     207                } else { 
     208                        closeImpl(); 
     209                } 
     210        } 
     211 
     212        public Throwable getError() { 
     213                return null; 
     214        } 
     215 
     216        private void closeImpl() { 
     217                try { 
     218                        if( in != null ) { 
     219                                try { 
     220                                        in.close(); 
     221                                } catch( IOException e ) { 
     222                                        e.printStackTrace(); 
     223                                } finally { 
     224                                        in = null; 
     225                                } 
     226                        } 
     227                        if( out != null ) { 
     228                                try { 
     229                                        out.close(); 
     230                                } catch( IOException e ) { 
     231                                        e.printStackTrace(); 
     232                                } finally { 
     233                                        out = null; 
     234                                } 
     235                        } 
     236                        if( connection != null ) { 
     237                                try { 
     238                                        connection.close(); 
     239                                } catch( IOException e ) { 
     240                                        e.printStackTrace(); 
     241                                } finally { 
     242                                        connection = null; 
     243                                } 
     244                        } 
     245 
     246                        if( pump != null && pump.isAlive() ) { 
     247                                pump.interrupt(); 
     248                                if( pump != Thread.currentThread() ) { 
     249                                        try { 
     250                                                pump.join(); 
     251                                        } catch( InterruptedException e ) { 
     252                                                e.printStackTrace(); 
     253                                        } 
     254                                } 
     255                        } 
     256                        for( int i = 0; i < postQueue.length; i++ ) { 
     257                                postQueue[i] = null; 
     258                        } 
     259                } finally { 
     260                        pump = null; 
     261                        device = null; 
     262                        if( listener != null ) { 
     263                                listener.closed(); 
     264                        } 
     265                } 
     266        } 
     267 
     268        private void openPipeline() throws IOException { 
     269                if( connection == null ) { 
     270                        final String addr = getBluetoothURL( device ); 
     271                        connection = ( StreamConnection ) Connector.open( addr, Connector.READ_WRITE, true ); 
     272                } 
     273                if( in == null ) { 
     274                        try { 
     275                                in = connection.openInputStream(); 
     276                        } catch( IOException ex ) { 
     277                                ex.printStackTrace(); 
     278                                throw ex; 
     279                                //throw new IOException( "Can't open input stream:" + ex.getMessage() ); 
     280                        } 
     281                } 
     282                if( out == null ) { 
     283                        try { 
     284                                out = connection.openOutputStream(); 
     285                        } catch( IOException ex ) { 
     286                                ex.printStackTrace(); 
     287                                throw ex; 
     288                                //throw new IOException( "Can't open output stream:" + ex.getMessage() ); 
     289                        } 
     290                } 
     291        } 
     292 
     293        public String toString() { 
     294                return getName(); 
     295        } 
     296 
     297        private void checkNotClosed() { 
     298                if( isClosed() ) { 
     299                        throw new IllegalStateException( "Node already closed" ); 
     300                } 
     301        } 
     302 
     303        private void checkPumpActive() { 
     304                checkNotClosed(); 
     305                if( !isStartCalled() ) { 
     306                        throw new IllegalStateException( ".start() not called" ); 
     307                } 
     308        } 
     309 
     310        private void checkConnected() { 
     311                checkNotClosed(); 
     312                checkPumpActive(); 
     313                if( !isConnected() ) { 
     314                        throw new IllegalStateException( "Node not connected" ); 
     315                } 
     316        } 
     317 
     318        private boolean isClosed() { 
     319                return device == null; 
     320        } 
     321 
     322        private void askPumpToQuit() { 
     323                synchronized( this ) { 
     324                        quitPump = true; 
     325                        notifyAll(); 
     326                } 
     327                //device = null; 
     328        } 
     329 
     330        private boolean isStartCalled() { 
     331                return pump != null; 
     332        } 
     333 
     334        private boolean isConnected() { 
     335                return connection != null && in != null && out != null; 
     336        } 
     337 
     338 
     339        private static String getBluetoothURL( final RemoteDevice device ) { 
     340                return BTRemote.BTSPP_SCHEME + device.getBluetoothAddress() + ":" + BT_STREAM; 
     341        } 
    339342} 
  • chess/src/chess/remote/impl/BTRemote.java

    r34 r36  
    2020 */ 
    2121public class BTRemote implements IRemote { 
    22     public static final String BTSPP_SCHEME = "btspp://"; 
    23     public static final String MY_SERVICE_NUMBER = "3B9FA89520078C303355AAA694238F08;name=ChessGameServer"; 
    24  
    25     public static final IRemoteNode[] EMPTY = new IRemoteNode[0]; 
    26  
    27     private final LocalDevice localDevice; 
    28     private final Vector devices = new Vector(); 
    29  
    30     public BTRemote() throws Exception { 
    31         localDevice = LocalDevice.getLocalDevice(); 
    32         fillupCache(); 
    33     } 
    34  
    35     private synchronized void fillupCache() { 
    36         final DiscoveryAgent agent = localDevice.getDiscoveryAgent(); 
    37         final RemoteDevice[] preknownDevices = agent.retrieveDevices( DiscoveryAgent.PREKNOWN ); 
    38         if ( preknownDevices != null ) { 
    39             for ( int i = 0; i < preknownDevices.length; i++ ) { 
    40                 final RemoteDevice device = preknownDevices[i]; 
    41                 devices.addElement( device ); 
    42             } 
    43         } 
    44         final RemoteDevice[] cachedDevices = agent.retrieveDevices( DiscoveryAgent.CACHED ); 
    45         if ( cachedDevices != null ) { 
    46             for ( int i = 0; i < cachedDevices.length; i++ ) { 
    47                 final RemoteDevice device = cachedDevices[i]; 
    48                 devices.addElement( device ); 
    49             } 
    50         } 
    51     } 
    52  
    53     private synchronized void refreshCache() { 
    54         devices.removeAllElements(); 
    55         fillupCache(); 
    56     } 
    57  
    58     public IAsyncProcess waitForIncoming( final IServerListener l ) { 
    59         return new WaitForIncomingThread( localDevice, l ); 
    60     } 
    61  
    62     public IAsyncProcess getAvailable( final boolean refresh, 
    63                                        final IClientListener listener ) { 
    64         final DiscoveryAgent agent = localDevice.getDiscoveryAgent(); 
    65         return new QueryDeviceProcess( this, refresh, agent, listener ); 
     22        public static final String BTSPP_SCHEME = "btspp://"; 
     23        public static final String MY_SERVICE_NUMBER = "3B9FA89520078C303355AAA694238F08;name=ChessGameServer"; 
     24 
     25        public static final IRemoteNode[] EMPTY = new IRemoteNode[0]; 
     26 
     27        private final LocalDevice localDevice; 
     28        private final Vector devices = new Vector(); 
     29 
     30        public BTRemote() throws Exception { 
     31                localDevice = LocalDevice.getLocalDevice(); 
     32                fillupCache(); 
     33        } 
     34 
     35        private synchronized void fillupCache() { 
     36                final DiscoveryAgent agent = localDevice.getDiscoveryAgent(); 
     37                final RemoteDevice[] preknownDevices = agent.retrieveDevices( DiscoveryAgent.PREKNOWN ); 
     38                if( preknownDevices != null ) { 
     39                        for( int i = 0; i < preknownDevices.length; i++ ) { 
     40                                final RemoteDevice device = preknownDevices[i]; 
     41                                devices.addElement( device ); 
     42                        } 
     43                } 
     44                final RemoteDevice[] cachedDevices = agent.retrieveDevices( DiscoveryAgent.CACHED ); 
     45                if( cachedDevices != null ) { 
     46                        for( int i = 0; i < cachedDevices.length; i++ ) { 
     47                                final RemoteDevice device = cachedDevices[i]; 
     48                                devices.addElement( device ); 
     49                        } 
     50                } 
     51        } 
     52 
     53        private synchronized void refreshCache() { 
     54                devices.removeAllElements(); 
     55                fillupCache(); 
     56        } 
     57 
     58        public IAsyncProcess waitForIncoming( final IServerListener l ) { 
     59                return new WaitForIncomingThread( localDevice, l ); 
     60        } 
     61 
     62        public IAsyncProcess getAvailable( final boolean refresh, 
     63                                           final IClientListener listener ) { 
     64                final DiscoveryAgent agent = localDevice.getDiscoveryAgent(); 
     65                return new QueryDeviceProcess( this, refresh, agent, listener ); 
    6666//              try { 
    6767//              } catch( Exception e ) { 
     
    7676//                      return null; 
    7777//              } 
    78     } 
    79  
    80     private synchronized IRemoteNode[] getNodes() { 
    81         if ( devices.isEmpty() ) { 
    82             return EMPTY; 
    83         } 
    84         final int length = devices.size(); 
    85         final IRemoteNode[] nodes = new IRemoteNode[devices.size()]; 
    86         boolean wasFailed = false; 
    87         for ( int i = 0; i < length; i++ ) { 
    88             try { 
    89                 final RemoteDevice device = ( RemoteDevice )devices.elementAt( i ); 
    90                 final BTNode node = new BTNode( device ); 
    91                 nodes[i] = node; 
    92             } catch ( IOException e ) { 
    93                 wasFailed = true; 
    94                 e.printStackTrace(); 
    95             } 
    96         } 
    97         if ( wasFailed ) { 
    98             //óäàëÿåì ïóñòûå ÿ÷åéêè 
    99             final Vector res = new Vector( nodes.length ); 
    100             for ( int i = 0; i < nodes.length; i++ ) { 
    101                 final IRemoteNode node = nodes[i]; 
    102                 if ( node != null ) { 
    103                     res.addElement( node ); 
    104                 } 
    105             } 
    106  
    107             final IRemoteNode[] _nodes = new IRemoteNode[res.size()]; 
    108             res.copyInto( _nodes ); 
    109             return _nodes; 
    110         } else { 
    111             return nodes; 
    112         } 
    113     } 
    114  
    115     private static class WaitForIncomingThread extends BaseAsyncProcess { 
    116         private final LocalDevice localDevice; 
    117         private StreamConnectionNotifier server; 
    118  
    119         public WaitForIncomingThread( final LocalDevice local, 
    120                                       final IServerListener listener ) { 
    121             super( listener ); 
    122             this.localDevice = local; 
    123             start(); 
    124         } 
    125  
    126         public void run() { 
    127             try { 
    128                 localDevice.setDiscoverable( DiscoveryAgent.GIAC ); 
    129                 setStatus( IN_PROCESS ); 
    130                 while ( true ) { 
    131                     server = ( StreamConnectionNotifier )Connector.open( 
    132                             BTSPP_SCHEME + "localhost:" + MY_SERVICE_NUMBER, 
    133                             Connector.READ_WRITE, 
    134                             true 
    135                     ); 
    136                     Util.log.println( "creating server and waiting for incoming" ); 
    137                     try { 
    138                         final IServerListener _listener = ( IServerListener )listener; 
    139                         while ( server != null ) { 
    140                             // Îæèäàåì âõîäÿùåå ïîòîêîâîå ñîåäèíåíèå 
    141                             final StreamConnection conn = server.acceptAndOpen(); 
    142                             Util.log.println( "accepted incoming: " + conn ); 
    143                             final BTNode client = new BTNode( conn ); 
    144                             if ( _listener.incoming( client ) ) { 
    145                                 //åñëè êëèåíò ïðèíÿò -- âûõîäèì (èãðà äîïóñêàåò òîëüêî îäíîãî ñîïåðíèêà) 
    146                                 Util.log.println( "client accepted -> close server" ); 
    147                                 setStatus( SUCCEEDED ); 
    148                                 return; 
    149                             } 
    150                             client.close( true ); 
    151                         } 
    152                     } catch ( InterruptedIOException ex ) { 
    153                         //setStatus( INTERRUPTED ); 
    154                         //return; 
    155                         throw ex; 
    156                     } catch ( IOException ex ) { 
    157                         Util.log.println( "server got error -- trying to recreate server connection" ); 
    158                         ex.printStackTrace(); 
    159                     } finally { 
    160                         if ( server != null ) { 
    161                             try { 
    162                                 server.close(); 
    163                                 server = null; 
    164                             } catch ( IOException e ) { 
    165                                 e.printStackTrace(); 
    166                             } 
    167                         } 
    168                     } 
    169                 } 
    170             } catch ( Throwable ex ) { 
    171                 //åñëè íå óäàëîñü îòêðûòü ñîåäèíåíèå -- ýòî ïèçäåö. óõîäèì 
    172                 //...íå óäàëîñü îïóáëèêîâàòü óñòðîéñòâî -- ïèçäåö, óõîäèì 
    173                 if ( isQueryInterrupt() ) { 
    174                     Util.log.println( "server was closed: " + ex.getMessage() ); 
    175                     setStatus( INTERRUPTED ); 
    176                 } else { 
    177                     setStatus( FAILED, ex ); 
    178                 } 
    179             } finally { 
    180                 listener.finished( null ); 
    181                 Util.log.println( "server stopped" ); 
    182             } 
    183         } 
    184  
    185         public void stop( final int waitMillis ) { 
    186             setQueryInterrupt(); 
    187             if ( isAlive() ) { 
    188                 if ( server != null ) { 
    189                     try { 
    190                         server.close(); 
    191                         server = null; 
    192                     } catch ( IOException e ) { 
    193                         e.printStackTrace(); 
    194                     } 
    195                 } 
    196                 waitForThread( waitMillis ); 
    197             } 
    198         } 
    199  
    200     } 
    201  
    202     private static class QueryDeviceProcess extends BaseAsyncProcess implements DiscoveryListener { 
    203         private final BTRemote remote; 
    204         private final boolean realQuery; 
    205         private final DiscoveryAgent agent; 
    206  
    207         public QueryDeviceProcess( final BTRemote remote, 
    208                                    final boolean realQuery, 
    209                                    final DiscoveryAgent agent, 
    210                                    final IClientListener listener ) { 
    211             super( listener ); 
    212             this.remote = remote; 
    213             this.agent = agent; 
    214             this.realQuery = realQuery; 
    215             start(); 
    216         } 
    217  
    218         public void run() { 
    219             setStatus( IN_PROCESS ); 
    220  
    221             Util.log.println( "starting query device list" ); 
    222             try { 
    223                 /** 
    224                  * Íåïîíÿòíî, ÿâëÿåòñÿ ëè ýòîò çàïðîñ ñèíõðîííûì, èëè àñèíõðîííûì -- 
    225                  * äîêóìåíòàöèÿ íà ýòîò ñ÷åò ìîë÷èò, à ïðàêòèêà ïîêàçûâàåò, ÷òî 
    226                  * áûâàåò è òàê è ýäàê. Ïîýòîìó ñòðàõóåìñÿ îò íåâåäîìîé õóéíè è 
    227                  * äåëàåì ýòî â îòäåëüíîì ïîòîêå 
    228                  */ 
    229                 if ( realQuery ) { 
    230                     agent.startInquiry( DiscoveryAgent.GIAC, this ); 
    231                 } else { 
    232                     final IRemoteNode[] nodes = remote.getNodes(); 
    233                     setStatus( SUCCEEDED ); 
    234                     listener.finished( nodes ); 
    235                 } 
    236             } catch ( Throwable e ) { 
    237                 if ( isQueryInterrupt() ) { 
    238                     setStatus( INTERRUPTED ); 
    239                 } else { 
    240                     setStatus( FAILED, e ); 
    241                 } 
    242                 listener.finished( null ); 
    243             } 
    244         } 
    245  
    246  
    247         public void stop( final int waitMillis ) { 
    248             setQueryInterrupt(); 
    249             if ( status() == IN_PROCESS ) { 
    250                 if ( realQuery ) { 
    251                     agent.cancelInquiry( this ); 
    252                 } else { 
    253                     interrupt(); 
    254                 } 
    255                 waitForThread( waitMillis ); 
    256             } 
    257         } 
    258  
    259         public void deviceDiscovered( final RemoteDevice btDevice, 
    260                                       final DeviceClass cod ) { 
    261             Util.log.println( "device found:" + btDevice.getBluetoothAddress() ); 
    262         } 
    263  
    264         public void servicesDiscovered( final int transID, 
    265                                         final ServiceRecord[] servRecord ) { 
    266             //Util.log.println( "service found:" + transID ); 
    267         } 
    268  
    269         public void serviceSearchCompleted( final int transID, 
    270                                             final int respCode ) { 
    271  
    272         } 
    273  
    274         public void inquiryCompleted( final int discType ) { 
    275             switch ( discType ) { 
    276                 case INQUIRY_COMPLETED: 
    277                     Util.log.println( "device list query finished" ); 
    278                     remote.refreshCache(); 
    279                     setStatus( SUCCEEDED ); 
    280                     listener.finished( remote.getNodes() ); 
    281                     break; 
    282                 case INQUIRY_TERMINATED: 
    283                     Util.log.println( "device list query interrupted" ); 
    284                     setStatus( INTERRUPTED ); 
    285                     listener.finished( null ); 
    286                     break; 
    287                 case INQUIRY_ERROR: 
    288                     Util.log.println( "device list query failed" ); 
    289                     setStatus( FAILED ); 
    290                     listener.finished( null ); 
    291                     break; 
    292                 default: 
    293                     throw new IllegalStateException( "Unknown type:" + discType ); 
    294             } 
    295         } 
    296     } 
     78        } 
     79 
     80        private synchronized IRemoteNode[] getNodes() { 
     81                if( devices.isEmpty() ) { 
     82                        return EMPTY; 
     83                } 
     84                final int length = devices.size(); 
     85                final IRemoteNode[] nodes = new IRemoteNode[devices.size()]; 
     86                boolean wasFailed = false; 
     87                for( int i = 0; i < length; i++ ) { 
     88                        try { 
     89                                final RemoteDevice device = ( RemoteDevice ) devices.elementAt( i ); 
     90                                final BTNode node = new BTNode( device ); 
     91                                nodes[i] = node; 
     92                        } catch( IOException e ) { 
     93                                wasFailed = true; 
     94                                e.printStackTrace(); 
     95                        } 
     96                } 
     97                if( wasFailed ) { 
     98                        //óäàëÿåì ïóñòûå ÿ÷åéêè 
     99                        final Vector res = new Vector( nodes.length ); 
     100                        for( int i = 0; i < nodes.length; i++ ) { 
     101                                final IRemoteNode node = nodes[i]; 
     102                                if( node != null ) { 
     103                                        res.addElement( node ); 
     104                                } 
     105                        } 
     106 
     107                        final IRemoteNode[] _nodes = new IRemoteNode[res.size()]; 
     108                        res.copyInto( _nodes ); 
     109                        return _nodes; 
     110                } else { 
     111                        return nodes; 
     112                } 
     113        } 
     114 
     115        private static class WaitForIncomingThread extends BaseAsyncProcess { 
     116                private final LocalDevice localDevice; 
     117                private StreamConnectionNotifier server; 
     118 
     119                public WaitForIncomingThread( final LocalDevice local, 
     120                                              final IServerListener listener ) { 
     121                        super( listener ); 
     122                        this.localDevice = local; 
     123                        start(); 
     124                } 
     125 
     126                public void run() { 
     127                        try { 
     128                                localDevice.setDiscoverable( DiscoveryAgent.GIAC ); 
     129                                setStatus( IN_PROCESS ); 
     130                                while( true ) { 
     131                                        server = ( StreamConnectionNotifier ) Connector.open( 
     132                                                        BTSPP_SCHEME + "localhost:" + MY_SERVICE_NUMBER, 
     133                                                        Connector.READ_WRITE, 
     134                                                        true 
     135                                        ); 
     136                                        Util.log.println( "creating server and waiting for incoming" ); 
     137                                        try { 
     138                                                final IServerListener _listener = ( IServerListener ) listener; 
     139                                                while( server != null ) { 
     140                                                        // Îæèäàåì âõîäÿùåå ïîòîêîâîå ñîåäèíåíèå 
     141                                                        final StreamConnection conn = server.acceptAndOpen(); 
     142                                                        Util.log.println( "accepted incoming: " + conn ); 
     143                                                        final BTNode client = new BTNode( conn ); 
     144                                                        if( _listener.incoming( client ) ) { 
     145                                                                //åñëè êëèåíò ïðèíÿò -- âûõîäèì (èãðà äîïóñêàåò òîëüêî îäíîãî ñîïåðíèêà) 
     146                                                                Util.log.println( "client accepted -> close server" ); 
     147                                                                setStatus( SUCCEEDED ); 
     148                                                                return; 
     149                                                        } 
     150                                                        client.close( true ); 
     151                                                } 
     152                                        } catch( InterruptedIOException ex ) { 
     153                                                //setStatus( INTERRUPTED ); 
     154                                                //return; 
     155                                                throw ex; 
     156                                        } catch( IOException ex ) { 
     157                                                Util.log.println( "server got error -- trying to recreate server connection" ); 
     158                                                ex.printStackTrace(); 
     159                                        } finally { 
     160                                                if( server != null ) { 
     161                                                        try { 
     162                                                                server.close(); 
     163                                                                server = null; 
     164                                                        } catch( IOException e ) { 
     165                                                                e.printStackTrace(); 
     166                                                        } 
     167                                                } 
     168                                        } 
     169                                } 
     170                        } catch( Throwable ex ) { 
     171                                //åñëè íå óäàëîñü îòêðûòü ñîåäèíåíèå -- ýòî ïèçäåö. óõîäèì 
     172                                //...íå óäàëîñü îïóáëèêîâàòü óñòðîéñòâî -- ïèçäåö, óõîäèì 
     173                                if( isQueryInterrupt() ) { 
     174                                        Util.log.println( "server was closed: " + ex.getMessage() ); 
     175                                        setStatus( INTERRUPTED ); 
     176                                } else { 
     177                                        setStatus( FAILED, ex ); 
     178                                } 
     179                        } finally { 
     180                                listener.finished( null ); 
     181                                Util.log.println( "server stopped" ); 
     182                        } 
     183                } 
     184 
     185                public void stop( final int waitMillis ) { 
     186                        setQueryInterrupt(); 
     187                        if( isAlive() ) { 
     188                                if( server != null ) { 
     189                                        try { 
     190                                                server.close(); 
     191                                                server = null; 
     192                                        } catch( IOException e ) { 
     193                                                e.printStackTrace(); 
     194                                        } 
     195                                } 
     196                                waitForThread( waitMillis ); 
     197                        } 
     198                } 
     199 
     200        } 
     201 
     202        private static class QueryDeviceProcess extends BaseAsyncProcess implements DiscoveryListener { 
     203                private final BTRemote remote; 
     204                private final boolean realQuery; 
     205                private final DiscoveryAgent agent; 
     206 
     207                private boolean finishedEventWasPost = false; 
     208 
     209                public QueryDeviceProcess( final BTRemote remote, 
     210                                           final boolean realQuery, 
     211                                           final DiscoveryAgent agent, 
     212                                           final IClientListener listener ) { 
     213                        super( listener ); 
     214                        this.remote = remote; 
     215                        this.agent = agent; 
     216                        this.realQuery = realQuery; 
     217                        start(); 
     218                } 
     219 
     220                public void run() { 
     221                        setStatus( IN_PROCESS ); 
     222 
     223                        Util.log.println( "starting query device list" ); 
     224                        try { 
     225                                /** 
     226                                 * Íåïîíÿòíî, ÿâëÿåòñÿ ëè ýòîò çàïðîñ ñèíõðîííûì, èëè àñèíõðîííûì -- 
     227                                 * äîêóìåíòàöèÿ íà ýòîò ñ÷åò ìîë÷èò, à ïðàêòèêà ïîêàçûâàåò, ÷òî 
     228                                 * áûâàåò è òàê è ýäàê. Ïîýòîìó ñòðàõóåìñÿ îò íåâåäîìîé õóéíè è 
     229                                 * äåëàåì ýòî â îòäåëüíîì ïîòîêå 
     230                                 */ 
     231                                if( realQuery ) { 
     232                                        agent.startInquiry( DiscoveryAgent.GIAC, this ); 
     233                                } else { 
     234                                        final IRemoteNode[] nodes = remote.getNodes(); 
     235                                        setStatus( SUCCEEDED ); 
     236                                        ensureListenerInformed( nodes ); 
     237                                } 
     238                        } catch( Throwable e ) { 
     239                                if( isQueryInterrupt() ) { 
     240                                        setStatus( INTERRUPTED ); 
     241                                } else { 
     242                                        setStatus( FAILED, e ); 
     243                                } 
     244                                ensureListenerInformed( null ); 
     245                        } finally { 
     246//                              synchronized( this ) { 
     247//                                      notifyAll(); 
     248//                              } 
     249                        } 
     250                } 
     251 
     252                private synchronized void ensureListenerInformed( final IRemoteNode[] nodes ) { 
     253                        if( !finishedEventWasPost ) { 
     254                                listener.finished( nodes ); 
     255                                finishedEventWasPost = true; 
     256                        } 
     257                } 
     258 
     259 
     260                public void stop( final int waitMillis ) { 
     261                        setQueryInterrupt(); 
     262                        if( status() == IN_PROCESS ) { 
     263                                if( realQuery ) { 
     264                                        agent.cancelInquiry( this ); 
     265                                } else { 
     266                                        interrupt(); 
     267                                } 
     268                                waitForThread( waitMillis ); 
     269                        } 
     270                        if( status() == IN_PROCESS ) { 
     271                                setStatus( INTERRUPTED ); 
     272                        } 
     273                        ensureListenerInformed( null ); 
     274                } 
     275 
     276                public void deviceDiscovered( final RemoteDevice btDevice, 
     277                                              final DeviceClass cod ) { 
     278                        Util.log.println( "device found:" + btDevice.getBluetoothAddress() ); 
     279                } 
     280 
     281                public void servicesDiscovered( final int transID, 
     282                                                final ServiceRecord[] servRecord ) { 
     283                        //Util.log.println( "service found:" + transID ); 
     284                } 
     285 
     286                public void serviceSearchCompleted( final int transID, 
     287                                                    final int respCode ) { 
     288 
     289                } 
     290 
     291                public void inquiryCompleted( final int discType ) { 
     292                        remote.refreshCache(); 
     293                        switch( discType ) { 
     294                                case INQUIRY_COMPLETED: 
     295                                        Util.log.println( "device list query finished" ); 
     296                                        setStatus( SUCCEEDED ); 
     297                                        ensureListenerInformed( remote.getNodes() ); 
     298                                        break; 
     299                                case INQUIRY_TERMINATED: 
     300                                        Util.log.println( "device list query interrupted" ); 
     301                                        setStatus( INTERRUPTED ); 
     302                                        ensureListenerInformed( null ); 
     303                                        break; 
     304                                case INQUIRY_ERROR: 
     305                                        Util.log.println( "device list query failed" ); 
     306                                        setStatus( FAILED ); 
     307                                        ensureListenerInformed( null ); 
     308                                        break; 
     309                                default: 
     310                                        setStatus( FAILED ); 
     311                                        ensureListenerInformed( null ); 
     312                                        throw new IllegalStateException( "Unknown type:" + discType ); 
     313                        } 
     314                } 
     315        } 
    297316} 
  • chess/src/chess/ui/ChessMIDlet.java

    r34 r36  
    202202                                break; 
    203203                            case IAsyncProcess.FAILED: 
    204                                 final Alert alert = new Alert( 
    205                                         "Error", 
    206                                         "Error in starting server", 
    207                                         null, 
    208                                         AlertType.ERROR 
     204                                final Alert alert = Util.createErrorDialog(  
     205                                        "Error in starting server" 
    209206                                ); 
    210207                                display.setCurrent( alert, startForm ); 
  • chess/src/chess/ui/JoinGameScreen.java

    r34 r36  
    44 
    55import chess.MSG; 
     6import chess.Util; 
     7import chess.remote.IAsyncProcess; 
    68import chess.remote.IClientListener; 
    79import chess.remote.IRemoteNode; 
    8 import chess.remote.IAsyncProcess; 
    910 
    1011/** 
     
    1516 */ 
    1617public class JoinGameScreen extends BaseListScreen 
    17         implements IChoiceListener, IClientListener, Runnable { 
    18     //private final ChessMIDlet midlet; 
     18                implements IChoiceListener, IClientListener { 
     19        //private final ChessMIDlet midlet; 
    1920 
    20     private IRemoteNode[] nodes; 
    21     private boolean force; 
     21        private IRemoteNode[] nodes; 
     22        private boolean force; 
    2223 
    23     private final Alert nothingFoundAlert = new Alert( 
    24             MSG.getMessage( "join-game.no-server-found.title" ), 
    25             MSG.getMessage( "join-game.no-server-found.message" ), 
    26             null, 
    27             AlertType.INFO 
    28     ); 
     24        private final Alert nothingFoundAlert = new Alert( 
     25                        MSG.getMessage( "join-game.no-server-found.title" ), 
     26                        MSG.getMessage( "join-game.no-server-found.message" ), 
     27                        null, 
     28                        AlertType.INFO 
     29        ); 
    2930 
    30     private final Alert scanningNetworkAlert = new Alert( 
    31             MSG.getMessage( "join-game.scanning-network.title" ), 
    32             MSG.getMessage( "join-game.scanning-network.message" ), 
    33             null, 
    34             AlertType.INFO 
    35     ); 
     31        private final Alert scanningNetworkAlert = new Alert( 
     32                        MSG.getMessage( "join-game.scanning-network.title" ), 
     33                        MSG.getMessage( "join-game.scanning-network.message" ), 
     34                        null, 
     35                        AlertType.INFO 
     36        ); 
    3637 
    37     private IAsyncProcess asyncProcess; 
     38        private IAsyncProcess asyncProcess; 
    3839 
    39     public JoinGameScreen( final ChessMIDlet midlet ) { 
    40         super( midlet, MSG.getMessage( "join-game.title" ) ); 
     40        public JoinGameScreen( final ChessMIDlet midlet ) { 
     41                super( midlet, MSG.getMessage( "join-game.title" ) ); 
    4142 
    42         scanningNetworkAlert.setTimeout( Alert.FOREVER ); 
    43         scanningNetworkAlert.addCommand( midlet.cancelCommand ); 
    44         scanningNetworkAlert.setCommandListener( this ); 
     43                scanningNetworkAlert.setTimeout( Alert.FOREVER ); 
     44                scanningNetworkAlert.addCommand( midlet.cancelCommand ); 
     45                scanningNetworkAlert.setCommandListener( this ); 
    4546 
    46         addCommand( midlet.refreshCommand ); 
    47         addCommand( midlet.backCommand ); 
     47                addCommand( midlet.refreshCommand ); 
     48                addCommand( midlet.backCommand ); 
    4849 
    49         setChoiceListener( this ); 
    50     } 
     50                setChoiceListener( this ); 
     51        } 
    5152 
    52     public void run() { 
    53         refresh( true ); 
    54     } 
     53//      public void run() { 
     54//              refresh( true ); 
     55//      } 
    5556 
    56     public void refresh( final boolean force ) { 
    57         this.force = force; 
    58         midlet.display.setCurrent( scanningNetworkAlert ); 
    59         ensureSearcherClosed(); 
    60         asyncProcess = midlet.getRemoteManager().getAvailable( this.force, this ); 
    61     } 
     57        public void refresh( final boolean force ) { 
     58                this.force = force; 
     59                ensureSearcherClosed(); 
     60                midlet.display.setCurrent( scanningNetworkAlert ); 
     61                asyncProcess = midlet.getRemoteManager().getAvailable( this.force, this ); 
     62        } 
    6263 
    63     public void finished( final Object res ) { 
    64         final IRemoteNode[] servers = ( IRemoteNode[] )res; 
    65         removeAllItems(); 
    66         nodes = servers; 
     64        public void finished( final Object res ) { 
     65                final IRemoteNode[] servers = ( IRemoteNode[] ) res; 
     66                removeAllItems(); 
     67                nodes = servers; 
    6768 
    68         final boolean nothingFound = ( servers == null || servers.length == 0 ); 
    69         if ( nothingFound ) { 
    70             final int status = asyncProcess.status(); 
    71             if ( status == IAsyncProcess.FAILED ) { 
    72                 final Throwable e = asyncProcess.getError(); 
    73                 if ( e != null ) { 
    74                     final Alert alert = new Alert( "Error", e.getMessage(), null, AlertType.ERROR ); 
    75                     midlet.display.setCurrent( alert, this ); 
    76                 } 
    77             } else if ( status == IAsyncProcess.INTERRUPTED ) { 
    78                 final Alert alert = new Alert( 
    79                         "Warning", 
    80                         "Search interrupted", 
    81                         null, 
    82                         AlertType.INFO 
    83                 ); 
    84                 midlet.display.setCurrent( alert, this ); 
    85             } else if ( force ) { 
    86                 //åñëè èñêàëè â ñåòè è íè÷åãî íå íàøëè -- íå ñóäüáà 
    87                 midlet.display.setCurrent( nothingFoundAlert, this ); 
    88             } else { 
    89                 //åñëè èñêàëè â êýøå... 
    90                 //...è íèõåðà íå íàøëè -- ïðèäåòñÿ îïðîñèòü ñåòü è îáíîâèòü êýø 
    91                 /** 
    92                  * îïðîñ äåëàåì ïðèíóäèòåëüíî â EDT, ÷òîáû èçáåæàòü deadlock'îâ 
    93                  * è, çàîäíî, äàòü îáíîâèòüñÿ ýêðàíó 
    94                  */ 
    95                 //midlet.display.callSerially( this ); 
    96                 refresh( true ); 
    97             } 
    98         } else { 
    99             for ( int i = 0; i < nodes.length; i++ ) { 
    100                 final IRemoteNode node = nodes[i]; 
    101                 addItem( node.getName() ); 
    102             } 
    103             midlet.display.setCurrent( this ); 
    104         } 
    105     } 
     69                final boolean nothingFound = ( servers == null || servers.length == 0 ); 
     70                if( nothingFound ) { 
     71                        final int status = asyncProcess.status(); 
     72                        if( status == IAsyncProcess.FAILED ) { 
     73                                final Throwable e = asyncProcess.getError(); 
     74                                if( e != null ) { 
     75                                        final Alert alert = Util.createErrorDialog( e ); 
     76                                        midlet.display.setCurrent( alert, this ); 
     77                                } 
     78                        } else if( status == IAsyncProcess.INTERRUPTED ) { 
     79                                final Alert alert = new Alert( 
     80                                                MSG.getMessage( "alert.warning" ), 
     81                                                MSG.getMessage( "join-game.search-interrupted.message" ), 
     82                                                null, 
     83                                                AlertType.INFO 
     84                                ); 
     85                                midlet.display.setCurrent( alert, this ); 
     86                        } else if( force ) { 
     87                                //åñëè èñêàëè â ñåòè è íè÷åãî íå íàøëè -- íå ñóäüáà 
     88                                midlet.display.setCurrent( nothingFoundAlert, this ); 
     89                        } else { 
     90                                //åñëè èñêàëè â êýøå... 
     91                                //...è íèõåðà íå íàøëè -- ïðèäåòñÿ îïðîñèòü ñåòü è îáíîâèòü êýø 
     92                                refresh( true ); 
     93                        } 
     94                } else { 
     95                        for( int i = 0; i < nodes.length; i++ ) { 
     96                                final IRemoteNode node = nodes[i]; 
     97                                addItem( node.getName() ); 
     98                        } 
     99                        midlet.display.setCurrent( this ); 
     100                } 
     101        } 
    106102 
    107     public void commandAction( final Command command, 
    108                                final Displayable displayable ) { 
    109         if ( displayable == scanningNetworkAlert ) { 
    110             if ( command == midlet.cancelCommand ) { 
    111                 ensureSearcherClosed(); 
    112             } 
    113         } 
    114         super.commandAction( command, displayable ); 
    115     } 
     103        public void commandAction( final Command command, 
     104                                   final Displayable displayable ) { 
     105                if( displayable == scanningNetworkAlert ) { 
     106                        if( command == midlet.cancelCommand ) { 
     107                                ensureSearcherClosed(); 
     108//                              scanningNetworkAlert.setString( "Cancelled" ); 
     109                        } 
     110                } 
     111                super.commandAction( command, displayable ); 
     112        } 
    116113 
    117     public void choosed( final Command c, 
    118                          final int selectedIndex ) { 
    119         if ( c == getDefaultCommand() ) { 
    120             if ( selectedIndex >= 0 && selectedIndex < nodes.length ) { 
    121                 final IRemoteNode server = nodes[selectedIndex]; 
    122                 midlet.connectToServer( server ); 
    123             } 
    124         } else if ( c == midlet.backCommand ) { 
    125             ensureSearcherClosed(); 
    126             midlet.showStartScreen(); 
    127         } else if ( c == midlet.refreshCommand ) { 
    128             refresh( true ); 
    129         } 
    130     } 
     114        public void choosed( final Command c, 
     115                             final int selectedIndex ) { 
     116                if( c == getDefaultCommand() ) { 
     117                        if( selectedIndex >= 0 && selectedIndex < nodes.length ) { 
     118                                final IRemoteNode server = nodes[selectedIndex]; 
     119                                midlet.connectToServer( server ); 
     120                        } 
     121                } else if( c == midlet.backCommand ) { 
     122                        ensureSearcherClosed(); 
     123                        midlet.showStartScreen(); 
     124                } else if( c == midlet.refreshCommand ) { 
     125                        refresh( true ); 
     126                } 
     127        } 
    131128 
    132     private void ensureSearcherClosed() { 
    133         if ( asyncProcess != null ) { 
    134             asyncProcess.stop( 1000 ); 
    135             //asyncProcess = null; 
    136         } 
    137     } 
     129        private void ensureSearcherClosed() { 
     130                if( asyncProcess != null ) { 
     131                        asyncProcess.stop( 1000 ); 
     132                        //asyncProcess = null; 
     133                } 
     134        } 
    138135} 
  • chess/src/chess/ui/WaitCanvas.java

    r34 r36  
    11package chess.ui; 
    22 
    3 import java.util.TimerTask; 
    4 import java.util.Timer; 
     3import java.util.*; 
    54import javax.microedition.lcdui.Canvas; 
     5import javax.microedition.lcdui.Displayable; 
    66import javax.microedition.lcdui.Graphics; 
    7 import javax.microedition.lcdui.Displayable; 
    87 
    98import chess.remote.IAsyncProcessListener; 
     
    1615 */ 
    1716public class WaitCanvas extends Canvas implements IAsyncProcessListener { 
    18     private int count = 0; 
    19     private final int max = 36; 
    20     private final int tickPeriod = 100; 
     17        private int count = 0; 
     18        private final int max = 36; 
     19        private final int tickPeriod = 100; 
    2120 
    22     private String message; 
     21        private String message; 
    2322 
    24     private final ChessMIDlet midlet; 
    25     private final Displayable nextScreen; 
     23        private final ChessMIDlet midlet; 
     24        private final Displayable nextScreen; 
    2625 
    27     private static final Timer TIMER = new Timer(); 
    28     private transient TimerTask task; 
     26        private static final Timer TIMER = new Timer(); 
     27        private transient TimerTask task; 
    2928 
    30     public WaitCanvas( final ChessMIDlet midlet, 
    31                        final String msg, 
    32                        final Displayable nextScreen ) { 
    33         this.midlet = midlet; 
    34         this.nextScreen = nextScreen; 
    35         setText( msg ); 
    36     } 
     29        public WaitCanvas( final ChessMIDlet midlet, 
     30                           final String msg, 
     31                           final Displayable nextScreen ) { 
     32                this.midlet = midlet; 
     33                this.nextScreen = nextScreen; 
     34                setText( msg ); 
     35        } 
    3736 
    38     protected void showNotify() { 
    39         task = new TimerTask() { 
    40             public void run() { 
    41                 count = ( count + 1 ) % max; 
    42                 repaint(); 
    43             } 
    44         }; 
    45         TIMER.schedule( task, 0, tickPeriod ); 
    46     } 
     37        protected void showNotify() { 
     38                task = new TimerTask() { 
     39                        public void run() { 
     40                                count = ( count + 1 ) % max; 
     41                                repaint(); 
     42                        } 
     43                }; 
     44                TIMER.schedule( task, 0, tickPeriod ); 
     45        } 
    4746 
    48     protected void hideNotify() { 
    49         task.cancel(); 
    50         task = null; 
    51     } 
     47        protected void hideNotify() { 
     48                if( task != null ) { 
     49                        task.cancel(); 
     50                        task = null; 
     51                } 
     52        } 
    5253 
    53     public void setText( final String msg ) { 
    54         message = msg; 
    55         repaint(); 
    56     } 
     54        public void setText( final String msg ) { 
     55                message = msg; 
     56                repaint(); 
     57        } 
    5758 
    58     public void paint( final Graphics g ) { 
    59         final int width = getWidth(); 
    60         final int height = getHeight(); 
     59        public void paint( final Graphics g ) { 
     60                final int width = getWidth(); 
     61                final int height = getHeight(); 
    6162 
    62         // Calculate the radius. 
    63         final int halfWidth = width / 2; 
    64         final int halfHeight = height / 2; 
    65         final int radius = Math.min( halfWidth, halfHeight ); 
     63                // Calculate the radius. 
     64                final int halfWidth = width / 2; 
     65                final int halfHeight = height / 2; 
     66                final int radius = Math.min( halfWidth, halfHeight ); 
    6667 
    67         // Calculate the location. 
    68         final int x = halfWidth - radius / 2; 
    69         final int y = halfHeight - radius / 2; 
     68                // Calculate the location. 
     69                final int x = halfWidth - radius / 2; 
     70                final int y = halfHeight - radius / 2; 
    7071 
    71         final int theta = -( count * 360 / max ); 
     72                final int theta = -( count * 360 / max ); 
    7273 
    73         // Clear the whole screen. 
    74         g.setColor( 255, 255, 255 ); 
    75         g.fillRect( 0, 0, width, height ); 
     74                // Clear the whole screen. 
     75                g.setColor( 255, 255, 255 ); 
     76                g.fillRect( 0, 0, width, height ); 
    7677 
    77         // Now draw the pinwheel. 
    78         g.setColor( 0, 0, 0 ); 
    79         g.drawArc( x, y, radius, radius, 0, 360 ); 
    80         g.fillArc( x, y, radius, radius, theta + 90, 90 ); 
    81         g.fillArc( x, y, radius, radius, theta + 270, 90 ); 
     78                // Now draw the pinwheel. 
     79                g.setColor( 0, 0, 0 ); 
     80                g.drawArc( x, y, radius, radius, 0, 360 ); 
     81                g.fillArc( x, y, radius, radius, theta + 90, 90 ); 
     82                g.fillArc( x, y, radius, radius, theta + 270, 90 ); 
    8283 
    83         // Draw the message, if there is a message. 
    84         if ( message != null ) { 
    85             g.drawString( message, 
    86                           width / 2, 
    87                           height, 
    88                           Graphics.BOTTOM | Graphics.HCENTER 
    89             ); 
    90         } 
    91     } 
     84                // Draw the message, if there is a message. 
     85                if( message != null ) { 
     86                        g.drawString( message, 
     87                                      width / 2, 
     88                                      height, 
     89                                      Graphics.BOTTOM | Graphics.HCENTER 
     90                        ); 
     91                } 
     92        } 
    9293 
    93     public void finished( final Object result ) { 
    94         midlet.display.setCurrent( nextScreen ); 
    95     } 
     94        public void finished( final Object result ) { 
     95                midlet.display.setCurrent( nextScreen ); 
     96        } 
    9697} 
Note: See TracChangeset for help on using the changeset viewer.