package org.openiot.cupus.mobile.entity.mobilebroker; import android.content.Context; import org.openiot.cupus.artefact.Announcement; import org.openiot.cupus.artefact.Publication; import org.openiot.cupus.artefact.Subscription; import org.openiot.cupus.entity.NetworkEntity; import org.openiot.cupus.entity.mobilebroker.MobileBrokerInterface; import org.openiot.cupus.entity.subscriber.NotificationListener; import org.openiot.cupus.message.Message; import org.openiot.cupus.message.external.AnnounceMessage; import org.openiot.cupus.message.external.MobileBrokerDisconnectMessage; import org.openiot.cupus.message.external.PublishMessage; import org.openiot.cupus.message.external.SubscribeMessage; import org.openiot.cupus.mobile.util.AndroidLogWriter; import org.openiot.cupus.mobile.util.Utils; import org.openiot.cupus.util.ReadingWritingXML; import java.io.File; import java.io.FileInputStream; import java.util.ArrayList; import java.util.List; import java.util.Properties; import java.util.UUID; /** * Created by kpripuzic on 1/21/14. */ public abstract class AbstractMobileBroker extends NetworkEntity implements MobileBrokerInterface { //List of all locally created Publications protected ArrayList<Publication> allPubs = new ArrayList<Publication>(); // List od all locally active Publications protected ArrayList<Publication> activePubs = new ArrayList<Publication>(); protected ArrayList<Publication> outboxPubs = new ArrayList<Publication>(); protected List<Subscription> allSubs = new ArrayList<Subscription>(); // List od all active Subscriptions protected List<Subscription> activeSubs = new ArrayList<Subscription>(); protected List<Subscription> outboxSubs = new ArrayList<Subscription>(); protected NotificationListener notificationListener; protected List<Publication> publicationList = new ArrayList<Publication>(); // List od all active Annoncements protected ArrayList<Announcement> allAnnouncements = new ArrayList<Announcement>(); protected ArrayList<Announcement> activeAnnouncements = new ArrayList<Announcement>(); protected ArrayList<Announcement> outboxAnnouncements = new ArrayList<Announcement>(); // List od all active subscriptions received from the cloud broker protected List<Subscription> brokerSubs = new ArrayList<Subscription>(); //List of configuration parameters protected String myBrokerIP; protected int myBrokerPort; protected boolean connected; protected AndroidLogWriter log; protected boolean logWriting = true; protected boolean testing = true; //List od locks protected Object publicationListMutex = new Object(); protected Object subscriptionListMutex = new Object(); /** * Constructor - mobile broker can be created via configuration file or * directly * * @param myName Mobile Broker's name * @param myBrokerIP Mobile Broker's connecting broker IP address * @param myBrokerPort Mobile Broker's connecting broker port */ public AbstractMobileBroker(String myName, String myBrokerIP, int myBrokerPort, Context context) { super(myName, Utils.getIPAddress(true), -1); log = new AndroidLogWriter(this.myName + "_mobilebrokerLog.txt", logWriting, testing, context); if (this.myIP.equals("")) { log.writeToLog("Does not have correct IP address " + this.myIP, true); this.myIP = "localhost"; } this.myBrokerIP = myBrokerIP; this.myBrokerPort = myBrokerPort; this.connected = false; log.writeToLog("Mobile Broker name: " + this.myName, true); log.writeToLog("Mobile Broker broker port: " + this.myBrokerPort, true); log.writeToLog("Mobile Broker broker IP: " + this.myBrokerIP, true); log.writeToLog("", true); } /** * Constructor - subscriber can be created via configuration file or * directly */ public AbstractMobileBroker(File configFile, Context context) { super("", Utils.getIPAddress(true), -1); log = new AndroidLogWriter(this.myName + "_mobilebrokerLog.txt", logWriting, testing, context); if (this.myIP.equals("")) { this.myIP = "localhost"; } try { Properties mbProps = new Properties(); FileInputStream fileIn = new FileInputStream(configFile); mbProps.load(fileIn); fileIn.close(); this.myName = mbProps.getProperty("mobilebrokerName"); if (this.myName == null) { throw new NullPointerException("Name must be defined!"); } this.myBrokerIP = mbProps.getProperty("brokerIP"); if (this.myBrokerIP == null) { throw new NullPointerException("BrokerIP must be defined!"); } this.myBrokerPort = Integer.parseInt(mbProps.getProperty("brokerPort")); if (mbProps.getProperty("testing", "false").toLowerCase().equals("false")) { this.testing = false; } else if (mbProps.getProperty("testing").toLowerCase().equals("true")) { this.testing = true; } else { System.err.println("Config param \"testing\" should be either true or false! Setting to default false."); this.testing = false; } if (mbProps.getProperty("logWriting", "true").toLowerCase().equals("true")) { this.logWriting = true; } else if (mbProps.getProperty("logWriting").toLowerCase().equals("false")) { this.logWriting = false; } else { System.err.println("Config param \"logWriting\" should be either true or false! Setting to default true."); this.logWriting = true; } } catch (Exception e) { e.printStackTrace(); System.exit(-1); } log.writeToLog("Mobile Broker name: " + this.myName, true); log.writeToLog("Mobile Broker broker port: " + this.myBrokerPort, true); log.writeToLog("Mobile Broker broker IP: " + this.myBrokerIP, true); log.writeToLog("", true); } /** * Used for connecting mobile broker to broker */ @Override public abstract void connect(); /** * Used for handling negative response message (reconnecting to broker) * * @param brokerIP IP address of reconnecting broker * @param brokerPort Port number of reconnecting broker */ @Override public void reconnect(String brokerIP, int brokerPort) { if (connected) { log.writeToLog("Disconnecting from broker (part of reconnect)."); disconnectFromBroker(); } this.myBrokerIP = brokerIP; this.myBrokerPort = brokerPort; this.connect(); } /** * Reconnect to last connected broker */ @Override public void reconnect() { if (connected) { log.writeToLog("Disconnecting from broker (part of reconnect)."); disconnectFromBroker(); } this.connect(); } /** * Used for disconnecting from broker */ @Override public void disconnectFromBroker() { if (connected) { Message disconnectMessage = new MobileBrokerDisconnectMessage(myName, getId()); this.sendMessage(disconnectMessage); //TODO FIXME no confirmation is waited for... it is just assumed the communication went ok terminateConnection(); log.writeToLog("Disconnected from broker!"); } else { log.writeToLog("Cannot disconnect from broker because not connected."); } } /** * For terminating the connection... closes to outSocket and sets everything * to null */ public abstract void terminateConnection(); public abstract void setAnnouncementListener(AnnouncementListener announcementListener); /** * Subscribing subscription from XML file * * @param fileName Name of input file * @return returns subscription UUID */ public UUID subscribeFromXMLFile(String fileName) { return subscribe(fileName, ""); } /** * Subscribing subscription from string * * @param inputString string containing XML subscription * @return returns subscription UUID */ public UUID subscribeFromXMLString(String inputString) { return subscribe("", inputString); } /** * Subscribing subscription from XML file or content (not both - one has to * be empty string ("")) * * @param fileName Name of input file * @param inputString Name of input String * @return returns subscription UUID */ public UUID subscribe(String fileName, String inputString) { ReadingWritingXML input = new ReadingWritingXML(fileName, inputString); input.read(); Subscription sub = input.createSubscription(); this.subscribe(sub); return sub.getId(); } /** * Used for subscribing * * @param subscription Subscription to be subscribed */ public void subscribe(Subscription subscription) { if (connected) { Message sendMasg = new SubscribeMessage(subscription, false); this.sendMessage(sendMasg); log.writeToLog("Subscription " + subscription + " sent to broker."); //TODO no confirmation is waited for here... if (!allSubs.contains(subscription)) { allSubs.add(subscription); activeSubs.add(subscription); } else if (!activeSubs.contains(subscription)) { activeSubs.add(subscription); } } else { if (!allSubs.contains(subscription)) { outboxSubs.add(subscription); allSubs.add(subscription); } else if (!outboxSubs.contains(subscription)) { outboxSubs.add(subscription); } log.writeToLog("Subscription " + subscription + " put in outbox because not connected to broker."); } } /** * Used for unsubscribing * * @param subscription Subscription to be unsubscribed */ public void unsubscribe(Subscription subscription) { if (activeSubs.contains(subscription)) { if (connected) { Message sendMsg = new SubscribeMessage(subscription, true); this.sendMessage(sendMsg); log.writeToLog("Unsubscription request sent to broker."); } activeSubs.remove(subscription); } else if (outboxSubs.contains(subscription)) { outboxSubs.remove(subscription); log.writeToLog("Subscription unsubscribed from outbox. No need to contact the broker."); } else { log.writeToLog("Unsubscription impossible because subscription is no longer active."); } } /** * Used for sending messages to broker * * @param sendMsg message to be sent */ protected abstract void sendMessage(Message sendMsg); /** * Publishing publication from XML file * * @param fileName Name of input file * @return returns publication UUID */ public UUID publishFromXMLFile(String fileName) { return publish(fileName, ""); } /** * Publishing publication from string * * @param inputString string containing XML publication * @return returns publication UUID */ public UUID publishFromXMLString(String inputString) { return publish("", inputString); } /** * Publishing publication from XML file or content (not both - one has to be * empty string ("")) * * @param fileName Name of input file * @param inputString Name of input String * @return returns publication UUID */ public UUID publish(String fileName, String inputString) { ReadingWritingXML input = new ReadingWritingXML(fileName, inputString); if (fileName.equalsIgnoreCase("")) { input.readString(); } else { input.readFile(); } Publication pub = input.createPublication(); this.publish(pub); return pub.getId(); } /** * Used for publishing new publication * * @param publication Publication to be published */ public void publish(Publication publication) { for (Subscription subscritpion : brokerSubs) { if (!subscritpion.isValid()) { brokerSubs.remove(subscritpion); continue; } if (subscritpion.coversPublication(publication)) { if (connected) { Message sendMsg = new PublishMessage(publication, false); this.sendMessage(sendMsg); log.writeToLog("Publication " + publication + " sent to broker."); //TODO no confirmation is waited for here... activePubs.add(publication); allPubs.add(publication); } else { outboxPubs.add(publication); allPubs.add(publication); log.writeToLog("Publication " + publication + " put in outbox because not connected to broker."); } return; } } } /** * Used for unpublishing old publication * * @param publication Publication to be unpublished */ public void unpublish(Publication publication) { if (activePubs.contains(publication)) { if (connected) { Message sendMsg = new PublishMessage(publication, true); this.sendMessage(sendMsg); log.writeToLog("Unpublication request sent to broker."); } activePubs.remove(publication); } else if (outboxPubs.contains(publication)) { outboxPubs.remove(publication); log.writeToLog("Publication unpublished from outbox. No need to contact the broker."); } else { log.writeToLog("Unpublication impossible because publication is not active."); } } /** * Announcing the data source from XML file * * @param fileName Name of input file * @return returns announcement UUID */ public UUID announceFromXMLFile(String fileName) { return announce(fileName, ""); } /** * Announcing the data source from string * * @param inputString string containing XML announcement * @return returns announcement UUID */ public UUID announceFromXMLString(String inputString) { return announce("", inputString); } /** * Announcing the data soruce from XML file or content (not both - one has to * be empty string ("")) * * @param fileName Name of input file * @param inputString Name of input String * @return returns announcement UUID */ public UUID announce(String fileName, String inputString) { ReadingWritingXML input = new ReadingWritingXML(fileName, inputString); input.read(); Announcement ann = input.createAnnouncement(); this.announce(ann); return ann.getId(); } /** * Used for announcing * * @param announcement Announcement to be published */ public void announce(Announcement announcement) { if (connected) { Message sendMasg = new AnnounceMessage(announcement, false); this.sendMessage(sendMasg); log.writeToLog("Announcement " + announcement + " sent to broker."); //TODO no confirmation is waited for here... if (!allAnnouncements.contains(announcement)) { allAnnouncements.add(announcement); activeAnnouncements.add(announcement); } else if (!activeAnnouncements.contains(announcement)) { activeAnnouncements.add(announcement); } } else { if (!allAnnouncements.contains(announcement)) { allAnnouncements.add(announcement); activeAnnouncements.add(announcement); } else if (!activeAnnouncements.contains(announcement)) { activeAnnouncements.add(announcement); } log.writeToLog("Announcement " + announcement + " put in outbox because not connected to broker."); } } /** * Used for revoke of previously sent announcement * * @param announcement Announcement to be published */ public void revokeAnnouncement(Announcement announcement) { if (activeAnnouncements.contains(announcement)) { if (connected) { Message sendMsg = new AnnounceMessage(announcement, true); this.sendMessage(sendMsg); log.writeToLog("Request for revoke of announcement sent to broker."); } activeAnnouncements.remove(announcement); } else if (outboxAnnouncements.contains(announcement)) { outboxAnnouncements.remove(announcement); log.writeToLog("Announcement removed from outbox. No need to contact the broker."); } else { log.writeToLog("Revoke of announcement impossible because announcement is no longer active."); } } public void setNotificationListener( NotificationListener notificationListener) { this.notificationListener = notificationListener; } public boolean isConnected() { return connected; } public boolean isLogWriting() { return logWriting; } public boolean isTesting() { return testing; } @Override public void unregisterFromBroker() { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } }