Clover coverage report -
Coverage timestamp: Sun Oct 12 2003 22:57:21 PDT
file stats: LOC: 488   Methods: 16
NCLOC: 243   Classes: 5
 
 Source file Conditionals Statements Methods TOTAL
TextureManager.java 0% 0% 0% 0%
coverage
 1   
 /*
 2   
 
 3   
 VRMoo Server - Virtual Reality Object Oriented MUD Server
 4   
 Copyright (C) 2001 - 2003  VRMoo Development Team
 5   
 
 6   
 
 7   
 This program is free software; you can redistribute it and/or modify
 8   
 it under the terms of the GNU General Public License as published by
 9   
 the Free Software Foundation; either version 2 of the License, or
 10   
 (at your option) any later version.
 11   
 
 12   
 This program is distributed in the hope that it will be useful,
 13   
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 14   
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 15   
 GNU General Public License for more details.
 16   
 
 17   
 You should have received a copy of the GNU General Public License
 18   
 along with this program; if not, write to the Free Software
 19   
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 20   
 
 21   
 
 22   
 For information about VRMoo and its authors, please visit the website:
 23   
 http://www.vrmoo.org/
 24   
 
 25   
 */
 26   
 
 27   
 package org.vrmoo.server.data;
 28   
 
 29   
 import java.io.File;
 30   
 import java.util.ArrayList;
 31   
 import java.util.List;
 32   
 
 33   
 import org.vrmoo.common.exception.VRMooException;
 34   
 import org.vrmoo.common.exception.VRMooParseException;
 35   
 import org.vrmoo.common.util.Base64Utility;
 36   
 import org.vrmoo.common.util.CommandHandler;
 37   
 import org.vrmoo.common.util.CommandProcessor;
 38   
 import org.vrmoo.common.util.FileUtility;
 39   
 import org.vrmoo.common.util.ParserUtility;
 40   
 
 41   
 import org.vrmoo.server.client.AllClients;
 42   
 import org.vrmoo.server.client.ClientHandler;
 43   
 import org.vrmoo.server.world.World;
 44   
 
 45   
 /**
 46   
  * Manages a set of textures.
 47   
  *
 48   
  * @author Jeff Weston
 49   
  */
 50   
 public class TextureManager extends CommandHandler implements CommandProcessor
 51   
 {
 52   
     /**
 53   
      * The prefix used for texture commands.
 54   
      */
 55   
     private static final String TEXTURE_COMMAND_PREFIX = "texture:";
 56   
 
 57   
     /**
 58   
      * The directory of textures that we are managing.
 59   
      */
 60   
     private String textureDir;
 61   
 
 62   
     /**
 63   
      * The world that we are managing textures for.
 64   
      */
 65   
     private World world;
 66   
 
 67   
     /**
 68   
      * A list of data for all the textures handled by this class.
 69   
      */
 70   
     private List textureDataList;
 71   
 
 72   
     /**
 73   
      * Construct this class using the given world data directory. The texture
 74   
      * data directory this class uses will be based upon the world data
 75   
      * directory passed in here.
 76   
      *
 77   
      * @param world   the world we are managing textures for
 78   
      */
 79  0
     public TextureManager( World world )
 80   
     {
 81  0
         addCommandProcessor( new TextureListCommandProcessor( ) );
 82  0
         addCommandProcessor( new AddTextureCommandProcessor( ) );
 83  0
         addCommandProcessor( new DeleteTextureCommandProcessor( ) );
 84   
 
 85  0
         textureDataList = new ArrayList( );
 86  0
         this.world = world;
 87  0
         world.addCommandProcessor( this );
 88  0
         textureDir = world.getWorldDataDirectory( ) + "/textures";
 89  0
         File dir = new File( textureDir );
 90  0
         FileUtility.ensureDirectoryExists( dir );
 91   
 
 92  0
         File[ ] files = dir.listFiles( );
 93  0
         for ( int i = 0; i < files.length; i++ )
 94   
         {
 95  0
             addTextureData( files[ i ] );
 96   
         }
 97   
     }
 98   
 
 99   
     /**
 100   
      * Establish what type of commands that the class implementing this
 101   
      * interface can process. Returns a String indicating the prefix to look
 102   
      * for in the commands sent to the client or the server.
 103   
      *
 104   
      * @return the command prefix
 105   
      */
 106  0
     public String getCommandPrefix( )
 107   
     {
 108  0
         return TEXTURE_COMMAND_PREFIX;
 109   
     }
 110   
 
 111   
     /**
 112   
      * Process a command matching the command prefix established by the
 113   
      * <code>getCommandPrefix()</code> method.
 114   
      *
 115   
      * @param command     the command to process
 116   
      * @param extraData   extra data that isn't part of the command but may be
 117   
      *                      needed for dealing with the command (such as the ID
 118   
      *                      of the client that sent the command)
 119   
      *
 120   
      * @throws VRMooException   for any errors while processing the command
 121   
      */
 122  0
     public synchronized void processCommand( String command, String extraData )
 123   
             throws VRMooException
 124   
     {
 125  0
         String textureCommand = command.substring(
 126   
                 TEXTURE_COMMAND_PREFIX.length( ) ).trim( );
 127   
 
 128  0
         handleCommand( textureCommand, extraData );
 129   
     }
 130   
 
 131   
     /**
 132   
      * Indicate that a new client has connected to the world and that this
 133   
      * texture manager should perform the texture initialization procedure
 134   
      * with the client.
 135   
      *
 136   
      * @param client   the <code>ClientHandler</code> that connected
 137   
      */
 138  0
     public void newClientConnected( ClientHandler client )
 139   
     {
 140  0
         client.writeLine( "world: texture: listTextures" );
 141   
     }
 142   
 
 143   
     /**
 144   
      * Takes a texture specified by a <code>File</code> object and adds its data
 145   
      * to the texture data list.
 146   
      *
 147   
      * @param textureFile   the file indicating which texture's data to add
 148   
      */
 149  0
     private void addTextureData( File textureFile )
 150   
     {
 151  0
         String name = textureFile.getName( );
 152  0
         long crc = 0;
 153   
 
 154  0
         try
 155   
         {
 156  0
             crc = FileUtility.computeCRC32( textureFile );
 157   
         }
 158   
         catch ( Exception e )
 159   
         {
 160  0
             e.printStackTrace( );
 161   
         }
 162   
 
 163  0
         textureDataList.add( new TextureData( name, crc ) );
 164   
     }
 165   
 
 166   
     /**
 167   
      * Takes a texture specified by a <code>File</code> object and deletes its
 168   
      * data from the texture data list.
 169   
      *
 170   
      * @param textureFile   the file indicating which texture's data to delete
 171   
      */
 172  0
     private void deleteTextureData( File textureFile )
 173   
     {
 174  0
         String name = textureFile.getName( );
 175   
 
 176  0
         for ( int i = 0; i < textureDataList.size( ); i++ )
 177   
         {
 178  0
             TextureData textureData = ( TextureData ) textureDataList.get( i );
 179  0
             if ( textureData.getName( ).equals( name ) )
 180   
             {
 181  0
                 textureDataList.remove( i );
 182  0
                 break;
 183   
             }
 184   
         }
 185   
     }
 186   
 
 187   
     /**
 188   
      * Private inner class for keeping track of various bits of data about a
 189   
      * texture.
 190   
      */
 191   
     private class TextureData
 192   
     {
 193   
         /**
 194   
          * The name of the texture.
 195   
          */
 196   
         private String name;
 197   
 
 198   
         /**
 199   
          * The CRC-32 of the texture.
 200   
          */
 201   
         private long crc;
 202   
 
 203   
         /**
 204   
          * Construct this class with a given texture name and CRC-32 of the
 205   
          * texture.
 206   
          *
 207   
          * @param name   the name of the texture
 208   
          * @param crc    the CRC-32 of the texture
 209   
          */
 210  0
         public TextureData( String name, long crc )
 211   
         {
 212  0
             this.name = name;
 213  0
             this.crc = crc;
 214   
         }
 215   
 
 216   
         /**
 217   
          * Accessor for the texture name.
 218   
          *
 219   
          * @return the texture name
 220   
          */
 221  0
         public String getName( )
 222   
         {
 223  0
             return name;
 224   
         }
 225   
 
 226   
         /**
 227   
          * Accessor for the texture CRC-32.
 228   
          *
 229   
          * @return the texture CRC-32
 230   
          */
 231  0
         public long getCRC( )
 232   
         {
 233  0
             return crc;
 234   
         }
 235   
     }
 236   
 
 237   
     /**
 238   
      * Private inner class implementing the <code>CommandProcessor</code>
 239   
      * interface for dealing with the "deleteTexture" command sent from
 240   
      * the client. This class removes the texture from the list of current
 241   
      * textures, removes the file, and notifies all connected clients.
 242   
      */
 243   
     private class DeleteTextureCommandProcessor implements CommandProcessor
 244   
     {
 245   
         /**
 246   
          * The prefix for the command handled by this processor.
 247   
          */
 248   
         private static final String PREFIX = "deleteTexture:";
 249   
 
 250   
         /**
 251   
          * Returns the command prefix used to recognize commands that this
 252   
          * processor can handle.
 253   
          *
 254   
          * @return the command prefix
 255   
          */
 256  0
         public String getCommandPrefix( )
 257   
         {
 258  0
             return PREFIX;
 259   
         }
 260   
 
 261   
         /**
 262   
          * Process a command matching the command prefix established by the
 263   
          * <code>getCommandPrefix()</code> method.
 264   
          *
 265   
          * @param command     the command to process
 266   
          * @param extraData   extra data that isn't part of the command but may
 267   
          *                      be needed for dealing with the command (such as
 268   
          *                      the ID of the client that sent the command)
 269   
          *
 270   
          * @throws VRMooParseException   for any parsing errors while processing
 271   
          *                                 the command
 272   
          */
 273  0
         public void processCommand( String command, String extraData )
 274   
                 throws VRMooParseException
 275   
         {
 276  0
             String texture = command.substring( PREFIX.length( ) ).trim( );
 277  0
             File file = new File( textureDir + "/" + texture );
 278  0
             deleteTextureData( file );
 279  0
             file.delete( );
 280  0
             world.broadcast( "world: texture: deleteTexture: " + texture );
 281   
         }
 282   
     }
 283   
 
 284   
     /**
 285   
      * Private inner class implementing the <code>CommandProcessor</code>
 286   
      * interface for dealing with the "addTexture" command sent from the client.
 287   
      * This class adds the texture to the list of current textures, writes it as
 288   
      * data, and notifies all connected clients.
 289   
      */
 290   
     private class AddTextureCommandProcessor implements CommandProcessor
 291   
     {
 292   
         /**
 293   
          * The prefix for the command handled by this processor.
 294   
          */
 295   
         private static final String PREFIX = "addTexture:";
 296   
 
 297   
         /**
 298   
          * Returns the command prefix used to recognize commands that this
 299   
          * processor can handle.
 300   
          *
 301   
          * @return the command prefix
 302   
          */
 303  0
         public String getCommandPrefix( )
 304   
         {
 305  0
             return PREFIX;
 306   
         }
 307   
 
 308   
         /**
 309   
          * Process a command matching the command prefix established by the
 310   
          * <code>getCommandPrefix()</code> method.
 311   
          *
 312   
          * @param command     the command to process
 313   
          * @param extraData   extra data that isn't part of the command but may
 314   
          *                      be needed for dealing with the command (such as
 315   
          *                      the ID of the client that sent the command)
 316   
          *
 317   
          * @throws VRMooParseException   for any parsing errors while processing
 318   
          *                                 the command
 319   
          */
 320  0
         public void processCommand( String command, String extraData )
 321   
                 throws VRMooParseException
 322   
         {
 323  0
             String textureData =
 324   
                     command.substring( PREFIX.length( ) ).trim( );
 325  0
             int delimiter = textureData.indexOf( "," );
 326  0
             String textureName = textureData.substring( 0, delimiter ).trim( );
 327  0
             String base64Data = textureData.substring( delimiter + 1 ).trim( );
 328  0
             byte[ ] data = Base64Utility.toBinary( base64Data );
 329  0
             try
 330   
             {
 331  0
                 File file = new File( textureDir + "/" + textureName );
 332  0
                 FileUtility.writeFile( file, data );
 333  0
                 addTextureData( file );
 334   
             }
 335   
             catch ( Exception e )
 336   
             {
 337  0
                 e.printStackTrace( );
 338   
             }
 339  0
             world.broadcast( "world: texture: addTexture: " + textureName +
 340   
                              ", " + base64Data );
 341   
         }
 342   
     }
 343   
 
 344   
     /**
 345   
      * Private inner class implementing the <code>CommandProcessor</code>
 346   
      * interface for dealing with the "textureList" command sent from the
 347   
      * client.
 348   
      */
 349   
     private class TextureListCommandProcessor implements CommandProcessor
 350   
     {
 351   
         /**
 352   
          * The prefix for the command handled by this processor.
 353   
          */
 354   
         private static final String PREFIX = "textureList:";
 355   
 
 356   
         /**
 357   
          * Returns the command prefix used to recognize commands that this
 358   
          * processor can handle.
 359   
          *
 360   
          * @return the command prefix
 361   
          */
 362  0
         public String getCommandPrefix( )
 363   
         {
 364  0
             return PREFIX;
 365   
         }
 366   
 
 367   
         /**
 368   
          * Process a command matching the command prefix established by the
 369   
          * <code>getCommandPrefix()</code> method.
 370   
          *
 371   
          * @param command     the command to process
 372   
          * @param extraData   extra data that isn't part of the command but may
 373   
          *                      be needed for dealing with the command (such as
 374   
          *                      the ID of the client that sent the command)
 375   
          *
 376   
          * @throws VRMooException   for any errors while processing the command
 377   
          */
 378  0
         public void processCommand( String command, String extraData )
 379   
                 throws VRMooException
 380   
         {
 381  0
             int clientId = ParserUtility.parseInt( extraData );
 382  0
             ClientHandler client = AllClients.getClientByID( clientId );
 383  0
             List textureList = new ArrayList( );
 384   
 
 385  0
             if ( command.length( ) > PREFIX.length( ) )
 386   
             {
 387  0
                 String textures = command.substring(
 388   
                         PREFIX.length( ) ).trim( );
 389   
 
 390  0
                 int nextIndex;
 391  0
                 do
 392   
                 {
 393  0
                     nextIndex = textures.indexOf( "," );
 394  0
                     String curTexture;
 395  0
                     if ( nextIndex == -1 )
 396   
                     {
 397  0
                         curTexture = textures;
 398   
                     }
 399   
                     else
 400   
                     {
 401  0
                         curTexture = textures.substring( 0, nextIndex ).trim( );
 402  0
                         textures = textures.substring( nextIndex + 1 ).trim( );
 403   
                     }
 404  0
                     int delimiter = curTexture.indexOf( "*" );
 405  0
                     String name = curTexture.substring( 0, delimiter ).trim( );
 406  0
                     String crc = curTexture.substring( delimiter + 1 ).trim( );
 407  0
                     long lCRC = ParserUtility.parseLong( crc );
 408  0
                     textureList.add( new TextureData( name, lCRC ) );
 409   
                 }
 410  0
                 while ( nextIndex != -1 );
 411   
             }
 412   
 
 413  0
             boolean processComplete = true;
 414   
 
 415   
             // Determine which textures need to be deleted on the client.
 416  0
             for ( int i = 0; i < textureList.size( ); i++ )
 417   
             {
 418  0
                 TextureData textureData = ( TextureData ) textureList.get( i );
 419  0
                 if ( ! containsTexture( textureData, textureDataList ) )
 420   
                 {
 421  0
                     processComplete = false;
 422  0
                     client.writeLine( "world: texture: deleteTexture: " +
 423   
                                       textureData.getName( ) );
 424   
                 }
 425   
             }
 426   
 
 427   
             // Determine which textures need to be created on the client.
 428  0
             for ( int i = 0; i < textureDataList.size( ); i++ )
 429   
             {
 430  0
                 TextureData textureData =
 431   
                         ( TextureData ) textureDataList.get( i );
 432  0
                 if ( ! containsTexture( textureData, textureList ) )
 433   
                 {
 434  0
                     File file = new File( textureDir + "/" +
 435   
                                           textureData.getName( ) );
 436  0
                     String base64 = "";
 437  0
                     try
 438   
                     {
 439  0
                         base64 = Base64Utility.toBase64(
 440   
                                 FileUtility.readFile( file ) );
 441   
                     }
 442   
                     catch ( Exception e )
 443   
                     {
 444  0
                         e.printStackTrace( );
 445   
                     }
 446  0
                     processComplete = false;
 447  0
                     client.writeLine( "world: texture: addTexture: " +
 448   
                                       textureData.getName( ) + ", " +
 449   
                                       base64 );
 450   
                 }
 451   
             }
 452   
 
 453  0
             if ( processComplete )
 454   
             {
 455  0
                 client.writeLine( "world: texture: activate" );
 456  0
                 world.clientFinishedTextures( client );
 457   
             }
 458   
             else
 459   
             {
 460  0
                 client.writeLine( "world: texture: listTextures" );
 461   
             }
 462   
         }
 463   
 
 464   
         /**
 465   
          * Determines if a specified <code>TextureData</code> is contained in
 466   
          * a specified <code>List</code>.
 467   
          *
 468   
          * @param data   the <code>TextureData</code> to look for
 469   
          * @param list   the <code>List</code> to look in
 470   
          *
 471   
          * @return true if found, false otherwise
 472   
          */
 473  0
         private boolean containsTexture( TextureData data, List list )
 474   
         {
 475  0
             for ( int i = 0; i < list.size( ); i++ )
 476   
             {
 477  0
                 TextureData textureData = ( TextureData ) list.get( i );
 478  0
                 if ( ( data.getName( ).equals( textureData.getName( ) ) ) &&
 479   
                      ( data.getCRC( ) == textureData.getCRC( ) ) )
 480   
                 {
 481  0
                     return true;
 482   
                 }
 483   
             }
 484  0
             return false;
 485   
         }
 486   
     }
 487   
 }
 488