Welcome to Bishnu`s JINI Tutorial

home      introduction       My Interest   My Favorites link      Photo gallery

 

Hello ExampleのプログラムをベースにNew Hello Exampleを作っていく

前回の解説ではHelloプログラムをどのように動かせるのかについて説明をしました。本説明はできるだけJINIのプログラムの構成を丁寧に説明しJINIを通じて分散コンピューティング の理解を深めていきたいのが目的の一つです。JINIに関してある程度知識がある人は本章を飛ばしてかましません。 では前章で登場したHello programの中殿辺を変えてどう変更していくのかについて説明したいと思います。
まず下記のプログラム郡のよいをします。自分が利用しているEditorに下記のプログラムを開いてください。
  • Client.java - Helloを利用するクライント
  • Server.java サーバプログラム
  • Proxy.java Helloインタフェースを実装するProxy
さて、上記のプログラム郡を少しづつ変更し、どのように変わったのかを理解して行きましょう。まずはServer.Javaの中身を見てみましょう。
import java.rmi.RemoteException;
import java.security.PrivilegedExceptionAction;
import javax.security.auth.Subject;
import javax.security.auth.login.LoginContext;
import net.jini.config.Configuration;
import net.jini.config.ConfigurationException;
import net.jini.config.ConfigurationProvider;
import net.jini.config.NoSuchEntryException;
import net.jini.core.lookup.ServiceID;
import net.jini.discovery.DiscoveryManagement;
import net.jini.discovery.LookupDiscovery;
import net.jini.export.Exporter;
import net.jini.export.ProxyAccessor;
import net.jini.id.Uuid;
import net.jini.id.UuidFactory;
import net.jini.jeri.BasicILFactory;
import net.jini.jeri.BasicJeriExporter;
import net.jini.jeri.tcp.TcpServerEndpoint;
import net.jini.lookup.JoinManager;
import net.jini.security.TrustVerifier;
import net.jini.security.proxytrust.ServerProxyTrust;

/**
 * Defines an application server that provides an implementation of the Hello
 * interface.
 *
 * The application uses the following arguments:
 *
 * [all] - All arguments are used as options when getting the configuration
 *
 * The application uses the following configuration entries, with component
 * com.sun.jini.example.hello.Server:
 *
 * discoveryManager
 *   type: DiscoveryManagement
 *   default: new LookupDiscovery(new String[] { "" }, config)
 *   Object used to discover lookup services to join.
 *
 * exporter
 *   type: Exporter
 *   default: none
 *   The object to use for exporting the server
 *
 * loginContext
 *   type: LoginContext
 *   default: null
 *   If non-null, specifies the JAAS login context to use for performing a JAAS
 *   login and supplying the Subject to use when running the server. If null,
 *   no JAAS login is performed.
 *
 * @author Sun Microsystems, Inc.
 */
public class Server implements Hello, ServerProxyTrust, ProxyAccessor {

    /**
     * If the impl gets GC'ed, then the server will be unexported.
     * Store the instance here to prevent this.
     */
    private static Server serverImpl;

    /* The configuration to use for configuring the server */
    protected final Configuration config;

    /** The server proxy, for use by getProxyVerifier */
    protected Hello serverProxy;

    /**
     * Starts and registers a server that implements the Hello interface.
     *
     * @param args options to use when getting the Configuration
     * @throws ConfigurationException if a problem occurs with the
     *	       configuration
     * @throws RemoteException if a remote communication problem occurs
     */
    public static void main(String[] args) throws Exception {
	serverImpl = new Server(args);
	serverImpl.init();
	System.out.println("Hello server is ready");
    }

    /**
     * Creates the server.
     *
     * @param configOptions options to use when getting the Configuration
     * @throws ConfigurationException if a problem occurs creating the
     *	       configuration
     */
    protected Server(String[] configOptions) throws ConfigurationException {
	config = ConfigurationProvider.getInstance
                       ( configOptions, (this.getClass()).getClassLoader() );
    }

    /**
     * Initializes the server, including exporting it and storing its proxy in
     * the registry.
     *
     * @throws Exception if a problem occurs
     */
    protected void init() throws Exception {
	LoginContext loginContext = (LoginContext) config.getEntry(
	    "com.sun.jini.example.hello.Server", "loginContext",
	    LoginContext.class, null);
	if (loginContext == null) {
	    initAsSubject();
	} else {
	    loginContext.login();
	    Subject.doAsPrivileged(
		loginContext.getSubject(),
		new PrivilegedExceptionAction() {
		    public Object run() throws Exception {
			initAsSubject();
			return null;
		    }
		},
		null);
	}
    }

    /**
     * Initializes the server, assuming that the appropriate subject is in
     * effect.
     */
    protected void initAsSubject() throws Exception {
	/* Export the server */
	Exporter exporter = getExporter();
	serverProxy = (Hello) exporter.export(this);

	/* Create the smart proxy */
	Proxy smartProxy = Proxy.create(serverProxy);

	/* Get the discovery manager, for discovering lookup services */
	DiscoveryManagement discoveryManager;
	try {
	    discoveryManager = (DiscoveryManagement) config.getEntry(
		"com.sun.jini.example.hello.Server", "discoveryManager",
		DiscoveryManagement.class);
	} catch (NoSuchEntryException e) {
            /* Use the public group */
	    discoveryManager = new LookupDiscovery(
		new String[] { "" }, config);
	}

	/* Get the join manager, for joining lookup services */
	JoinManager joinManager =
	    new JoinManager(smartProxy, null /* attrSets */, getServiceID(),
			    discoveryManager, null /* leaseMgr */, config);
    }

    /**
     * Returns the exporter for exporting the server.
     *
     * @throws ConfigurationException if a problem occurs getting the exporter
     *	       from the configuration
     * @throws RemoteException if a remote communication problem occurs
     */
    protected Exporter getExporter()
	throws ConfigurationException, RemoteException
    {
	return (Exporter) config.getEntry(
	    "com.sun.jini.example.hello.Server", "exporter", Exporter.class,
	    new BasicJeriExporter(TcpServerEndpoint.getInstance(0),
				  new BasicILFactory()));
    }

    /** Returns the service ID for this server. */
    protected ServiceID getServiceID() {
	return createServiceID();
    }

    /** Creates a new service ID. */
    protected static ServiceID createServiceID() {
	Uuid uuid = UuidFactory.generate();
	return new ServiceID(
	    uuid.getMostSignificantBits(), uuid.getLeastSignificantBits());
    }

    /** Implement the Hello interface. */
    public String sayHello() {
	return "Server Changed two times Hello, world!";
    }



    /**
     * Implement the ServerProxyTrust interface to provide a verifier for
     * secure smart proxies.
     */
    public TrustVerifier getProxyVerifier() {
	return new Proxy.Verifier(serverProxy);
    }

    /**
     * Returns a proxy object for this remote object.
     *
     * @return our proxy
     */
    public Object getProxy() {
        return serverProxy;
    }

}
確認の通り、ざっとJINIのコードが書かれていますが、詳しい解説は次回の解説にすることにし、今回は上記のプログラムの中で大事なところだけ解説します。Server.javaの198行目あたりをみてほしいですが、sayHello()メソッドを実装されています。そのメソッドは実はHelloServiceを実装したJINIのサービスになるわけですね。要するにHelloServiceの基本的な性質を持つのがこのメソッドです。 このメソッドの実装を変更すればサービス自体の本質が変わることになるわけです。これはJavaでクライント、サーバプログラミングあるいはRMIプログラミングを経験したひとにはわかりづらい話ではありません。ではSayHello()の中身を好きなように変えてください。これでServer.javaから送られるメセッジが変わったことになるわけですね。
今度はProxy.javaを見てみましょう。

/*
 *
 * Copyright 2005 Sun Microsystems, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * 	http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.sun.jini.example.hello;

import java.io.Serializable;
import java.rmi.RemoteException;
import net.jini.core.constraint.MethodConstraints;
import net.jini.core.constraint.RemoteMethodControl;
import net.jini.security.TrustVerifier;
import net.jini.security.proxytrust.ProxyTrustIterator;
import net.jini.security.proxytrust.SingletonProxyTrustIterator;
import net.jini.security.proxytrust.TrustEquivalence;

/** Define a smart proxy for the server. */
class Proxy implements Serializable, Hello {

    private static final long serialVersionUID = 2L;

    /** The server proxy */
    final Hello serverProxy;

    /**
     * Create a smart proxy, using an implementation that supports constraints
     * if the server proxy does.
     */
    static Proxy create(Hello serverProxy) {
	return (serverProxy instanceof RemoteMethodControl)
	    ? new ConstrainableProxy(serverProxy)
	    : new Proxy(serverProxy);
    }

    Proxy(Hello serverProxy) {
	this.serverProxy = serverProxy;
    }

    public boolean equals(Object o) {
	return getClass() == o.getClass()
	    && serverProxy.equals(((Proxy) o).serverProxy);
    }

    public int hashCode() {
	return serverProxy.hashCode();
    }

    /** Implement Hello. */
    public String sayHello() throws RemoteException {
	System.out.println("Calling sayHello in smart proxy");
	return serverProxy.sayHello();
    }

	public int calculate(int a, int b) throws RemoteException {
	System.out.println("Calling calculate in smart proxy");
	return serverProxy.calculate(a, b);
    }

    /** A constrainable implementation of the smart proxy. */
    private static final class ConstrainableProxy extends Proxy
	implements RemoteMethodControl
    {
        private static final long serialVersionUID = 2L;

	ConstrainableProxy(Hello serverProxy) {
	    super(serverProxy);
	}

	/** Implement RemoteMethodControl */

	public MethodConstraints getConstraints() {
	    return ((RemoteMethodControl) serverProxy).getConstraints();
	}

	public RemoteMethodControl setConstraints(MethodConstraints mc) {
	    return new ConstrainableProxy(
		(Hello) ((RemoteMethodControl) serverProxy).setConstraints(
		    mc));
	}

	/*
	 * Provide access to the underlying server proxy to permit the
	 * ProxyTrustVerifier class to verify the proxy.
	 */
	private ProxyTrustIterator getProxyTrustIterator() {
	    return new SingletonProxyTrustIterator(serverProxy);
	}
    }

    /** A trust verifier for secure smart proxies. */
    final static class Verifier implements TrustVerifier, Serializable {

        private static final long serialVersionUID = 2L;

	private final RemoteMethodControl serverProxy;

	/**
	 * Create the verifier, throwing UnsupportedOperationException if the
	 * server proxy does not implement both RemoteMethodControl and
	 * TrustEquivalence.
	 */
	Verifier(Hello serverProxy) {
	    if (serverProxy instanceof RemoteMethodControl &&
		serverProxy instanceof TrustEquivalence)
	    {
		this.serverProxy = (RemoteMethodControl) serverProxy;
	    } else {
		throw new UnsupportedOperationException();
	    }
	}

	/** Implement TrustVerifier */
	public boolean isTrustedObject(Object obj, TrustVerifier.Context ctx)
	    throws RemoteException
	{
	    if (obj == null || ctx == null) {
		throw new NullPointerException();
	    } else if (!(obj instanceof ConstrainableProxy)) {
		return false;
	    }
	    RemoteMethodControl otherServerProxy =
		(RemoteMethodControl) ((ConstrainableProxy) obj).serverProxy;
	    MethodConstraints mc = otherServerProxy.getConstraints();
	    TrustEquivalence trusted =
		(TrustEquivalence) serverProxy.setConstraints(mc);
	    return trusted.checkTrustEquivalence(otherServerProxy);
	}
    }
}
上記のプログラムProxy.javaはHelloのSmartProxyとての役割をします。sayHello()メソッドの具体的な実装ははServer.javaの方ですることになりますが、一様ProxyのほうでもImplementsしなければなりません。ですので、確認の通りプログラムのClass定義のところでimplements Helloと書かれています。但し、sayHelloの具体的な定義はProxy.javaではなくServer.javaの方でやっていることに注目して欲しいです。

変更したプログラムをコンパイルする

cd %JINI_HOME%\source\src\com\sun\jini\example\hello

そこで下記の順番でAntのタスクを実行する:

  • ant clean
  • ant
  • ant this.jars
  • Steps

    1. クラスサーバー(Htttp Server)を動かす

    cd %JINI_HOME%\source\src\com\sun\jini\example\hello
    start scripts\httpd.bat (これはCommand promptで動かす)うまくいったら以下のようながめんが出ます。

    2. 以下のコマンドを順番に打ってください。

    (これも%JINI_HOME%\source\src\com\sun\jini\example\helloのところで動かすこと)
  • a. start scripts\jrmp-reggie

  • b. start scripts\confirming-jeri-server(helloぷろぐらむのサーバー)

  • c. start scripts\client (クライントの起動)
  • うまくいったら変更したサービスを利用することができると思います。

    以上で変更したhelloのプログラムを動かすことが完了します

     http://www.wakhok.ac.jp/~gautam
    page design by Gautam
    send comments to gautam@wakhok.ac.jp