listing files from a lan node

Hello,I have an application where I need to look up the file list on a remote meachine connected to my lan network. the java.io.File permit me to look up only the local machine. Any tips will be of great help.thanksshajy mathew
[276 byte] By [shajy_mathew] at [2007-9-26 1:29:48]
# 1
Well, it is probably naive but can you start a process on this node? If so, you could write a simple server for it.Another solution would be to use ftp/http daemons - if there are running any on this node.I can't think of any really generic solution.
rthomanek at 2007-6-29 1:27:00 > top of Java-index,Archived Forums,Java Programming...
# 2

thanks rthomanek

the jave program gets the node name and the input file name as the parameter. The applciaions require the file names as the result. do u mean a socket based server?

regards.

shajy

> Well, it is probably naive but can you start a process

> on this node? If so, you could write a simple server

> for it.

>

> Another solution would be to use ftp/http daemons - if

> there are running any on this node.

>

> I can't think of any really generic solution.

shajy_mathew at 2007-6-29 1:27:00 > top of Java-index,Archived Forums,Java Programming...
# 3

Hi,

It is very much possible therough RMI. Here is a sample code which creates a RMI file server.

RMI Example Architecture

To demonstrate the java.rmi package, we will create a (very simple) file server. This

server accepts requests from a remote caller and returns a RemoteObject that is used

by wrapper classes to provide java.io.InputStream and java.io.OutputStream

objects that read or write from the remote file.

The RemoteInputHandle Interface

First off, we define the interface with which our input wrapper class interacts with

the remote file (see Listing 54.1). The RemoteInputHandle class provides methods that

correspond to those required by the java.io.InputStream abstract class. The interface

simply defines the methods required for an InputStream object. Each method can

throw a RemoteException as noted in the throws clause.

Listing 54.1. The RemoteInputHandle interface.

import java.rmi.*;

import java.io.IOException;

public interface RemoteInputHandle

extends Remote

{

public int available( )

throws IOException, RemoteException;

public void close( )

throws IOException, RemoteException;

public void mark( int readlimit )

throws RemoteException;

public boolean markSupported( )

throws RemoteException;

public int read( )

throws IOException, RemoteException;

public int read( byte b[] )

throws IOException, RemoteException;

public int read( byte b[], int off, int len )

throws IOException, RemoteException;

public void reset( )

throws IOException, RemoteException;

public long skip( long n )

throws IOException, RemoteException;

}

The RemoteInputHandleImpl Class

Next up is the RemoteInputHandleImpl class, which provides the implementation for

the RemoteInputHandle interface just defined (see Listing 54.2). The

RemoteFileServerImpl class creates a new input handle implementation when a

RemoteInputHandle is requested. The constructor for the implementation class takes

one argument: the InputStream for which we are providing remote access. This makes

the handle more useful because we can provide remote access to any local object that

extends InputStream. This stream is saved in an instance variable (inStream) after the

UnicastRemoteServer superclass's constructor is called. The superclass constructor is

called because it has to set things up to listen for requests from remote clients.

Listing 54.2. The RemoteInputHandleImpl class.

import java.rmi.*;

import java.rmi.server.UnicastRemoteObject;

import java.rmi.RMISecurityManager;

public class RemoteInputHandleImpl

extends UnicastRemoteObject

implements RemoteInputHandle

{

private InputStream inStream;

public RemoteInputHandleImpl( InputStream in )

throws RemoteException

{

super( );

inStream = in;

}

Next comes the actual code implementing the methods of the RemoteInputHandle

interface (see Listing 54.3). Each method simply calls the corresponding method on

inStream and returns the return value from that call (as appropriate). The RMI system

takes care of returning the result--as well as any exceptions that occur--to the

calling object on the remote machine.

Listing 54.3. The methods of the RemoteInputHandleImpl class.

public int available( )

throws IOException, RemoteException

{

return inStream.available();

}

public void close( )

throws IOException, RemoteException

{

inStream.close( );

}

public synchronized void mark( int readlimit )

throws RemoteException

{

inStream.mark( readlimit );

}

public boolean markSupported( )

throws RemoteException

{

return inStream.markSupported( );

}

public int read( )

throws IOException, RemoteException

{

return inStream.read( );

}

public int read( byte b[] )

throws IOException, RemoteException

{

return inStream.read( b );

}

public int read( byte b[], int off, int len )

throws IOException, RemoteException

{

return inStream.read( b, off, len );

}

public synchronized void reset( )

throws IOException, RemoteException

{

inStream.reset( );

}

public long skip( long n )

throws IOException, RemoteException

{

return inStream.skip( n );

}

}

