View Javadoc

1   package cz.cuni.amis.pogamut.ut2004.teamcomm.mina.messages;
2   
3   import java.io.ByteArrayInputStream;
4   import java.io.ByteArrayOutputStream;
5   import java.io.IOException;
6   import java.io.ObjectInput;
7   import java.io.ObjectInputStream;
8   import java.io.ObjectOutput;
9   import java.io.ObjectOutputStream;
10  import java.io.Serializable;
11  
12  import cz.cuni.amis.pogamut.base.communication.translator.event.IWorldChangeEvent;
13  import cz.cuni.amis.pogamut.base.communication.worldview.event.IWorldEvent;
14  import cz.cuni.amis.pogamut.unreal.communication.messages.UnrealId;
15  import cz.cuni.amis.utils.SafeEquals;
16  import cz.cuni.amis.utils.exception.PogamutException;
17  import cz.cuni.amis.utils.token.IToken;
18  import cz.cuni.amis.utils.token.Tokens;
19  
20  public class TCMessage implements IWorldChangeEvent, IWorldEvent, Serializable {
21  
22  	/**
23  	 * Auto-generated.
24  	 */
25  	private static final long serialVersionUID = 1656106303299952920L;
26  	
27  	private long simTime;
28  	private IToken messageType;
29  	
30  	/**
31  	 * We have to transport messages as byte[] because the server would not have concrete message classes available for deserialization... 
32  	 */
33  	private byte[] messageData;
34  	
35  	private UnrealId source;
36  	
37  	private TCRecipient target;
38  	
39  	private int channelId;
40  	
41  	private UnrealId targetId;
42  	
43  	private transient boolean resolved = false;
44  	private transient Serializable message = null;
45  	
46  	public TCMessage(UnrealId source, TCRecipient target, IToken messageType, Serializable message, long simTime) {
47  		this.source = source;
48  		this.target = target;
49  		this.messageType = messageType;
50  		this.message = message;
51  		
52  		// TODO: use {@link ObjectManager} and pool instances!
53  		if (message == null) {
54  			this.messageData = null; 
55  		} else {
56  			ByteArrayOutputStream bos = new ByteArrayOutputStream();
57  			ObjectOutput out = null;
58  			try {
59  				out = new ObjectOutputStream(bos);
60  				out.writeObject(message);			
61  				this.messageData = bos.toByteArray();
62  			} catch (IOException e) {
63  				throw new PogamutException("Failed to serialize: " + message, e, this);
64  			} finally {
65  				if (out != null) {
66  					try {
67  						out.close();
68  					} catch (IOException e) {
69  					}
70  				}
71  				out = null;
72  				if (bos != null) {
73  					try {
74  						bos.close();
75  					} catch (IOException e) {
76  					}
77  					bos = null;
78  				}
79  			}
80  		}
81  		
82  		this.simTime = simTime;
83  	}
84  	
85  	private void readObject(ObjectInputStream ois) {
86  		try {
87  			ois.defaultReadObject();			
88  			if (this.messageType != null) {
89  				this.messageType = Tokens.get(this.messageType.getToken());
90  			}
91  			if (this.source != null) {
92  				this.source = UnrealId.get(source.getStringId());
93  			}
94  			
95  			this.resolved = false;
96  			this.message = null;
97  		} catch (RuntimeException re) {
98  			throw re;
99  		} catch (Exception e) {
100 			throw new RuntimeException("Failed to deserialize the object.", e);
101 		}
102 	}
103 	
104 	public IToken getMessageType() {
105 		return messageType;
106 	}
107 	
108 	public boolean isMessageType(String type) {
109 		return SafeEquals.equals(this.messageType, Tokens.get(type));
110 	}
111 	
112 	public boolean isMessageType(IToken type) {
113 		return SafeEquals.equals(this.messageType, type);
114 	}
115 	
116 	/**
117 	 * Attempts to deserialize {@link #messageData} and returns them.
118 	 * 
119 	 * Throws {@link PogamutException} if unsuccessful.
120 	 * 
121 	 * @return
122 	 * @throws PogamutException
123 	 */
124 	public Serializable getMessage() throws PogamutException {
125 		if (this.messageData == null) return null;
126 		if (this.message == null) {
127 			// DESERIALIZE
128 			// TODO: use {@link ObjectManager} and pool instances!
129 			ByteArrayInputStream bis = new ByteArrayInputStream(messageData);
130 			ObjectInput in = null;
131 			try {
132 			  in = new ObjectInputStream(bis);
133 			  message = (Serializable)in.readObject(); 		  
134 			} catch (Exception e) {
135 				throw new PogamutException("Failed to deserialize TCMessage of type " + messageType.getToken() + "...", this);
136 			} finally {
137 			  if (bis != null) {
138 				  try {
139 					bis.close();
140 				} catch (IOException e) {
141 				}
142 				  bis = null;
143 			  }
144 			  if (in != null) {
145 				  try {
146 					in.close();
147 				} catch (IOException e) {
148 				}
149 				in = null;
150 			  }
151 			}
152 		}
153 		return message;
154 	}
155 
156 	public Serializable getData() {
157 		return messageData;
158 	}
159 
160 	public TCRecipient getTarget() {
161 		return target;
162 	}
163 	
164 	public boolean isTarget(TCRecipient target) {
165 		return SafeEquals.equals(this.target, target);
166 	}
167 	
168 	public UnrealId getSource() {
169 		return source;
170 	}
171 	
172 	public int getChannelId() {
173 		return channelId;
174 	}
175 
176 	public void setChannelId(int channelId) {
177 		this.channelId = channelId;
178 	}
179 
180 	public UnrealId getTargetId() {
181 		return targetId;
182 	}
183 
184 	public void setTargetId(UnrealId targetId) {
185 		this.targetId = targetId;
186 	}
187 
188 	/**
189 	 * CLIENT SUPPORT for implementation of TCMessage filters, you can check whether this message has already been resolved by other filter. 
190 	 * @return
191 	 */
192 	public boolean isResolved() {
193 		return resolved;
194 	}
195 
196 	/**
197 	 * CLIENT SUPPORT for implementation of TCMessage filters, you can mark this message as "resolved" within your logic to let your further filters know it was handled...
198 	 */
199 	public void markResolved() {
200 		this.resolved = true;
201 	}
202 
203 	@Override
204 	public long getSimTime() {
205 		return simTime;
206 	}
207 	
208 	@Override
209 	public String toString() {
210 		return "TCMessage[from=" + (source == null ? "NULL" : source.getStringId()) + ", messageType=" + (messageType == null ? "NULL" : messageType.getToken()) + ", target=" + target + "]";
211 	}
212 	
213 }