// ChatOlioRMI.java import java.rmi.*; import java.rmi.server.*; import java.util.concurrent.LinkedBlockingQueue; import java.util.TreeMap; import java.util.concurrent.TimeUnit; public class ChatOlioRMI extends UnicastRemoteObject implements ChatLiittymaRMI { // asiakkaille lähtevien viestijonojen kokoelma private TreeMap> asiakkaat; // konstruktori luo viestijonojen joukon public ChatOlioRMI() throws RemoteException { asiakkaat = new TreeMap>(); } // liittyy (rekisteröityy) keskusteluun public synchronized boolean liity(String tunnus) throws RemoteException { // varattu tunnus if (asiakkaat.containsKey(tunnus)) return false; asiakkaat.put(tunnus, new LinkedBlockingQueue()); System.out.println(tunnus + " liittyi"); return true; } // erotaan keskustelusta public synchronized boolean eroa(String tunnus) throws RemoteException { System.out.println(tunnus + " eroaa"); return asiakkaat.remove(tunnus) != null; } // lisää viestin kaikkien asiakkaiden lähetysjonoon (paitsi lähettäjän) public synchronized void lahetaViesti(String tunnus, String viesti) throws RemoteException { System.out.println(tunnus + ":"); System.out.println(viesti); // laitetaan viesti kaikkien muiden asiakkaiden jonoihin for (String as : asiakkaat.keySet()) { if (! as.equals(tunnus)) { asiakkaat.get(as).offer(teeViesti(tunnus, viesti)); } } } /** * Lisää tunnuksen viestin joka rivin alkuun. * @param tunnus tunnus joka lisätään * @param viesti täydennettävä viesti * @return täydennetty viesti */ private String teeViesti(String tunnus, String viesti) { return viesti.replaceAll("^", tunnus + "> "); } // lukee seuraavan viestin, odottaa korkeintaan timeout millisekuntia // jollei viestiä ole tullut, palauttaa null // tunnus käytetään oikean lähetysjonon valintaan // timeout = 0: ei odota ollenkaan // timeout = -1: odottaa ikuisesti public String lueViesti(String tunnus, int timeout) throws RemoteException { // ei vielä kovin kaunis ratkaisu if (timeout == -1) timeout = 7*24*60*60*1000; // viikko on noin ikuisesti // turvaratkaisuna jos joku yrittaa pollata liian usein: if (timeout < 20) timeout = 20; LinkedBlockingQueue jono = asiakkaat.get(tunnus); if (jono == null) return null; try { return jono.poll(timeout, TimeUnit.MILLISECONDS); } catch (InterruptedException e) { return null; } } // lueViesti() } // chatolio