The RemoteInputStream Class

The RemoteInputStream class extends the abstract InputStream class and uses the

RemoteInputHandle interface. The constructor first contacts a RemoteFileServer to

obtain a RemoteInputHandle reference for the path given and then stores this handle

in an instance variable. The InputStream methods are mapped into the corresponding

calls on the RemoteInputHandle (that is, the RemoteInputStream read() method calls

the read() method on the RemoteInputHandle reference obtained by the constructor).

NOTE: You may wonder why we are using a wrapper class when all it

does is turn around and call the same method on the interface. The

reason is that we want to provide a class that can be used any place an

InputStream or OutputStream can be used. Although this approach

increases the overhead because we have to make an extra method call,

the ability to use our remote streams as drop-in replacements outweighs

the cost of that extra call.

For example, you can create a PrintStream using a RemoteOutputStream

for a log file for an application. Anything you print to this PrintStream is

written to the log file on the remote machine. Without the wrapper class,

you would have to individually extend each class to use the

RemoteInputHandle or RemoteOutputHandle as needed.

We'll start out with the necessary imports and the class definition (see Listing 54.4).

We need access to the java.io classes because the RemoteInputStream extends

InputStream. We also need access to the RMI Naming class so that we can use the

lookup() method to get a RemoteInputHandle from the server. There are two

constructors for the class: One takes a path name as the argument and contacts the

file server residing on the same host, and the other takes a remote host name to

contact as well.

Listing 54.4. The RemoteInputStream class.

import java.io.*;

import java.rmi.RemoteException;

import java.rmi.Naming;

import java.rmi.NotBoundException;

public class RemoteInputStream

extends InputStream

{

private RemoteInputHandle in;

public RemoteInputStream( String path )

throws IOException, RemoteException, NotBoundException

{

String url = "rmi://localhost/RFSI";

RemoteFileServer rfs = (RemoteFileServer) Naming.lookup( url );

in = rfs.getInStream( path );

}

public RemoteInputStream( String path, String host )

throws IOException, RemoteException, NotBoundException

{

String url = "rmi://" + host + "/RFSI";

RemoteFileServer rfs = (RemoteFileServer) Naming.lookup( url );

in = rfs.getInStream( path );

}

Next, each of the InputStream methods is defined (see Listing 54.5). The code for each

method tries to call the corresponding method on the handle object. If a

RemoteException occurs, an IOException is thrown with the message from the

RemoteException as its message.

Listing 54.5. The InputStream methods of the RemoteInputStream class.

public int available( )

throws IOException

{

try {

return in.available( );

} catch( RemoteException e ) {

throw new IOException( "Remote error: " + e );

}

}

public void close( )

throws IOException

{

try {

in.close( );

} catch( RemoteException e ) {

throw new IOException( "Remote error: " + e );

}

}

public synchronized void mark( int readlimit )

{

try {

in.mark( readlimit );

} catch( Exception e ) {

System.err.println(

"RemoteInputStream::mark: Remote error: " + e );

}

}

public boolean markSupported( ) {

try {

return in.markSupported( );

} catch( RemoteException e ) {

return false; // Assume mark not supported

}

}

public int read( )

throws IOException

{

try {

return in.read( );

} catch( RemoteException e ) {

throw new IOException( "Remote error: " + e );

}

}

public int read( byte b[] )

throws IOException

{

try {

return in.read( b );

} catch( RemoteException e ) {

throw new IOException( "Remote error: " + e );

}

}

public int read( byte b[], int off, int len )

throws IOException

{

try {

return in.read( b, off, len );

} catch( RemoteException e ) {

throw new IOException( "Remote error: " + e );

}

}

public synchronized void reset( )

throws IOException

{

try {

in.reset( );

} catch( RemoteException e ) {

throw new IOException( "Remote error: " + e );

}

}

public long skip( long n )

throws IOException

{

try {

return in.skip( n );

} catch( RemoteException e ) {

throw new IOException( "Remote error: " + e );

}

}

}

The Output Side

Because the remote interface, implementation, and the wrapper class for the output

stream version are, for the most part, identical to those for input stream, they are not

given here. The methods in the interface correspond to those for

