package fr.alcatel.ether.app.common; // JDK - rmi import java.rmi.*; import java.rmi.server.*; // JDK - io import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.BufferedOutputStream; import java.io.IOException; import java.io.FileNotFoundException; import java.net.MalformedURLException; // JDK - collections import java.util.ArrayList; import java.util.Map; import java.util.Collections; import java.util.HashMap; // Utilities import flafi.util.FileCopy2; import fr.alcatel.ether.app.common.Config; //import fr.alcatel.ether.app.order.Order; import fr.alcatel.ether.tools.Trace; public class AtaRemoteFileServer extends UnicastRemoteObject implements RemoteFileManager { // Debugging private static final boolean DEBUG = true; /** delegate to runnable queeuing server */ private QueuedFileServer server = null; /** Default buffer size used for copying */ public static final int DEFAULT_BUFFER_SIZE = 8192; /** Default buffer size used for copying */ public static final int MIN_BUFFER_SIZE = 128; /** Current buffer size used for copying */ private int bufferSize = DEFAULT_BUFFER_SIZE; /** Buffer used for copying */ private byte[] buffer; transient RmiFileInputStream input = null; private transient final Map inputs = Collections.synchronizedMap( new HashMap() ); private transient final Map inputBuffers = Collections.synchronizedMap( new HashMap() ); /** * Construire un RemoteFileServer résidant sur un hôte. * */ public AtaRemoteFileServer( ) throws RemoteException { super(); Config.getConfig( ); Trace.getTrace( IF_REMOTE_FILE_MANAGER ); server = new QueuedFileServer( this ); Trace.debug(this,"AtaRemoteFileServer constructed"); } /** * Modifier la taille du buffer utilisé pour lire et écrire des fichiers. * Valeurs négatives sont ignorées. * * @param bufferSize: la taille du buffer en octets */ public void setBufferSize( int bufferSize ) throws RemoteException { if ( bufferSize >= MIN_BUFFER_SIZE ) { this.bufferSize = bufferSize; } } /** * Ouvrir un fichier distant pour lecture ou écriture. * * @param f: le fichier distant */ public void open( RemoteFile f ) throws RemoteException, IOException, FileNotFoundException { /* if ( DEBUG ) { Trace.debug( this, "Illegal call to AtaRemoteFileServer.open()" ); } if ( DEBUG ) { System.out.println( "Illegal call to AtaRemoteFileServer.open()" ); } */ File file = f.getFile( ); if ( DEBUG) Trace.debug( this, "Opening remote file " + file ); RmiFileInputStream input = (RmiFileInputStream)inputs.get( file ); if ( input != null ) { throw new IOException( file + " is already open" ); } FileInputStream in = new FileInputStream( file ); input = new RmiFileInputStream( in ); inputs.put( file, input ); inputBuffers.put( input, new byte[bufferSize] ); } /** * Fermer un fichier distant après lecture ou écriture. * * @param f: le fichier distant */ public void close( RemoteFile f ) throws RemoteException, IOException { /* if ( DEBUG ) { Trace.debug( this, "Illegal call to AtaRemoteFileServer.close()" ); } if ( DEBUG ) { System.out.println( "Illegal call to AtaRemoteFileServer.close()" ); } */ RmiFileInputStream input = (RmiFileInputStream)inputs.remove( f.getFile() ); if ( input != null ) { if ( DEBUG) Trace.debug( this, "Closing remote file " + f.getFile() ); inputBuffers.remove( input ); input.close( ); } else { throw new IOException( "No input stream to close" ); } } /** * Lire un fichier distant. * * @param f: le fichier distant */ public byte[] read( RemoteFile f ) throws RemoteException, IOException { /* if ( DEBUG ) { Trace.debug( this, "Illegal call to AtaRemoteFileServer.read()" ); } if ( DEBUG ) { System.out.println( "Illegal call to AtaRemoteFileServer.read()" ); } return null; */ if ( DEBUG ) { Trace.debug( this, "BEGINNING READ OF FILE:" + f);} File file = f.getFile( ); RmiFileInputStream input = (RmiFileInputStream)inputs.get( file ); if ( input != null ) { byte[] buffer = (byte[])inputBuffers.get( input ); int len = input.read( buffer ); if ( len > 0 ) { byte[] buf = new byte[len]; for ( int i = 0; i < len; i++ ) { buf[i] = buffer[i]; } if ( DEBUG ) { Trace.debug( this, "ENDING READ OF FILE:" + f); } return buf; } else { throw new IOException( "EOF reached" ); } } else { if ( DEBUG ) { Trace.debug( this, "No input stream for " + file ); } return new byte[0]; } } /** *

