java.rmi.Remote

目的
RMIを使ったファイル転送を行う。

関連クラス

今回のソース
//////////////////// FileTransfer.java ////////////////////
import java.rmi.Remote;
import java.rmi.RemoteException;

/**
	リモートメソッド定義

	@version	1.00 06/13/1999
	@author		Takahiro Shigemoto
*/
public interface FileTransfer extends Remote
{
	public String	getTextFile(String file_name) throws RemoteException;
	public byte[]	getBinaryFile(String file_name) throws RemoteException;
	public String[]	getFileList(String path) throws RemoteException;
}
////////////////////////////////////////////////////////////

//////////////////// FileTransferClient.java ////////////////////
import java.io.*;
import java.rmi.*;

/**
	ファイル転送クライアント

	@version	1.00 06/13/1999
	@author		Takahiro Shigemoto
*/
public class FileTransferClient
{
	/**
		操作(ファイルリスト、ファイルの取得)とファイル名を指定する。
		@param	operation	操作
		@param	file_name	ファイル名
	*/
	public FileTransferClient(String operation,String file_name)
	{
		try
		{
			// リモートオブジェクトの取得
			FileTransfer obj = (FileTransfer)Naming.lookup("rmi:///FileTransferServer");

			// フルパスファイル名から、ファイル名だけを取り出す。
			File file = new File(file_name);

			// 各操作
			if(operation.compareTo("l") == 0)
				printList(obj.getFileList(file_name));
			else if(operation.compareTo("a") == 0)
				saveTextFile(file.getName(),obj.getTextFile(file_name));
			else if(operation.compareTo("b") == 0)
				saveBinaryFile(file.getName(),obj.getBinaryFile(file_name));
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
	}

	/**
		ファイルリストを表示する。

		@param list	ファイルリスト
	*/
	public void printList(String list[])
	{
		for(int i=0;i<list.length;i++)
		{
			System.out.println(list[i]);
		}
	}

	/**
		テキストファイルを保存する。

		@param	file_name	保存するファイル名
		@param	text		テキスト
	*/
	public void saveTextFile(String file_name,String text)
	{
		try
		{
			// ストリームの作成とファイルの書き込み
			BufferedWriter writer = new BufferedWriter(new FileWriter(file_name));
			writer.write(text,0,text.length());

			// ストリームを閉じる
			writer.flush();
			writer.close();
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
	}

	/**
		バイナリファイルを保存する。

		@param	file_name	保存するファイル名
		@param	binary		バイナリデータ
	*/
	public void saveBinaryFile(String file_name,byte binary[])
	{
		try
		{
			// ストリームの作成とファイルの書き込み
			BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream(file_name));
			output.write(binary,0,binary.length);

			// ストリームを閉じる
			output.flush();
			output.close();
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
	}

	public static void main(String args[])
	{
		if(args.length != 2)
			Usage();

		new FileTransferClient(args[0],args[1]);
	}

	//	Usage
	private static void Usage()
	{
		System.out.println("Usage:	java FileTransferClient <option> <FileName>");
		System.out.println("		--options--");
		System.out.println("l:	Print File List, Please specify Directory.");
		System.out.println("a:	Get  Ascii File, Please specify FileName.");
		System.out.println("b:	Get Binary File, Please specify FileName.");

		System.exit(0);
	}
}
////////////////////////////////////////////////////////////

//////////////////// FileTransferImpl.java ////////////////////
import java.io.*;
import java.rmi.*;
import java.rmi.server.UnicastRemoteObject;

/**
	FileTransfer実装クラス

	@version	1.00 06/13/1999
	@author		Takahiro Shigemoto
*/
public class FileTransferImpl extends UnicastRemoteObject implements FileTransfer
{
	// サーバ側の改行コード
	private final String line_separator = System.getProperty("line.separator");

	/**
		デフォルトコンストラクタ(Export)
	*/
	public FileTransferImpl() throws RemoteException
	{
		super();
	}

	/**
		テキストファイルを読み込む。

		@param	file_name	読み込むファイル名
		@return	成功した時には読み込まれたテキストを、失敗した時にはnullを返す。
	*/
	public String getTextFile(String file_name)
	{
		try
		{
			// テキスト格納用バッファ
			StringBuffer buffer = new StringBuffer();

			// ストリームの構築
			BufferedReader reader = new BufferedReader(new FileReader(file_name));

			// テキストファイルの読み込み
			String buf;
			while((buf = reader.readLine()) != null)
			{
				buffer.append(buf + line_separator);
			}
			reader.close();

			return(buffer.toString());
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
			return("");
		}
	}

	/**
		バイナリファイルを読み込む。

		@param	file_name	読み込むファイル名
		@param	成功した時には読み込まれたバイナリデータを、失敗した時にはnullを返す。
	*/
	public byte[] getBinaryFile(String file_name)
	{
		try
		{
			// バイナリファイルのサイズ分のバッファを確保する
			File file = new File(file_name);
			byte buffer[] = new byte[(int)file.length()];

			// ストリームの構築と読み込み
			BufferedInputStream input = new BufferedInputStream(new FileInputStream(file_name));
			input.read(buffer,0,buffer.length);
			input.close();

			return(buffer);
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
			return(null);
		}
	}

	/**
		ファイルリストを表示する。

		@param path	ファイルリストを取得するディレクトリのパス
		@return	成功した時にはファイルリストを、失敗した時にはnullを返す。
	*/
	public String[] getFileList(String path)
	{
		try
		{
			File directory = new File(path);

			// ディレクトリであれば、リストを返す。
			if(directory.isDirectory())
				return(directory.list());
			else
				return(null);
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
			return(null);
		}
	}
}
////////////////////////////////////////////////////////////

//////////////////// FileTransferServer.java ////////////////////
import java.rmi.*;

/**
	ファイル転送サーバ

	@version	1.00 06/13/1999
	@author		Takahiro Shigemoto
*/
public class FileTransferServer
{
	public static void main(String args[])
	{
		// セキュリティマネージャの設定
		if(System.getSecurityManager() == null)
			System.setSecurityManager(new RMISecurityManager());

		try
		{
			// RMIサーバへ登録
			FileTransferImpl file_transfer = new FileTransferImpl();
			Naming.rebind("rmi:///FileTransferServer",file_transfer);
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
	}
}
////////////////////////////////////////////////////////////
Source is here. (ZIP Format,20780Byte,Shift-JIS)

コンパイル&実行
[コンパイル]
javac *.java

[リモートオブジェクトのためのスタブとスケルトンを生成]
rmic FileTransferImpl

[RMIRegistryの起動]
(Windows)start rmiregistry (Unix)rmiregistry &

[サーバの起動]
java -Djava.rmi.server.codebase=file:///c:/〜(classファイルへのパス)
   -Djava.security.policy=policy FileTransferServer(一行に続けて)

[クライアントの起動]
java FileTransferClient l C:\

説明
(概略)

RMIでファイルを転送してみよう! というプログラムです(^^;
前に書いた、SocketでFTPサーバに接続してファイルを取得する
というプログラムよりも大分簡単だったという印象があります。
ただ、RMIの取り決めみたいなものが面倒ですね。

FileTransferClientのコードを見る限り、
ネットワークを意識させるようなところは無く、
メソッド呼び出しだけで通信出来るあたりが、
かなりユーザーフレンドリなライブラリですね。

今回はついでに、javadoc形式のコメントを入れました。
/** 〜 */というものですが、見てもらえれば分かると思うので、
この機会に、使ってみましょう。
(アーカイブのdocsディレクトリ以下に、ドキュメントを入れときました。)

(サンプルプログラムの説明)

リモートメソッド定義
クライアントから呼ぶことの出来る、
リモートオブジェクトのメソッドを定義します。
interfaceなので、メソッドの実際の中身は記述しません。
また、リモートメソッドは、必ずRemoteExceptionを
throwするようにしておかなければなりません。
(FileTransfer)Naming.lookup("rmi:///FileTransferServer");
RMIRegistryに登録されているリモートオブジェクトを取得します。
参照方法は、rmi://<hostname>:<port>/<Service Name> です。
今回の場合は、ローカル用に作られているので、
ホスト名及びポートの指定はありません。
public class FileTransferImpl extends UnicastRemoteObject implements FileTransfer
FileTransfer interfaceの実装クラスであるFileTransferImplクラスを定義しています。
つまり、このクラスでは、メソッドの中身を記述しています。
また、UnicastRemoteObjectクラスを継承することで、
常時起動のリモートオブジェクトとすることが出来ます。
Naming.rebind("rmi:///FileTransferServer",file_transfer);
リモートオブジェクトを、RMIRegistryに登録します。
rmiのURLに関しては、リモートオブジェクトを参照する時と同じです。
bindでは無くrebindを使用する理由は、同じ登録名を何度も使用するためです。