RMI Appletサンプル

そのうち説明書くから許して・・・(汗)

構成(ls -R)

build.xml    classes      public_html  src

classes:
bbs

classes/bbs:
BBS.class           BBSApplet.class     BBSImpl_Stub.class  Message.class
BBSApplet$1.class   BBSImpl.class       BBSServer.class
BBSApplet$2.class   BBSImpl_Skel.class  BBSStore.class

public_html:
bbs         index.html

public_html/bbs:
BBS.class           BBSApplet$2.class   BBSImpl_Stub.class
BBSApplet$1.class   BBSApplet.class     Message.class

src:
bbs

src/bbs:
BBS.java        BBSImpl.java    BBSStore.java
BBSApplet.java  BBSServer.java  Message.java

リモートインターフェイス

package bbs;

import java.util.List;
import java.rmi.Remote; 
import java.rmi.RemoteException; 

/**
 * BBS のリモートインターフェイス。
 */
public interface BBS extends Remote {
    /**
     * BBS にメッセージを登録する。
     * @param message メッセージ
     */
    public void addMessage(Message message) throws RemoteException;
    /**
     * BBS からメッセージ一覧を取得する。
     * @return メッセージ一覧
     */
    public List getMessages() throws RemoteException;
}

インターフェイスの実装

package bbs;

import java.util.List;
import java.util.Date;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

public class BBSImpl extends UnicastRemoteObject implements BBS {
    public BBSImpl() throws RemoteException {
    }
    /**
     * BBS にメッセージを登録する。
     * @param message メッセージ
     */
    public void addMessage(Message message) {
	message.setTime(new Date());
	BBSStore.getInstance().addMessage(message);
    }

    /**
     * BBS からメッセージ一覧を取得する。
     * @return メッセージ一覧
     */
    public List getMessages() {
	return BBSStore.getInstance().getMessages();
    }
}

BBS本体

package bbs;

import java.util.List;
import java.util.ArrayList;

public class BBSStore {
    /** 保存するメッセージ数 */
    public static final int SIZE = 20;
    /** シングルトンインスタンス */
    private static BBSStore instance = new BBSStore();
    /** メッセージの保存先 */
    private List messages = new ArrayList();
    /**
     * BBSStoreのインスタンスを取得する。
     * @return BBSStore
     */
    public static BBSStore getInstance() {
	return instance;
    }

    private BBSStore() {
    }

    /**
     * BBS にメッセージを登録する。
     * @param message メッセージ
     */
    public synchronized void addMessage(Message message) {
	// ここではメモリに置くだけ。再起動しても保存したければ、
	// ファイルに書いても良い。
	messages.add(message);
	if (messages.size() > SIZE) {
	    messages.remove(0);
	}
    }

    /**
     * BBS からメッセージ一覧を取得する。
     * @return メッセージ一覧
     */
    public List getMessages() {
	return messages;
    }
}

サーバプログラム

package bbs;

import java.rmi.Naming;
import java.rmi.registry.LocateRegistry;

public class BBSServer {
    public static void main(String args[]) throws Exception {
	LocateRegistry.createRegistry(1099);
	BBSImpl bbs = new BBSImpl();
	Naming.rebind("BBS", bbs);
    }
}

メッセージエンティティ

package bbs;

import java.io.Serializable;
import java.util.Date;

public class Message implements Serializable {
    /** 発言者 */
    private String name;
    /** 時刻 */
    private Date time;
    /** メッセージ */
    private String text;

    /**
     * 発言者を設定する。
     * @param name 発言者 
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 発言者を取得する。
     * @return 発言者
     */
    public String getName() {
        return name;
    }

    /**
     * 時刻を設定する。
     * @param time 時刻 
     */
    public void setTime(Date time) {
        this.time = time;
    }

    /**
     * 時刻を取得する。
     * @return 時刻
     */
    public Date getTime() {
        return time;
    }

    /**
     * メッセージを設定する。
     * @param text メッセージ 
     */
    public void setText(String text) {
        this.text = text;
    }

    /**
     * メッセージを取得する。
     * @return メッセージ
     */
    public String getText() {
        return text;
    }
}

クライアントアプレット

package bbs;

