Details | Last modification | View Log | SVN | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 15 | arune | 1 | /* |
| 2 | * MbPacket.java |
||
| 3 | * |
||
| 4 | * Created on den 24 augusti 2003, 12:55 |
||
| 5 | */ |
||
| 6 | package Macbeth.System; |
||
| 7 | |||
| 8 | import Macbeth.XML.XMLDataHandler; |
||
| 9 | import Macbeth.XML.XMLParser; |
||
| 10 | import Macbeth.Utilities.MySystem; |
||
| 11 | import java.util.Iterator; |
||
| 12 | import java.util.HashMap; |
||
| 13 | import java.io.IOException; |
||
| 14 | |||
| 15 | import org.xml.sax.SAXException; |
||
| 16 | |||
| 17 | /** |
||
| 18 | * This class represents a Macbeth packet, containing both its destination, |
||
| 19 | * its source, and its contents. |
||
| 20 | * @author Jimmy |
||
| 21 | */ |
||
| 22 | public class MbPacket { |
||
| 23 | |||
| 24 | /** |
||
| 25 | * The Macbeth location to which this packet is addressed. |
||
| 26 | * If the kernel-field is set to "self", it means that |
||
| 27 | * the packet will be delivered locally only (that is, |
||
| 28 | * within the same kernel it was sent from). If the field |
||
| 29 | * is set to something else, however, this name will be |
||
| 30 | * looked up in the list of known kernels, which, in case |
||
| 31 | * the kernel was found, also provides the internet address |
||
| 32 | * of the specified kernel. |
||
| 33 | */ |
||
| 34 | private MbLocation destination; |
||
| 35 | |||
| 36 | /** |
||
| 37 | * The Macbeth location from which this packet was sent. |
||
| 38 | * This can be used by receiver module (or kernel) |
||
| 39 | * to identify the sender. |
||
| 40 | */ |
||
| 41 | private MbLocation source; |
||
| 42 | |||
| 43 | /** |
||
| 44 | * The packet contents (an XML-document). |
||
| 45 | */ |
||
| 46 | private String contents; |
||
| 47 | |||
| 48 | /** |
||
| 49 | * The remote address of the client that sent us this packet. |
||
| 50 | * If the packet has never been transported via any networks, |
||
| 51 | * this value is "self" (that is, source kernel and dest kernel |
||
| 52 | * are equal). |
||
| 53 | */ |
||
| 54 | private String originAddress; |
||
| 55 | |||
| 56 | /** |
||
| 57 | * Gets the destination of this packet. |
||
| 58 | * @return The packet destination. |
||
| 59 | */ |
||
| 60 | public MbLocation getDestination() { |
||
| 61 | return destination; |
||
| 62 | } |
||
| 63 | /** |
||
| 64 | * Sets the destination of this packet. |
||
| 65 | * @param destination The new destination. |
||
| 66 | */ |
||
| 67 | public void setDestination(MbLocation destination) { |
||
| 68 | this.destination = destination; |
||
| 69 | } |
||
| 70 | /** |
||
| 71 | * Sets the kernel field in the destination of this packet. |
||
| 72 | * @param kernel The new destination kernel. |
||
| 73 | */ |
||
| 74 | public void setDestinationKernel(String kernel) { |
||
| 75 | destination.setKernel(kernel); |
||
| 76 | } |
||
| 77 | /** |
||
| 78 | * Sets the module field in the destination of this packet. |
||
| 79 | * @param module The new destination module. |
||
| 80 | */ |
||
| 81 | public void setDestinationModule(String module) { |
||
| 82 | destination.setModule(module); |
||
| 83 | } |
||
| 84 | |||
| 85 | /** |
||
| 86 | * Gets the source of this packet. |
||
| 87 | * @return The packet source. |
||
| 88 | */ |
||
| 89 | public MbLocation getSource() { |
||
| 90 | return source; |
||
| 91 | } |
||
| 92 | /** |
||
| 93 | * Sets the source of this packet. |
||
| 94 | * @param source The new packet source. |
||
| 95 | */ |
||
| 96 | public void setSource(MbLocation source) { |
||
| 97 | this.source = source; |
||
| 98 | } |
||
| 99 | |||
| 100 | /** |
||
| 101 | * Gets the packet contents. This is an XML-string. |
||
| 102 | * @return The packet contents. |
||
| 103 | */ |
||
| 104 | public synchronized String getContents() { |
||
| 105 | return contents; |
||
| 106 | } |
||
| 107 | /** |
||
| 108 | * Sets the packet contents. This must be valid XML-data. |
||
| 109 | * @param contents The new packet contents. |
||
| 110 | */ |
||
| 111 | public synchronized void setContents(String contents) { |
||
| 112 | this.contents = contents; |
||
| 113 | } |
||
| 114 | /** |
||
| 115 | * Appends a string to the packet contents. This must be |
||
| 116 | * valid XML-data. |
||
| 117 | * @param s The string to append. |
||
| 118 | */ |
||
| 119 | public synchronized void appendContents(String s) { |
||
| 120 | this.contents += s; |
||
| 121 | } |
||
| 122 | |||
| 123 | /** |
||
| 124 | * Gets the source remote address of this packet. |
||
| 125 | * @return The remote address of the packet source. |
||
| 126 | */ |
||
| 127 | public synchronized String getOriginAddress() { |
||
| 128 | return originAddress; |
||
| 129 | } |
||
| 130 | |||
| 131 | /** |
||
| 132 | * Creates a new instance of MbPacket. |
||
| 133 | */ |
||
| 134 | public MbPacket() { |
||
| 135 | destination = new MbLocation(); |
||
| 136 | source = new MbLocation(); |
||
| 137 | originAddress = "self"; |
||
| 138 | contents = ""; |
||
| 139 | } |
||
| 140 | |||
| 141 | /** |
||
| 142 | * Serializes this packet into a string object (XML-formatted) |
||
| 143 | * @return the packet as an XML-string. |
||
| 144 | */ |
||
| 145 | public String serializeToString() { |
||
| 146 | String s = "<mbpacket "; |
||
| 147 | s += "sourcekernel=\"" + source.getKernel() + "\" "; |
||
| 148 | s += "sourcemodule=\"" + source.getModule() + "\" "; |
||
| 149 | //s += "destkernel=\"" + destination.kernel + "\" "; |
||
| 150 | s += "destmodule=\"" + destination.getModule() + "\" "; |
||
| 151 | s += ">" + MySystem.lineBreak; |
||
| 152 | s += contents; |
||
| 153 | s += MySystem.lineBreak + "</mbpacket>"; |
||
| 154 | return s; |
||
| 155 | } |
||
| 156 | |||
| 157 | /** |
||
| 158 | * Tries to deserialize an XML-string into a packet. |
||
| 159 | * The format of the string must be: |
||
| 160 | * <mbpacket destmodule="modulename"> |
||
| 161 | * Only valid XML-data in here! |
||
| 162 | * </mbpacket> |
||
| 163 | * or else this function will not succeed. |
||
| 164 | * @param s The XML-string |
||
| 165 | * @return true if successful, false otherwise. |
||
| 166 | * @throws SAXException if the string contains an invalid XML document (syntax errors). |
||
| 167 | */ |
||
| 168 | synchronized public boolean createFromString(String s) throws SAXException { |
||
| 169 | //destination kernel is always set to "self" |
||
| 170 | destination = new MbLocation("self",null); |
||
| 171 | source = new MbLocation("external","external"); |
||
| 172 | contents = ""; |
||
| 173 | XMLParser xmlParser = new XMLParser(new DataHandler()); |
||
| 174 | try { |
||
| 175 | xmlParser.parseString(s); |
||
| 176 | } catch (IOException e) { |
||
| 177 | System.err.println(e); |
||
| 178 | e.printStackTrace(); |
||
| 179 | return false; |
||
| 180 | } |
||
| 181 | //TODO: why check this? can it happen? |
||
| 182 | if (destination==null) { |
||
| 183 | return false; |
||
| 184 | } |
||
| 185 | return true; |
||
| 186 | } |
||
| 187 | |||
| 188 | /** |
||
| 189 | * A data handler for XML parser. |
||
| 190 | */ |
||
| 191 | private class DataHandler implements XMLDataHandler { |
||
| 192 | //current element name |
||
| 193 | private String currentElement = null; |
||
| 194 | //current data for the element |
||
| 195 | private String currentElementData = null; |
||
| 196 | |||
| 197 | public void XMLstartElement(String element, HashMap attributes) { |
||
| 198 | currentElementData = null; |
||
| 199 | if (element.equals("mbpacket")) { |
||
| 200 | if (attributes.containsKey("sourcekernel")) { |
||
| 201 | source.setKernel((String)attributes.get("sourcekernel")); |
||
| 202 | } |
||
| 203 | if (attributes.containsKey("sourcemodule")) { |
||
| 204 | source.setModule((String)attributes.get("sourcemodule")); |
||
| 205 | } |
||
| 206 | if (attributes.containsKey("destmodule")) { |
||
| 207 | destination.setModule((String)attributes.get("destmodule")); |
||
| 208 | } |
||
| 209 | // NOTE: destination kernel is IGNORED in all incoming packets! |
||
| 210 | // (for security reasons, since no relaying is allowed. destkernel is always set to "self") |
||
| 211 | } else if (element.equals("remoteaddress") && originAddress.equals("self")) { |
||
| 212 | //(it must equal self, or else it can be set more than once, and can thus be faked) |
||
| 213 | //remember remote address |
||
| 214 | if (attributes.containsKey("value")) { |
||
| 215 | originAddress = (String)attributes.get("value"); |
||
| 216 | } |
||
| 217 | } else { |
||
| 218 | //this is user data, so put it into the contents field |
||
| 219 | currentElement = element; |
||
| 220 | contents += "<" + element; |
||
| 221 | Iterator it = attributes.keySet().iterator(); |
||
| 222 | while (it.hasNext()) { |
||
| 223 | String key = (String)it.next(); |
||
| 224 | contents += " " + key + "=\"" + attributes.get(key) + "\""; |
||
| 225 | } |
||
| 226 | //NEW CODE: |
||
| 227 | contents += ">"; |
||
| 228 | } |
||
| 229 | } |
||
| 230 | public void XMLelementData(String data) { |
||
| 231 | //NEW CODE |
||
| 232 | if (currentElement!=null) { |
||
| 233 | contents += MySystem.lineBreak + data; |
||
| 234 | currentElementData = data; |
||
| 235 | } |
||
| 236 | } |
||
| 237 | public void XMLendElement(String element) { |
||
| 238 | if (!element.equals("remoteaddress") && !element.equals("mbpacket")) { |
||
| 239 | //NEW CODE: |
||
| 240 | //always add full end tag |
||
| 241 | //TODO: maybe fix this again. OLD CODE caused some ">" to be missing though! |
||
| 242 | contents += "</" + element + ">"; |
||
| 243 | } |
||
| 244 | currentElement = null; |
||
| 245 | } |
||
| 246 | public void XMLdocumentStart() {} |
||
| 247 | public void XMLdocumentEnd() {} |
||
| 248 | } |
||
| 249 | } |