/*
 * LOGICAL-PARADOX.ORG
 * Copyright (C)2004 satoshi akabane(akabane@logical-paradox.org)
 * $Id: RMILookup.java,v 1.9 2005/10/12 16:39:05 rampil Exp $
 */
package org.logical_paradox.rss.lookup.impl;

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.Remote;
import java.rmi.RemoteException;

import org.logical_paradox.rss.Service;
import org.logical_paradox.rss.dsr.RSSDistributedServiceRegistry;
import org.logical_paradox.rss.lookup.Lookup;

/**
 * RMIで実装された、分散リソースネットワーク発見サービス
 * サービスの管理にrmiregistryを使用する．
 * 
 * @author satoshi akabane@logical-paradox.org
 * @version $Revision: 1.9 $
 */
public class RMILookup implements Lookup {
	/** バインドターゲット */
	private String bindTarget;
	/** 分散サービスレジストリ */
	private RSSDistributedServiceRegistry dsr;

	/**
	 * コンストラクタ
	 * @param bt バインドターゲット(この実装の場合はdsruri)
	 */
	public RMILookup(String bt) throws MalformedURLException, RemoteException, NotBoundException {
		// 分散サービスレジストリをロードする
		dsr = (RSSDistributedServiceRegistry)Naming.lookup(bt);
		bindTarget = bt;
	}
	/**
	 * コンストラクタ
	 * @throws Exception 処理されなかった例外
	 */
	public RMILookup() throws Exception {
	}
	/**
	 * 分散サービスをバインドします．
	 * バインド先は，広域分散リソースネットワークが決定します．
	 * @return 実際にバインドされた際の識別文字列
	 * @throws Exception バインドに失敗した
	 */
	public String bind(int type, Object o) throws Exception {
		Service r = (Service)o;

		// 分散サービスレジストリに対して，新しいサービスを登録する
		String node = dsr.bind(type, r);
		// RMIレジストリにサーバーを登録する
		Naming.rebind(node, r);

		return node;
	}
	/**
	 * 分散サービスをアンバインドします．
	 * @param type サービスのタイプ
	 * @param name 登録解除したいノード名
	 * @throws Exception アンバインドに失敗した
	 */
	public void unbind(int type, String name) throws Exception {
		dsr.unbind(type, name);
		Naming.unbind(name);
	}
	/**
	 * DSRをレジストリに登録する
	 * @param stub DSRのインスタンス
	 * @throws Exception 登録に失敗した
	 */
	public void register(RSSDistributedServiceRegistry stub) throws Exception {
		Naming.rebind(stub.getName(), stub);
		dsr = stub;
	}
	/**
	 * 広域分散リソースネットワークから，特定の種類のサービスを発見します．
	 * @param name 発見するサービスの種類
	 * @return 発見されたサービスのスタブ
	 * @throws Exception 発見に失敗した
	 */
	public Object lookup(int type) throws Exception {
		// DSRに問い合わせる
		return dsr.getService(type);
	}
	/**
	 * 指定ノードIDのサービスを返します．
	 * @param nodeId ノードID
	 * @return サービスのスタプ
	 * @throws Exception ルックアップに失敗した
	 */
	public Service lookup(String nodeId) throws Exception {
		if(dsr.getName().equals(nodeId)) {
			return dsr;
		} else {
			return dsr.getService(nodeId);
		}
	}
	/**
	 * この発見サービスのバインドターゲット(接続先ノード)名を返す
	 * @return バインドターゲット名
	 */
	public String getBindTargetName() {
		return bindTarget;
	}
	/**
	 * サービス名のリストを取得する
	 * @param type サービスのタイプ
	 * @return サービス名の配列
	 * @throws Exception 一覧処理に失敗した際に発生する例外
	 */
	public String[] services(int type) throws Exception {
		return dsr.services(type);
	}
	/**
	 * この発見サービスのバインドターゲットに対して、ルーティングテーブルの更新を指示する
	 * @throws Exception 更新処理中に発生した例外
	 */
	public void configure() throws Exception {
		dsr.configure();
	}
	/**
	 * リモート参照をお互いに共有する
	 * @param stub 登録してもらうスタブ
	 * @throws RemoteException 登録に失敗した
	 */
	public Remote hug(Service stub) throws RemoteException {
		dsr.bind(RSSDistributedServiceRegistry.RSS_SERVID_SERVICE_LOCATER, stub);
		return dsr;
	}
	/**
	 * リモート参照をお互いに共有する
	 * 登録名を明示的に指定できる
	 * @param stub 登録してもらうスタブ
	 * @param name サービス名
	 * @return RemoteException 登録に失敗した
	 */
	public Remote hug(String name, Service stub) throws RemoteException {
		dsr.bind(RSSDistributedServiceRegistry.RSS_SERVID_SERVICE_LOCATER, name, stub);
		return dsr;
	}
}