import java.util.List;
import java.util.Iterator;
import java.rmi.Naming;
import java.awt.Container;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JApplet;
import javax.swing.BoxLayout;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JLabel;
import javax.swing.JScrollPane;

public class BBSApplet extends JApplet {
    JTextArea bbsArea = new JTextArea(40, 40);
    JTextField nameArea = new JTextField(30);
    JTextArea inputArea = new JTextArea(10, 40);
    BBS bbs;
    public void init() {
	Container pane = getContentPane();
	pane.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS));
	pane.add(new JScrollPane(bbsArea));
	JButton updateButton = new JButton("更新");
	updateButton.addActionListener(new ActionListener() {
		public void actionPerformed(ActionEvent e) {
		    updateBBS();
		}
	    });
	pane.add(updateButton);
	JPanel p = new JPanel();
	p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));
	p.add(new JLabel("名前:"));
	p.add(nameArea);
	pane.add(p);
	pane.add(new JScrollPane(inputArea));
	JButton inputButton = new JButton("書き込み");
	inputButton.addActionListener(new ActionListener() {
		public void actionPerformed(ActionEvent e) {
		    writeBBS();
		}
	    });
	pane.add(inputButton);
	try {
	    bbs = (BBS) Naming.lookup("//" + getCodeBase().getHost() + "/BBS");
	} catch (Exception e) {
	    e.printStackTrace();
	    bbsArea.append(e.toString());
	}
	updateBBS();
    }
    public void updateBBS() {
	if (bbs == null) {
	    return;
	}
	List messages;
	try {
	    messages = bbs.getMessages();
	} catch (Exception e) {
	    e.printStackTrace();
	    bbsArea.append(e.toString());
	    return;
	}
	bbsArea.setText("");
	for (Iterator i = messages.iterator(); i.hasNext(); ) {
	    Message m = (Message) i.next();
	    bbsArea.append(m.getName() + ": " + m.getTime() + "\n");
	    bbsArea.append(m.getText());
	    bbsArea.append("\n----------\n");
	}
    }
    public void writeBBS() {
	if (bbs == null) {
	    return;
	}
	Message m = new Message();
	m.setName(nameArea.getText());
	m.setText(inputArea.getText());
	inputArea.setText("");
	try {
	    bbs.addMessage(m);
	} catch (Exception e) {
	    e.printStackTrace();
	    bbsArea.append(e.toString());
	}
	updateBBS();
    }
}

build.xml

<project name="bbs" default="compile" basedir=".">

  <!-- set global properties for this build -->
  <property name="src" value="src"/>
  <property name="build" value="classes"/>
  <property name="apidoc" value="docs"/>
  <path id="project.class.path">
    <pathelement path="${build}/"/>
    <pathelement path="${java.class.path}/"/>
  </path>

  <target name="init">
    <!-- Create the time stamp -->
    <tstamp/>
    <!-- Create the build directory structure used by compile -->
    <mkdir dir="${build}"/>
    <mkdir dir="${apidoc}"/>
  </target>

  <target name="compile" depends="init">
    <!-- Compile the java code from ${src} into ${build} -->
    <javac srcdir="${src}" destdir="${build}" encoding="Shift_JIS" depend="yes" deprecation="on">
      <classpath refid="project.class.path"/>
    </javac>
    <rmic classname="bbs.BBSImpl" base="${build}"/>
  </target>

  <target name="copy" depends="compile">
    <copy todir="public_html/">
      <fileset dir="${build}">
        <include name="bbs/BBSApplet*.class"/>
        <include name="bbs/*_Stub.class"/>
        <include name="bbs/Message.class"/>
        <include name="bbs/BBS.class"/>
      </fileset>
    </copy>
  </target>

  <target name="doc" depends="init">
    <!-- Compile the java code from ${src} into ${build} -->
    <javadoc sourcepath="${src}" destdir="${apidoc}" Encoding="Shift_JIS" packagenames="bbs.*">
      <classpath refid="project.class.path"/>
    </javadoc>
  </target>

  <target name="clean">
    <!-- Delete the ${build} and ${dist} directory trees -->
    <delete dir="${build}"/>
    <delete dir="${dist}"/>
  </target>
</project>

サーバの実行

java -Djava.rmi.server.hostname=www.wizard-limit.net bbs.BBSServer

false@wizard-limit.net