1 | package dmg.cells.nucleus ; |
2 | import java.io.* ; |
3 | |
4 | /** |
5 | * |
6 | * |
7 | * @author Patrick Fuhrmann |
8 | * @version 0.1, 15 Feb 1998 |
9 | */ |
10 | public class CellMessage implements Cloneable , Serializable { |
11 | |
12 | static final long serialVersionUID = -5559658187264201731L; |
13 | |
14 | private CellPath _source , _destination ; |
15 | private CellPath _markSource = null , _markDestination = null ; |
16 | private Object _message ; |
17 | private long _creationTime ; |
18 | private long _ttl = Long.MAX_VALUE; |
19 | private int _mode ; |
20 | private UOID _umid , _lastUmid ; |
21 | private byte [] _messageStream = null ; |
22 | private boolean _isRouted = false ; |
23 | private int _hopCount = 0 ; |
24 | private boolean _isAcknowledge = false ; |
25 | private boolean _isPersistent = false ; |
26 | private Object _session; |
27 | private static final int ORIGINAL_MODE = 0 ; |
28 | private static final int STREAM_MODE = 1 ; |
29 | private static final int DUMMY_MODE = 2 ; |
30 | private transient long _receivedAt; |
31 | |
32 | public CellMessage( CellPath addr , Object msg ){ |
33 | |
34 | _destination = addr ; |
35 | _message = msg ; |
36 | _source = new CellPath() ; |
37 | _creationTime = System.currentTimeMillis() ; |
38 | _receivedAt = _creationTime; |
39 | _mode = ORIGINAL_MODE ; |
40 | _umid = new UOID() ; |
41 | _lastUmid = _umid ; |
42 | _session = CDC.getSession(); |
43 | } |
44 | @Override |
45 | public String toString(){ |
46 | StringBuffer sb = new StringBuffer() ; |
47 | sb.append( "<CM: S=" ).append( _source.toString() ). |
48 | append( ";D=").append( _destination.toString() ) ; |
49 | if( _markSource != null ) |
50 | sb.append( ";MS=").append( _markSource.toString() ) ; |
51 | if( _markDestination != null ) |
52 | sb.append( ";MD=").append( _markDestination.toString() ) ; |
53 | if( _mode == ORIGINAL_MODE ) |
54 | sb.append( ";C=" ). |
55 | append( _message.getClass().getName() ) ; |
56 | else |
57 | sb.append( ";C=Stream" ) ; |
58 | |
59 | sb.append( ";O=" ).append( _umid ).append( ";LO=" ).append( _lastUmid ); |
60 | if (_session != null) |
61 | sb.append(";SID=").append(_session); |
62 | if (_ttl < Long.MAX_VALUE) |
63 | sb.append(";TTL=").append(_ttl); |
64 | sb.append( ">" ) ; |
65 | return sb.toString() ; |
66 | } |
67 | @Override |
68 | public int hashCode(){ return _umid.hashCode() ; } |
69 | @Override |
70 | public boolean equals( Object obj ){ |
71 | if( obj instanceof CellMessage ) |
72 | return ((CellMessage)obj)._umid.equals( _umid ) ; |
73 | else if( obj instanceof UOID ) |
74 | return ((UOID)obj).equals( _umid ) ; |
75 | |
76 | return false ; |
77 | } |
78 | public void setAcknowledge( boolean ack ){ _isAcknowledge = ack ; } |
79 | public boolean isAcknowledge(){ return _isAcknowledge ; } |
80 | public boolean isReply() { return _isPersistent; } |
81 | public int getHopCount(){ return _hopCount ; } |
82 | public void incHopCount(){ _hopCount++ ; } |
83 | public UOID getUOID() { return _umid ; } |
84 | public UOID getLastUOID() { return _lastUmid ; } |
85 | public void setUOID( UOID umid ) { |
86 | _umid = umid ; |
87 | return ; |
88 | } |
89 | public void setLastUOID( UOID lastUOID ) { |
90 | _lastUmid = lastUOID ; |
91 | return ; |
92 | } |
93 | public Object getSession() { return _session; } |
94 | public void setSession(Object session) { _session = session; } |
95 | public void setTtl(long ttl) { _ttl = ttl; } |
96 | public long getTtl() { return _ttl; } |
97 | public CellPath getDestinationAddress(){ return _destination ; } |
98 | public CellPath getSourceAddress(){ return _source ; } |
99 | public CellPath getDestinationPath(){ return _destination ; } |
100 | public CellPath getSourcePath(){ return _source ; } |
101 | public Object getMessageObject(){ return _message ; } |
102 | public void setMessageObject( Object obj ){ _message = obj ; } |
103 | public void revertDirection(){ |
104 | _destination = _source ; |
105 | _destination.revert() ; |
106 | _source = new CellPath() ; |
107 | _lastUmid = _umid ; |
108 | _isPersistent = true; |
109 | } |
110 | public void markLocation(){ |
111 | _markDestination = (CellPath)_destination.clone() ; |
112 | _markSource = (CellPath)_source.clone() ; |
113 | } |
114 | public void resetLocation(){ |
115 | if( ( _markDestination == null ) || |
116 | ( _markSource == null ) )return ; |
117 | _destination = _markDestination ; |
118 | _source = _markSource ; |
119 | } |
120 | public boolean isFinalDestination(){ return _destination.isFinalDestination() ; } |
121 | public boolean isFirstDestination(){ return _destination.isFirstDestination() ; } |
122 | public boolean nextDestination(){ return _destination.next() ; } |
123 | // |
124 | // package methods |
125 | // |
126 | void isRouted( boolean r ){ _isRouted = r ; } |
127 | boolean wasRouted(){ return _isRouted ; } |
128 | boolean isStreamMode(){ return _mode == STREAM_MODE ; } |
129 | void touch(){ |
130 | if( _destination.isFirstDestination() ){ |
131 | _umid = new UOID() ; |
132 | } |
133 | } |
134 | CellMessage(){ |
135 | _mode = DUMMY_MODE ; |
136 | return ; |
137 | } |
138 | public CellMessage( CellMessage cm ) throws SerializationException { |
139 | if( cm._mode == ORIGINAL_MODE ){ |
140 | _originalToStream( cm ) ; |
141 | }else{ |
142 | _streamToOriginal( cm ) ; |
143 | } |
144 | } |
145 | void addSourceAddress( CellAddressCore source ){ |
146 | _source.add( source ) ; |
147 | } |
148 | /* |
149 | void markPersistent(){ _source.wasStored() ; } |
150 | */ |
151 | // |
152 | // and private |
153 | // |
154 | private void _copyInternalStuff(CellMessage cm){ |
155 | _destination = (CellPath)cm._destination.clone() ; |
156 | _source = (CellPath)cm._source.clone() ; |
157 | _markDestination = cm._markDestination==null?null: |
158 | (CellPath)cm._markDestination.clone() ; |
159 | _markSource = cm._markSource==null?null: |
160 | (CellPath)cm._markSource.clone() ; |
161 | _creationTime = cm._creationTime ; |
162 | _receivedAt = cm._receivedAt; |
163 | _umid = cm._umid ; // UOID is immutable |
164 | _lastUmid = cm._lastUmid ; |
165 | _hopCount = cm._hopCount ; |
166 | _isPersistent = cm._isPersistent ; |
167 | _isAcknowledge = cm._isAcknowledge ; |
168 | _session = cm._session; |
169 | _ttl = cm._ttl; |
170 | } |
171 | private void _originalToStream( CellMessage cm ) |
172 | throws SerializationException { |
173 | _copyInternalStuff( cm ) ; |
174 | _mode = STREAM_MODE ; |
175 | // |
176 | // here we have to make a bytestream out of the message object ; |
177 | // |
178 | ObjectOutputStream out = null ; |
179 | ByteArrayOutputStream array = null ; |
180 | try{ |
181 | array = new ByteArrayOutputStream() ; |
182 | out = new ObjectOutputStream( array ) ; |
183 | out.writeObject( cm._message ) ; |
184 | } catch (InvalidClassException e) { |
185 | throw new SerializationException("Failed to serialize object: " |
186 | + e + "(this is usually a bug)", e); |
187 | } catch (NotSerializableException e) { |
188 | throw new SerializationException("Failed to serialize object because the object is not serializable (this is usually a bug)", e); |
189 | } catch (IOException e) { |
190 | throw new SerializationException("Failed to serialize object: " + e, e); |
191 | } |
192 | _messageStream = array.toByteArray() ; |
193 | |
194 | } |
195 | private void _streamToOriginal( CellMessage cm ) |
196 | throws SerializationException { |
197 | _copyInternalStuff( cm ) ; |
198 | _mode = ORIGINAL_MODE ; |
199 | ByteArrayInputStream in = null ; |
200 | ObjectInputStream stream = null ; |
201 | try{ |
202 | in = new ByteArrayInputStream( cm._messageStream ) ; |
203 | stream = new ObjectInputStream( in ) ; |
204 | _message = stream.readObject() ; |
205 | } catch (ClassNotFoundException e) { |
206 | throw new SerializationException("Failed to deserialize object: The class could not be found. Is there a software version mismatch in your installation?", e); |
207 | } catch (IOException e) { |
208 | throw new SerializationException("Failed to deserialize object: " + e, e); |
209 | } |
210 | |
211 | } |
212 | |
213 | private void readObject(ObjectInputStream stream) |
214 | throws IOException, ClassNotFoundException |
215 | { |
216 | stream.defaultReadObject(); |
217 | _receivedAt = System.currentTimeMillis(); |
218 | if (_ttl == 0) { |
219 | _ttl = Long.MAX_VALUE; |
220 | } |
221 | } |
222 | |
223 | /** |
224 | * Returns the number of milliseconds since this message was |
225 | * received by the local domain. If the message created in the |
226 | * local domain, then the method returns the number of |
227 | * milliseconds since it was created. |
228 | */ |
229 | public long getLocalAge() |
230 | { |
231 | return System.currentTimeMillis() - _receivedAt; |
232 | } |
233 | } |