java.io.OutputStream instead of InputStream, and the RemoteOutputStream object

extends OutputStream. The complete code for all the output classes is contained on

the CD-ROM that accompanies this book.

The RemoteFileServer Interface and the RemoteFileServerImpl Class

The RemoteFileServer interface provides two methods that the remote input and

output stream classes use to obtain handles (see Listing 54.6).

Listing 54.6. The RemoteFileServer interface.

public interface RemoteFileServer

extends java.rmi.Remote

{

public RemoteOutputHandle getOutStream( String path )

throws java.rmi.RemoteException;

public RemoteInputHandle getInStream( String path )

throws java.rmi.RemoteException;

}

The server itself is very simple. It consists of a constructor that calls the

UnicastRemoteServer superclass, a method that does some sanity checking on the

path names requested, implementations of the interface methods, and a main()

method that allows the server to be started (see Listing 54.7). We start off as usual

with the import statements, class declaration, and the constructor. Note that there is a

static class variable PATH_SEPARATOR, which should be changed to whatever character

separates directory components on your operating system.

Listing 54.7. The RemoteFileServerImpl class.

import java.io.*;

import java.rmi.*;

import java.rmi.server.UnicastRemoteServer;

import java.rmi.server.StubSecurityManager;

public class RemoteFileServerImpl

extends UnicastRemoteServer

implements RemoteFileServer

{

// Path component separator. Change as apropriate to your OS.

public static char PATH_SEPARATOR = '/';

public RemoteFileServerImpl( )

throws RemoteException

{

super( );// Call superclass' constructor

// No class specific initialisation needed.

}

The checkPathName() method shown in Listing 54.8 does some rudimentary checking

to ensure that the path name does not point outside the current directory or one of its

subdirectories. The code that checks for an absolute path (that is, a path that starts at

the root directory or with a specific drive) should be edited as appropriate for your

platform.

Listing 54.8. The RemoteFileServerImpl.checkPathName() method.

public boolean checkPathName( String path )

{

// No absolute path names (i.e. ones beginning with a slash or drive)

// UNIX Version

if( path.charAt( 0 ) == PATH_SEPARATOR ) {

return false;

}

// Wintel Version

/*

if( path.charAt( 1 ) == ':' && path.charAt( 2 ) == PATH_SEPARATOR ) {

return false;

}

*/

// No references to parent directory with ".."

for( int i = 0; i < path.length() - 1; i++ ) {

if( path.charAt( i ) == '.'

&& path.charAt( i + 1 ) == '.' ) {

return false;

}

}

return true;// Path's OK

}

Next comes the code implementing the methods of our remote interface (see Listing

54.9). Each calls checkPathName() on the path and then tries to open either a

FileInputStream or FileOutputStream as appropriate. Any exception that occurs while

obtaining a stream is rethrown as a RemoteException (although there is no reason the

interface cannot throw the appropriate exceptions). Once the stream has been opened,

a RemoteInputHandleImpl or RemoteOutputHandleImpl object is created as appropriate

with the just-opened stream. The handle is then returned to the caller.

Listing 54.9. The methods of the RemoteFileServerImpl class.

public RemoteInputHandle getInStream( String path )

throws java.rmi.RemoteException

{

FileInputStream file = null; // Used to hold file for input

// Log that we're opening a stream

System.err.println( "RFSI::getInStream( \"" + path + "\" )" );

// Check that the path name is legal or gripe

if( !checkPathName( path ) ) {

RemoteException e =

new RemoteException( "Invalid pathname '" + path + "'." );

throw e;

}

// Try and open a FileInputStream for the path

try {

file = new FileInputStream( path );

} catch( FileNotFoundException e ) {

// File doesn't exist, so throw remote exception with that message

RemoteException r =

new RemoteException( "File does not exist: "

+ e.getMessage() );

throw r;

} catch( IOException e ) {

// Problem opening file, so throw exception saying that

RemoteException r =

new RemoteException( "Error opening file: "

+ e.getMessage() );

throw r;

}

// Return value is a RemoteInputHandle for an RIH implementation

// object created with the file we just opened as it's input stream.

RemoteInputHandle retval =

new RemoteInputHandleImpl( file );

return retval;// Return handle to caller

}

public RemoteOutputHandle getOutStream( String path )

throws java.rmi.RemoteException

{

FileOutputStream file = null; // Used to hold file for output

// Log that we're opening a stream

System.err.println( "RFSI::getOutStream( \"" + path + "\" )" );

// Check that the path name is legal or gripe

if( !checkPathName( path ) ) {

RemoteException e =

new RemoteException( "Invalid pathname '" + path + "'." );

throw e;

}

// Try and open FileOutputStream for the path

try {

file = new FileOutputStream( path );

} catch( IOException e ) {

// Problem opening file for output, so throw exception saying so

RemoteException r =

new RemoteException( "Error opening file: "

+ e.getMessage() );

throw r;

}

// Return value is a RemoteOutputHandle for an ROH implementation

// object created with the file just opened as it's output stream

RemoteOutputHandle retval = new RemoteOutputHandleImpl( file );

return retval;// Return the handle

}

Finally, we come to the main() method, which can be used to start a standalone server

from the command line (see Listing 54.10). The first thing this method does is to

create a StubSecurityManager--a SecurityManager context appropriate for a

standalone remote object server. Next, main() creates a RemoteFileServerImpl object

and binds it to the name RFSI. If an exception occurs during object creation or binding,

the name of the exception is noted and the server exits.

Listing 54.10. The RemoteFileServerImpl.main() method.

public static void main( String args[] )

{

// Create and install stub security manager

System.setSecurityManager( new StubSecurityManager( ) );

try {

System.err.println( "RFSI::main: creating RFSI." );

// Create a new server implementation object

RemoteFileServerImpl i = new RemoteFileServerImpl( );

// Bind our server object to a name so clients may contact us.

/* The URL will be "rmi://host/RFSI", with host replaced with */

// the name of the host we're running on.

String name = "RFSI";

System.err.println( "RFSI::main: binding to name: " + name );

Naming.rebind( name, i );

} catch( Exception e ) {

// Problem creating server. Log exception and die.

System.err.println( "Exception creating server: "

+ e + "\n" );

e.printStackTrace( System.err );

System.exit( 1 );

}

}

}

