package platform.plugins.installables.application; import network.platform.PlatformMessagesReceptor; import platform.servicesregister.ServicesRegisterManager; import network.platform.PlatformMessagesEmitter; import platform.servicesregister.ServiceClosedException; import platform.servicesregister.ServiceInUseException; import model.interfaces.platform.IPlatformPlugin; import util.Parameters; import model.osagaia.BCModel; import network.NetworkEmitterContainer; import network.NetworkReceptorContainer; import util.NetworkAddress; import network.platform.NetworkPlatformMessage; import network.AddressesChecker; import java.util.Timer; import java.util.TimerTask; /** * Plugin for allowing BCs to send command to local or distant platforms * and get the replies from these platforms. * * @author Dalmau */ public class BCCommandSenderPlugin implements IPlatformPlugin { private PlatformMessagesReceptor boiteDeReponses; private PlatformMessagesEmitter envoi; private AddressesChecker addressesChecker; private NetworkReceptorContainer rec; private boolean arret; private boolean timeOut; /** * Construction :<br> * Creates a mailbox manager for BCs to find the replies.<br> * Starts a server on a special port number to get the replies from platforms. */ public BCCommandSenderPlugin() { NetworkEmitterContainer nec = (NetworkEmitterContainer)ServicesRegisterManager.platformWaitForService(Parameters.NETWORK_EMISSIONS_CONTAINER); envoi = nec.getPlatformMessagesEmitter(); // Mise en place des mecanismes permettant aux plugins de la PF de recevoir les reponses // aux commandes qu'ils envoient aux autres PF ou la PF locale rec = (NetworkReceptorContainer)ServicesRegisterManager.platformWaitForService(Parameters.NETWORK_RECEPTIONS_CONTAINER); boiteDeReponses = rec.getPlatformMessagesReceptor(); // creation d'un thread pour gerer les receptions IP pour les plugins addressesChecker = (AddressesChecker)ServicesRegisterManager.platformWaitForService(Parameters.NETWORK_ADDRESSES); try { // enregistrer le service d'acces aux commandes de PF pour les BC ServicesRegisterManager.registerService(Parameters.APPLICATION_COMMAND_SERVICE, this); } catch (ServiceInUseException mbiue) { System.err.println("BCCommandSenderPlugin service created twice"); } } /** * Starts the plugin: waiting for replies and putting them in mailboxes for BCs */ public void startPlugin() { arret = false; } /** * Stops the main loop of the plugin. */ public void stopPlugin() { try { ServicesRegisterManager.removeService(Parameters.APPLICATION_COMMAND_SERVICE); } catch (ServiceClosedException sce) {} try { ServicesRegisterManager.removeService(Parameters.APPLICATION_COMMAND_SERVICE); } catch (ServiceClosedException sce) { } arret = true; } /** * Send a command to a Kalimucho platform * @param demandeur the BC which sends the command * @param cmd command to send * @param destinataire address of the PF to send this message to * @throws InterruptedException if the BC is stopped while sending a command */ public void sendCommand(BCModel demandeur, String cmd, NetworkAddress destinataire) throws InterruptedException { synchronized (demandeur) { if (destinataire != null) { if (destinataire.isKnown()) { // l'adresse est correcte if (addressesChecker.isPresentAddress(destinataire)) { // la PF designee est la PF locale sendLocalCommand(demandeur, cmd); } else { // la PF designee est distante NetworkPlatformMessage msg = new NetworkPlatformMessage(Parameters.SUPERVISOR, destinataire.getNormalizedAddress()); msg.addContent(cmd); msg.setReplyTo(demandeur.getName()); envoi.postMessage(msg); // message envoye par reseau au superviseur distant } } } } } /** * Send a command to the local Kalimucho platform * @param demandeur the BC which sends the command * @param cmd command to send * @throws InterruptedException if the BC is stopped while sending a command */ public void sendLocalCommand(BCModel demandeur, String cmd) throws InterruptedException { synchronized (demandeur) { NetworkPlatformMessage msg = new NetworkPlatformMessage(Parameters.SUPERVISOR, "localhost"); msg.addContent(cmd); msg.setReplyTo(demandeur.getName()); msg.setFinalAddress("local"); rec.getPlatformMessagesReceptor().deposerMessage(msg); // message directement depose dans la BaL du superviseur } } /** * Used by a BC to register itself as a listener for platforms replies * @param ecouteur the BC which wants to get platforms' replies */ public synchronized void addReplyListener(String ecouteur) { boiteDeReponses.inscription(ecouteur); } /** * Used by a BC to unregister itself as a listener for platforms replies * @param ecouteur the BC which wants to unregister itself */ public synchronized void removeReplyListener(String ecouteur) { boiteDeReponses.desinscription(ecouteur); } /** * Used by the BCs to get the replies from platforms * @param demandeur the BC which waits for reply * @param attente time out (in ms) for waiting for reply * @return the platform's replie * @throws InterruptedException if the BC is stopped by the platform */ public PlatformReplyMessage getPlatformReply(BCModel demandeur, int attente) throws InterruptedException { synchronized (demandeur) { String own = demandeur.getName(); NetworkPlatformMessage recu = null; Timer delai = new Timer(); timeOut = false; delai.schedule(new TimeOut(own), attente); recu = boiteDeReponses.retirerMessageInterruptible(own); delai.cancel(); if (recu != null) return new PlatformReplyMessage(recu); else return null; } } private class TimeOut extends TimerTask { private String pour; public TimeOut(String own) { pour = own; } public void run() { timeOut = true; cancel(); boiteDeReponses.arreterAttenteMessage(pour); } } }