KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > ubermq > jms > common > datagram > impl > DelimitedDatagramFactory


1 package com.ubermq.jms.common.datagram.impl;
2
3 import com.ubermq.jms.common.datagram.*;
4 import com.ubermq.kernel.*;
5 import java.nio.*;
6
7 /**
8  * Implements a datagram factory that produces
9  * and interprets datagrams using start/end message byte sequences
10  * as an alternative to length information encoded in a header.
11  */

12 public class DelimitedDatagramFactory
13     implements IDatagramFactory
14 {
15     private final byte[] startOfMessage,
16         endOfMessage;
17
18     /**
19      * Constructs a delimited datagram factory, given
20      * a start of message byte sequence, and an end of message
21      * byte sequence.
22      *
23      * @param startOfMessage the byte sequence that flags the start
24      * of a datagram.
25      * @param endOfMessage the byte sequence that flags the end of
26      * a datagram.
27      */

28     public DelimitedDatagramFactory(byte[] startOfMessage,
29                                     byte[] endOfMessage)
30     {
31         this.startOfMessage = startOfMessage;
32         this.endOfMessage = endOfMessage;
33     }
34
35     /**
36      * Constructs a datagram factory that processes messages
37      * delimited by a single end of message sequence. <P>
38      *
39      * This will interpret ALL bytes preceding such a sequence
40      * as valid for consumption by a datagram instance.
41      *
42      * @param endOfMessage the byte sequence that flags the end
43      * of a datagram.
44      */

45     public DelimitedDatagramFactory(byte[] endOfMessage)
46     {
47         this(new byte[0], endOfMessage);
48     }
49
50     /**
51      * Provides information to the I/O processing thread about a
52      * raw incoming data stream. The byte buffer passed as a parameter
53      * could potentially be the actual read buffer owned by the I/O thread.
54      * It is critical that this method not change the limit, or
55      * capacity of the buffer. <P>
56      *
57      * when this method returns, the byte buffer's position should be set to the
58      * origin of the next datagram. the frame logic is allowed to skip arbitrary
59      * bytes in the input stream that are deemed invalid or extraneous.
60      *
61      * the caller of this method will call incoming() with an appropriate, well-formed
62      * byte buffer when <code>length</code> bytes are available starting at
63      * the position set when this call returns.
64      *
65      * @return int the length of the datagram, in terms of the buffer passed as a parameter.
66      * @throws IOException if the buffer is hopelessly unintelligible
67      * and the connection/buffer should be terminated.
68      */

69     public int frame(ByteBuffer bb)
70         throws java.io.IOException JavaDoc
71     {
72         // scans the byte buffer for the start of message indicator,
73
// then finds the end of message indicator, and
74
// returns the length.
75
int som = findSequence(bb, startOfMessage);
76         if (som >= 0) {
77             int eom = findSequence((ByteBuffer)bb.position(som), endOfMessage);
78             if (eom >= 0) {
79                 // ok we have a start and end that are valid
80
return eom - som + endOfMessage.length;
81             }
82         }
83
84         // we need more bytes
85
return Integer.MAX_VALUE;
86     }
87
88     /**
89      * Finds the given byte sequence in the specified buffer,
90      * starting at the buffer position to the buffer limit.
91      * <P>
92      * This could be optimized to use a better sequential searching
93      * algorithm.
94      */

95     private int findSequence(ByteBuffer bb, byte[] seq)
96     {
97         // proceed otherwise
98
int limit = bb.limit() - seq.length + 1;
99         for (int i = bb.position(); i < limit; i++)
100         {
101             int j;
102             for (j = 0; j < seq.length; j++)
103             {
104                 byte b = bb.get(i + j);
105                 if (b != seq[j])
106                     break;
107             }
108
109             // ok we found it.
110
if (j == seq.length) {
111                 return i;
112             }
113         }
114
115         return -1;
116     }
117
118     /**
119      * Reads and processes bytes from a buffer and produces an instance
120      * of IDatagram that can be passed to datagram processing logic.
121      * <P>
122      * The byte buffer that is passed into this method is a subset
123      * of the buffer passed into the frame() method call immediately preceding,
124      * and the buffer begins with the header information that may have been
125      * processed by frame.
126      * <P>
127      * @param bb a byte buffer with the position set to zero and the
128      * limit set to the number of bytes in the buffer,
129      * @throws IllegalArgumentException if the byte buffer does not contain
130      * a valid datagram.
131      */

132     public IDatagram incoming(ByteBuffer bb) throws IllegalArgumentException JavaDoc
133     {
134         // strip out the delimiters.
135
bb.position(startOfMessage.length).limit(bb.limit() - endOfMessage.length);
136
137         int type = bb.get();
138         IDatagram d = DatagramFactory.getInstance().createDatagramInstance(type);
139
140         try {
141             d.incoming(bb);
142             return d;
143         }
144         catch (java.io.IOException JavaDoc e) {
145             throw new IllegalArgumentException JavaDoc();
146         }
147     }
148
149     /**
150      * Outputs a datagram to the specified write buffer. The position of the
151      * write buffer should be zero on input. When the call returns, the position
152      * of the write buffer should be after the last byte of data to be
153      * output to the connection.
154      *<P>
155      * @param bb a byte buffer, with position 0 and limit equal to the maximum
156      * amount of data writeable in a single transaction.
157      * @param d the datagram that will be written to the buffer following this
158      * header.
159      */

160     public void outgoing(ByteBuffer bb, IDatagram d)
161     {
162         bb.put(startOfMessage);
163         bb.put((byte) (d.getDatagramType() & 0xFF));
164         d.outgoing(bb);
165         bb.put(endOfMessage);
166     }
167
168
169 }
170
Popular Tags