| 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 | } |