001: /*
002: * %W% %E%
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026:
027: package com.sun.jump.message;
028:
029: import java.io.IOException;
030: import com.sun.jump.os.JUMPOSInterface;
031:
032: /**
033: * <code>JUMPOutgoingMessage</code> encapsulates a message that is filled in
034: * with data.
035: */
036: public abstract class JUMPOutgoingMessage extends JUMPMessage {
037: private static final int MESSAGE_DATA_INITIAL_SIZE = 512;
038: protected JUMPMessagable sender;
039: /* offset just past header in message, for sanity checking by native
040: side */
041: protected int headerOffset;
042:
043: /**
044: * Creates a new instance of JUMPOutgoingMessage
045: */
046: protected JUMPOutgoingMessage(JUMPMessagable sender, String type,
047: String returnType, int responseId) {
048: this .sender = sender;
049: this .type = type;
050: this .returnType = returnType;
051: this .responseId = responseId;
052: this .messageDataBytes = new byte[MESSAGE_DATA_INITIAL_SIZE];
053: this .messageDataOffset = MESSAGE_DATA_OFFSET;
054: composeHeader();
055: messageMarkOffset = messageDataOffset;
056: }
057:
058: // used for deserializing the message
059: protected JUMPOutgoingMessage() {
060: super ();
061: }
062:
063: private void composeHeader() {
064: /* Here we leave room for the header. The native layer will
065: fill some of this in */
066: addInt(0); // Room for message id
067: addInt(this .responseId);
068: addInt(serializeMessagable(sender)); // Sender id
069: addUTF(this .returnType); // Add return type
070: addUTF(this .type); // And add type
071: //
072: // Remember this offset so the native side can sanity check
073: //
074: this .headerOffset = messageDataOffset;
075:
076: // User data follows
077: }
078:
079: //
080: // Make sure we can accommodate n more bytes.
081: //
082: private void ensureCapacity(int n) {
083: // NOTE: This assumes that requiredCapacity and newCapacity
084: // will not overflow an int, which should be reasonable.
085: int requiredCapacity = messageDataOffset + n;
086: if (requiredCapacity > messageDataBytes.length) {
087: int newCapacity = messageDataBytes.length * 2;
088: if (newCapacity < requiredCapacity) {
089: newCapacity = requiredCapacity;
090: }
091:
092: byte[] newData = new byte[newCapacity];
093: System.arraycopy(messageDataBytes, 0, newData, 0,
094: messageDataOffset);
095: messageDataBytes = newData;
096: }
097: }
098:
099: /**
100: * Add integer to message data
101: */
102: public void addInt(int i) {
103: ensureCapacity(4);
104: // Add int at messageDataOffset, big endian
105: messageDataBytes[messageDataOffset + 0] = (byte) (i >>> 24);
106: messageDataBytes[messageDataOffset + 1] = (byte) (i >>> 16);
107: messageDataBytes[messageDataOffset + 2] = (byte) (i >>> 8);
108: messageDataBytes[messageDataOffset + 3] = (byte) (i >>> 0);
109: messageDataOffset += 4;
110: }
111:
112: public void addLong(long l) {
113: ensureCapacity(8);
114: // Add int at messageDataOffset, big endian
115: messageDataBytes[messageDataOffset + 0] = (byte) (l >>> 56);
116: messageDataBytes[messageDataOffset + 1] = (byte) (l >>> 48);
117: messageDataBytes[messageDataOffset + 2] = (byte) (l >>> 40);
118: messageDataBytes[messageDataOffset + 3] = (byte) (l >>> 32);
119: messageDataBytes[messageDataOffset + 4] = (byte) (l >>> 24);
120: messageDataBytes[messageDataOffset + 5] = (byte) (l >>> 16);
121: messageDataBytes[messageDataOffset + 6] = (byte) (l >>> 8);
122: messageDataBytes[messageDataOffset + 7] = (byte) (l >>> 0);
123: messageDataOffset += 8;
124: }
125:
126: public void addByte(byte b) {
127: ensureCapacity(1);
128: // Add byte at messageDataOffset
129: messageDataBytes[messageDataOffset] = b;
130: messageDataOffset += 1;
131: }
132:
133: private byte[] getBytes(String s) {
134: char[] val = s.toCharArray();
135: byte[] dst = new byte[val.length + 1]; // Leave room for null termination
136: for (int i = 0; i < val.length; i++) {
137: dst[i] = (byte) val[i];
138: }
139: return dst;
140: }
141:
142: public void addUTF(String s) {
143: //
144: // FIXME
145: // Add string in Java-modified utf-8
146: // This code assumes ASCII (and so does the native layer)
147: // Example implementation in DataOutputStream.writeUTF().
148: //
149: if (s == null) {
150: addByteArray(null);
151: } else {
152: addByteArray(getBytes(s));
153: }
154: }
155:
156: public void addByteArray(byte[] barr) {
157: if (barr == null) {
158: addInt(-1);
159: return;
160: }
161: addInt(barr.length);
162: ensureCapacity(barr.length); // the bytes+length
163: System.arraycopy(barr, 0, messageDataBytes, messageDataOffset,
164: barr.length);
165: messageDataOffset += barr.length;
166: }
167:
168: public void addUTFArray(String[] arr) {
169: if (arr == null) {
170: addInt(-1);
171: return;
172: }
173: addInt(arr.length);
174: for (int i = 0; i < arr.length; i++) {
175: addUTF(arr[i]);
176: }
177: }
178:
179: public byte[] serialize() {
180: return messageDataBytes;
181: }
182:
183: protected abstract int serializeMessagable(JUMPMessagable messagable);
184:
185: // This should not be happening for an outgoing message constructed
186: // with a sender
187: protected void readMessageSender(int id) {
188: }
189:
190: }
|