The rfsClient Class

To demonstrate how to use our remote files, we now develop a very simple client that

opens a remote output file and writes a message to it (see Listing 54.11). An input

stream is obtained and the stream's contents are read back. The output filename is

defined as outputfile and the input filename defaults to inputfile (however, if an

argument is given on the command line, that name is used instead). The host

contacted is defined as the local host, but you can change the URL used to point to a

remote machine if you have access to more than one host.

Listing 54.11. The rfsClient class.

import java.io.*;

import java.rmi.*;

public class rfsClient

{

public static void main( String args[] ) {

System.setSecurityManager( new java.rmi.RMISecurityManager() );

// Contact remote file server running on same machine

String url = "rmi://localhost/";

// Default name of file to read

String infile = "inputfile";

// Try and open an output stream to a file called "outputfile"

try {

OutputStream out = new RemoteOutputStream( "outputfile");

PrintWriter ps = new PrintWriter( out );

ps.println( "Testing println on remote file." );

ps.println( new java.util.Date() );

ps.flush();

ps.close();

ps = null;

out = null;

} catch( Exception e ) {

System.err.println( "Error on getOutStream: " + e );

e.printStackTrace();

System.exit( 1 );

}

// If we were given a command line argument, use that as the

// input file name

if( args.length != 0 ) {

infile = args[ 0 ];

}

// Try and open an output stream on a file

try {

InputStream in = new RemoteInputStream( infile );

DataInputStream ds = new DataInputStream( in );

// Read each line of the file and print it out

try {

String line = ds.readLine( );

while( line != null ) {

System.err.println( "Read: " + line );

line = ds.readLine( );

} catch( EOFException e ) {

System.err.println( "EOF" );

}

} catch( Exception e ) {

System.err.println( "Error on getInStream: " + e );

e.printStackTrace( );

System.exit( 1 );

}

System.exit( 0 );// Exit gracefully

}

}

I hope this will help you.

Thanks

Bakrudeen

Technical Support Engineer

Sun MicroSystems Inc, India

bakrudeen_indts at 2007-6-29 1:27:00 > top of Java-index,Archived Forums,Java Programming...
# 4

> thanks rthomanek

> the jave program gets the node name and the input file

> name as the parameter. The applciaions require the

> file names as the result. do u mean a socket based

> server?

Well, socket would be the most natural solution. But you could actually use just anything, like CORBA or RMI.

Robert

rthomanek at 2007-6-29 1:27:00 > top of Java-index,Archived Forums,Java Programming...