1 /* 2 * $HeadURL: /cvsroot/insight/Insight/remote-protocol/src/com/mindtree/insight/remoteprotocol/PacketDataSizeOverLimitsException.java,v $ 3 * $Date: 2005/08/09 18:39:17 $ 4 * $Revision: 1.1 $ 5 * $Author: m1001025 $ 6 * 7 * Copyright (c) 2005 MindTree Consulting Ltd. 8 * 9 * This file is part of Insight Remote Protocol Library. 10 * 11 * Insight Remote Protocol Library is free software: you can redistribute it 12 * and/or modify it under the terms of the GNU General Public License as 13 * published by the Free Software Foundation, either version 3 of the License, 14 * or (at your option) any later version. 15 * 16 * Insight Remote Protocol Library is distributed in the hope that it will be 17 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 19 * Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License along with 22 * Insight Remote Protocol Library. If not, see <http://www.gnu.org/licenses/>. 23 */ 24 25 package com.mindtree.techworks.insight.remoteprotocol.spi; 26 27 import java.net.InetAddress; 28 import java.net.UnknownHostException; 29 import java.nio.charset.CharacterCodingException; 30 31 import com.mindtree.techworks.insight.remoteprotocol.PacketDataSizeOverLimitsException; 32 import com.mindtree.techworks.insight.remoteprotocol.RemoteProtocolException; 33 import com.mindtree.techworks.insight.remoteprotocol.util.ByteUtils; 34 35 /** 36 * The content type of a startup message. This message is transmitted before any 37 * LogMessage is transmitted from a particular source. This message is also 38 * retransmitted intermittently from the source. 39 * 40 * <pre> 41 * 0 8 16 24 32 42 * | . . . . . . . | . . . . . . . | . . . . . . . | . . . . . . . | 43 * 44 * +---------------+---------------+-------------------------------+ 45 * |R| UNUSED (0) | VERSION | NAMESPACE (To End) | 46 * +-+-------------+---------------+-------------------------------+ 47 * 48 * | . . . . . . . | . . . . . . . | . . . . . . . | . . . . . . . | 49 * 0 8 16 24 32 50 * 51 * R - Retransmission Indicator: 0 - First Transmission, 1 - Retransmission 52 * </pre> 53 * 54 * @see com.mindtree.techworks.insight.remoteprotocol.spi.PacketDataContent 55 * @author <a href="mailto:bindul_bhowmik@mindtree.com">Bindul Bhowmik</a> 56 * @version $Revision: 1.2 $ $Date: 2005/08/09 18:39:17 $ 57 */ 58 public class StartupMessageDataContent extends PacketDataContent { 59 60 // ------------------------------------------------------------------------- 61 // Class variables 62 // ------------------------------------------------------------------------- 63 64 /** 65 * The serial version UID for the serialized form 66 */ 67 private static final long serialVersionUID = -5321147203534982253L; 68 69 /** 70 * Filter mask to identify the Retransmission Indicator. The filter used to 71 * check and set the Retransmission Indicator in the message. 256 is 2^8 or 72 * 10000000 binary. 73 */ 74 private static final int RETRANSMISSION_INDICATOR_FILTER = 256; 75 76 // ------------------------------------------------------------------------- 77 // Instance variables 78 // ------------------------------------------------------------------------- 79 80 /** 81 * Indicates if the packet is a retransmission 82 */ 83 private boolean retransmission; 84 85 /** 86 * The version of the message, currently 1. 87 */ 88 private byte version = 1; 89 90 /** 91 * The namespace contained in the message 92 */ 93 private String namespace; 94 95 // ------------------------------------------------------------------------- 96 // Constructors 97 // ------------------------------------------------------------------------- 98 99 /** 100 * Creates a new StartupMessageDataContent object. 101 * 102 * @see PacketDataContent#PacketDataContent() 103 */ 104 public StartupMessageDataContent() { 105 106 super(); 107 this.messageType = MessageType.STARTUP_MESSAGE; 108 this.version = 1; 109 } 110 111 /** 112 * Creates an instance of the StartupMessageDataContent 113 * 114 * @see PacketDataContent#PacketDataContent(byte[], PacketHeader) 115 * @param completePacketData 116 * The data for the complete packet. 117 * @param packetHeader 118 * The header for the packet 119 * @throws RemoteProtocolException 120 * If the message type in the PacketHeader is not 121 * <code>MessageType#STARTUP_MESSAGE_TYPE</code> 122 */ 123 public StartupMessageDataContent(byte[] completePacketData, 124 PacketHeader packetHeader) throws RemoteProtocolException { 125 126 super(completePacketData, packetHeader); 127 if (!MessageType.STARTUP_MESSAGE.equals(this.messageType)) { 128 throw new RemoteProtocolException("Incompatible message type"); 129 } 130 readFieldsFromData(); 131 } 132 133 // ------------------------------------------------------------------------- 134 // Methods overridden from PacketDataContent 135 // ------------------------------------------------------------------------- 136 137 /** 138 * Sets the packet data. The fields in this class are updated right after 139 * setting the data. 140 * 141 * @throws RemoteProtocolException 142 * If the fields cannot be interpretted correctly. 143 * @see com.mindtree.techworks.insight.remoteprotocol.spi.PacketDataContent#setPacketData(byte[]) 144 */ 145 public void setPacketData(byte[] packetData) throws RemoteProtocolException { 146 147 super.setPacketData(packetData); 148 readFieldsFromData(); 149 } 150 151 // ------------------------------------------------------------------------- 152 // Accessors 153 // ------------------------------------------------------------------------- 154 155 /** 156 * Returns the namespace 157 * 158 * @return Returns the namespace. 159 */ 160 public String getNamespace() { 161 162 return namespace; 163 } 164 165 /** 166 * Sets the namespace 167 * 168 * @param namespace 169 * The namespace to set. 170 * @throws PacketDataSizeOverLimitsException 171 * If the packet data size is over limits 172 */ 173 public void setNamespace(String namespace) 174 throws PacketDataSizeOverLimitsException, RemoteProtocolException { 175 176 this.namespace = namespace; 177 setDataFromFields(); 178 } 179 180 /** 181 * Returns the retransmission 182 * 183 * @return Returns the retransmission. 184 */ 185 public boolean isRetransmission() { 186 187 return retransmission; 188 } 189 190 /** 191 * Sets the retransmission 192 * 193 * @param retransmission 194 * The retransmission to set. 195 */ 196 public void setRetransmission(boolean retransmission) { 197 198 this.retransmission = retransmission; 199 try { 200 setDataFromFields(); 201 } catch (PacketDataSizeOverLimitsException e) { 202 // This exception should never come for setting a boolean. So 203 // consuming it 204 } catch (RemoteProtocolException e) { 205 // TODO Auto-generated catch block 206 e.printStackTrace(); 207 } 208 } 209 210 /** 211 * Returns the version 212 * 213 * @return Returns the version. 214 */ 215 public byte getVersion() { 216 217 return version; 218 } 219 220 // ------------------------------------------------------------------------- 221 // Private Util methods 222 // ------------------------------------------------------------------------- 223 224 /** 225 * Creates the data byte array for this instance from the fields. This 226 * method should be called after every 'set' operation on the fields of this 227 * class, except when the data is set as a byte array. 228 * 229 * @throws PacketDataSizeOverLimitsException 230 * If the data size is higher than the limit. 231 * @throws RemoteProtocolException 232 * If we have an error in the data 233 */ 234 private void setDataFromFields() throws PacketDataSizeOverLimitsException, 235 RemoteProtocolException { 236 237 // Namespace cannot be sent as null 238 if (null == namespace || namespace.length() == 0) { 239 String localHost; 240 try { 241 localHost = InetAddress.getLocalHost().getCanonicalHostName(); 242 } catch (UnknownHostException e) { 243 // Do nothing here 244 localHost = "localhost"; 245 } 246 namespace = "insight://" + localHost + "/" 247 + System.currentTimeMillis(); 248 } 249 250 byte[] dataBytes = new byte[2 + 2 * namespace.length()]; 251 252 if (retransmission) { 253 dataBytes[0] = (byte) RETRANSMISSION_INDICATOR_FILTER; 254 } else { 255 dataBytes[0] = 0; 256 } 257 258 dataBytes[1] = 1; 259 260 byte[] namespaceBytes; 261 try { 262 namespaceBytes = ByteUtils.getByteArrayForString(namespace); 263 } catch (CharacterCodingException e) { 264 throw new RemoteProtocolException("Unable to encode data.", e); 265 } 266 System 267 .arraycopy(namespaceBytes, 0, dataBytes, 2, 268 namespaceBytes.length); 269 270 checkPacketDataSize(dataBytes); 271 this.packetData = dataBytes; 272 } 273 274 /** 275 * Interprets the fields of this instance from the data. 276 * 277 * @throws RemoteProtocolException 278 * If the fields cannot be interpretted. 279 */ 280 private void readFieldsFromData() throws RemoteProtocolException { 281 282 if (getLength() < 4) { 283 throw new RemoteProtocolException("Too Short Data!"); 284 } 285 286 // TODO Think about this 287 this.retransmission = ((packetData[0] & 0xFFFFFF00) & RETRANSMISSION_INDICATOR_FILTER) == RETRANSMISSION_INDICATOR_FILTER; 288 this.version = packetData[1]; 289 290 if (this.version != 0x01) { 291 throw new RemoteProtocolException("Invalid Startup Message Version"); 292 } 293 294 int dataSize = getLength(); 295 296 try { 297 this.namespace = ByteUtils.readStringFromByteArray(packetData, 2, dataSize - 2); 298 } catch (CharacterCodingException e) { 299 throw new RemoteProtocolException("Unable to decode namespace", e); 300 } 301 } 302 303 }