Copier un fichier distant.

* * @param src: le fichier source * @param dest: le fichier destination */ public boolean copy( RemoteFile src, RemoteFile dest ) throws RemoteException { final String ERROR = "Had a problem copying '" + src + "' to '" + dest + "' !"; boolean success = false; try { RemoteFileManager manager = dest.getFileManager( ); if ( manager.equals(this) ) { ArrayList args = new ArrayList( ); args.add( src ); args.add( dest ); RemoteFileServerEvent evt = new RemoteFileServerEvent( RemoteFileServerEvent.COPY, args ); server.postEventWithResult( evt ); Boolean result = (Boolean)evt.getResult( ); success = result.booleanValue( ); } else { success = manager.copy( src, dest ); } } catch ( RemoteException remoteException ) { if ( DEBUG ) { Trace.debug( this, ERROR, remoteException ); } } catch ( Exception exception ) { if ( DEBUG ) { Trace.debug( this, ERROR, exception ); } } return success; } /** *

Supprimer un fichier distant.

* * @param file: le fichier à supprimer */ public boolean delete( RemoteFile file ) throws RemoteException { final String ERROR = "Had a problem deleting '" + file + "' !"; boolean success = false; try { RemoteFileManager manager = file.getFileManager( ); if ( manager.equals(this) ) { if ( exists(file) ) { ArrayList args = new ArrayList( ); args.add( file ); RemoteFileServerEvent evt = new RemoteFileServerEvent( RemoteFileServerEvent.DELETE, args ); server.postEventWithResult( evt ); Boolean result = (Boolean)evt.getResult( ); success = result.booleanValue( ); } else { return true; } } else { // ------------------------------------------- // Ask the destination manager to retrieve the // source file for us. // ------------------------------------------- success = manager.delete( file ); } } catch ( RemoteException remoteException ) { if ( DEBUG ) { Trace.debug( this, ERROR, remoteException ); } } catch ( IOException ioProblem ) { if ( DEBUG ) { Trace.debug( this, ERROR, ioProblem ); } } catch ( Exception exception ) { if ( DEBUG ) { Trace.debug( this, ERROR, exception ); } } return success; } /** * Lister les fichiers distant d'un hôte. * On considère que le répertoire de base des fichiers est le répertoire passé en argument. * * @param directory: le répertoire distant */ public ArrayList list( RemoteFile directory ) throws RemoteException { ArrayList remoteFiles = null; String ERROR = "Had a problem listing '" + directory + "' !"; try { RemoteFileManager manager = directory.getFileManager( ); // ------------------------------------------- // List the files in the directory // ------------------------------------------- if ( manager.equals(this) ) { ArrayList args = new ArrayList( ); args.add( directory ); RemoteFileServerEvent evt = new RemoteFileServerEvent( RemoteFileServerEvent.LIST, args ); server.postEventWithResult( evt ); remoteFiles = (ArrayList)evt.getResult( ); } // ------------------------------------------- // Ask the destination manager to list the // directory for us. // ------------------------------------------- else { remoteFiles = manager.list( directory ); } } catch ( RemoteException remoteException ) { if ( DEBUG ) { Trace.debug( this, ERROR, remoteException ); } } catch ( Exception exception ) { if ( DEBUG ) { Trace.debug( this, ERROR, exception ); } } return remoteFiles; } /** *

Transférer un fichier distant.

* * @param src: le fichier source * @param dest: le fichier destination */ public boolean move( RemoteFile src, RemoteFile dest ) throws RemoteException { String ERROR = "Had a problem moving '" + src + "' to '" + dest + "' !"; boolean success = false; // ------------------------------------------- // Debugging // ------------------------------------------- if ( DEBUG ) { Trace.debug( this, IF_REMOTE_FILE_MANAGER + " moving files." ); } try { // ------------------------------------------- // Move the file src to dest // ------------------------------------------- RemoteFileManager manager = dest.getFileManager( ); if ( manager.equals(this) ) { ArrayList args = new ArrayList( ); args.add( src ); args.add( dest ); RemoteFileServerEvent evt = new RemoteFileServerEvent( RemoteFileServerEvent.MOVE, args ); server.postEventWithResult( evt ); Boolean result = (Boolean)evt.getResult( ); success = result.booleanValue( ); } // ------------------------------------------- // Ask the destination manager to move // the file for us. // ------------------------------------------- else { success = manager.move( src, dest ); } } catch ( RemoteException remoteException ) { if ( DEBUG ) { Trace.debug( this, ERROR, remoteException ); } } catch ( Exception exception ) { if ( DEBUG ) { Trace.debug( this, ERROR, exception ); } } return success; } /** * Récupérer un fichier distant sur cette hôte. * * @param remoteFile: le fichier source à rapatrier * * @return un File indiquant le fichier temporaire; l'appelant doit le détruire lorsqu'il a terminé */ public File retrieve( RemoteFile file ) throws RemoteException { final String ERROR = "Had a problem retrieving '" + file + "' !"; File retrieved = null; try { // ------------------------------------------- // Move the file src to dest // ------------------------------------------- RemoteFileManager manager = file.getFileManager( ); ArrayList args = new ArrayList( ); args.add( file ); RemoteFileServerEvent evt = new RemoteFileServerEvent( RemoteFileServerEvent.RETRIEVE, args ); server.postEventWithResult( evt ); retrieved = (File)evt.getResult( ); } catch ( RemoteException remoteException ) { if ( DEBUG ) { Trace.debug( this, ERROR, remoteException ); } } catch ( Exception exception ) { if ( DEBUG ) { Trace.debug( this, ERROR, exception ); } } return retrieved; } /** *

Retrieves the local file corresponding a remote file on local

*

Return value is null if file is not available with this remote file manager.

* * @param remoteFile: le fichier source à rapatrier * * @return un File indiquant le fichier en local */ public File getLocalFile( RemoteFile localFile ) throws RemoteException, IOException { try { RemoteFileManager distant = localFile.getFileManager( ); if ( distant.equals(this) ) { return localFile.getFile( ); } } catch ( NotBoundException notBound ) { if ( DEBUG ) { Trace.debug( this, "RemoteFileManager not bound to " + localFile, notBound ); } } catch ( MalformedURLException badURL ) { if ( DEBUG ) { Trace.debug( this, "Unable to locate RemoteFileManager for " + localFile, badURL ); } } return null; } /** *

Create a remote file representing a directory. * If the remote file is handled by this server, we delegat to the local * file manager. If not we forward the request to the RemoteFile's server. *

* @param directory: the remote directory to create * * @return true if the directory creation succeeded, false otherwise */ public boolean makeDir( RemoteFile directory ) throws RemoteException { boolean success = false; if ( DEBUG ) { Trace.debug( this, "Creating directory '" + directory + "'" ); } try { RemoteFileManager remoteManager = directory.getFileManager( ); if ( remoteManager.equals(this) ) { FileManager localFileManager = (FileManager)FileManager.instance( FileManager.class.toString() ); // ATTENTIOn CORECTIOn A TESTERT ET RETESTER // return localFileManager.mkdir( directory.getPath() ); // return localFileManager.mkdir( directory.getAbsolutePath() ); // success = true; } else { success = remoteManager.makeDir( directory ); } } catch ( Exception exception ) { if ( DEBUG ) { Trace.debug( this, "Had a problem creating '" + directory + "' !", exception ); } } return success; } /** *

Delete a remote file representing a directory. * If the remote file is handled by this server, we delegate to the local * file manager. If not we forward the request to the RemoteFile's server. *

* @param directory: the remote directory to remove files from */ public boolean deleteDir( RemoteFile directory ) throws RemoteException { if ( DEBUG ) { Trace.debug( this, "Deleting directory " + directory ); } try { RemoteFileManager remoteManager = directory.getFileManager( ); if ( remoteManager.equals(this) ) { FileManager localFileManager = (FileManager)FileManager.instance( FileManager.class.toString() ); localFileManager.deleteAllDir( directory.getPath() ); return true; } else { return remoteManager.deleteDir( directory ); } } catch ( Exception exception ) { if ( DEBUG ) { Trace.debug( this, "Had a problem deleting '" + directory + "' !", exception ); } } return false; } /** *

Determine the size, in bytes, of the file or of all the files in a directory.

* * @param directory: the file or directory * * @return the size of the file or directory; the size of a directory is the sum of all files within it and its sub-directories */ public long size( RemoteFile directory ) throws RemoteException { long length = 0; final String ERROR = "Had a problem obtaining size of " + directory; try { // ------------------------------------------- // We retrieve the size of the directory of file. // ------------------------------------------- RemoteFileManager remoteManager = directory.getFileManager( ); if ( remoteManager.equals(this) ) { // ArrayList args = new ArrayList( ); // args.add( directory ); // RemoteFileServerEvent evt = new RemoteFileServerEvent( RemoteFileServerEvent.SIZE, args ); // server.postEventWithResult( evt ); // Long size = (Long)evt.getResult( ); // length = size.longValue( ); // calcul réel par appel au local fileManager File toList = directory.getFileManager().getLocalFile( directory ); FileManager localFileManager = (FileManager)FileManager.instance( FileManager.class.toString() ); return localFileManager.size( toList ); } // ------------------------------------------- // Ask the other remote manager to retrieve // the source file for us. // ------------------------------------------- else { length = remoteManager.size( directory ); } } catch ( RemoteException remoteException ) { if ( DEBUG ) { Trace.debug( this, ERROR, remoteException ); } } catch ( IOException ioProblem ) { if ( DEBUG ) { Trace.debug( this, ERROR, ioProblem ); } } catch ( Exception exception ) { if ( DEBUG ) { Trace.debug( this, ERROR, exception ); } } if ( DEBUG ) { Trace.debug( this, "Size of files in remote directory: " + length + " bytes" ); } return length; } /** *

Determine if a remote file exists.

* * @param file: remote file to verify * * @return true if the file exists, false otherwise */ public boolean exists( RemoteFile file ) throws RemoteException { boolean exists = false; try { RemoteFileManager manager = file.getFileManager( ); if ( manager.equals(this) ) { ArrayList args = new ArrayList( ); args.add( file ); RemoteFileServerEvent evt = new RemoteFileServerEvent( RemoteFileServerEvent.EXISTS, args ); server.postEventWithResult( evt ); Boolean result = (Boolean)evt.getResult( ); exists = result.booleanValue( ); } else { exists = manager.exists( file ); } } catch ( NotBoundException notRunning ) { if ( DEBUG ) { Trace.debug( this, "Remote Server not bound", notRunning ); } } catch ( MalformedURLException badURL ) { if ( DEBUG ) { Trace.debug( this, "Invalid file name " + file, badURL ); } } catch ( IOException ioProblem ) { if ( DEBUG ) { Trace.debug( this, "Invalid file name " + file, ioProblem ); } } catch ( Exception e ) { if ( DEBUG ) { Trace.debug( this, "Error checking existence of file " + file, e ); } } finally { return exists; } } /** *

Nettoyer les espaces temporaire utilisés sur cette machine.

* * @param int : l'identifiant de la commande */ public void cleanTmpDir(int orderId) throws RemoteException { FileManager localFileManager = (FileManager)FileManager.instance( FileManager.class.toString() ); try { if ( DEBUG ) { Trace.debug( this, " TRYING TO CLEAN ARCHIVE DIR :" + localFileManager.getArchiveOrderDir(orderId)) ;} localFileManager.deleteAllDir(localFileManager.getArchiveOrderDir(orderId)); } catch ( Exception e ) { if ( DEBUG ) { Trace.debug( this, "Error ", e ); } } // Order tempOrder = new Order(orderId); // try { // if ( DEBUG ) { Trace.debug( this, " TRYING TO CLEAN SERVICE DIR :" + localFileManager.getServiceOrderDir(tempOrder)) ;} // localFileManager.deleteAllDir(localFileManager.getServiceOrderDir(tempOrder)); // } // catch ( Exception e ) { // if ( DEBUG ) { Trace.debug( this, "Error ", e ); } // } // try { // if ( DEBUG ) { Trace.debug( this, " TRYING TO CLEAN TEMP DIR :" + localFileManager.getTempOrderDir(tempOrder)) ;} // localFileManager.deleteAllDir(localFileManager.getTempOrderDir(tempOrder)); // } // catch ( Exception e ) { // if ( DEBUG ) { Trace.debug( this, "Error ", e ); } // } } /** *

Execute the RMI Remote File Server.

* * @param args: command-line arguments; requires host name as first and only arg. * */ public static void main(String[] args) { /* if ( System.getSecurityManager() == null ) { System.setSecurityManager( new RMISecurityManager() ); } */ String name = "//" + args[0] + "/" + IF_REMOTE_FILE_MANAGER; try { Naming.rebind( name, new AtaRemoteFileServer() ); System.out.println( IF_REMOTE_FILE_MANAGER + " bound" ); } catch ( Exception e ) { System.err.println( IF_REMOTE_FILE_MANAGER + " exception: " + e.getMessage() ); e.printStackTrace( ); } } }