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 boolean excludeMyselfIfApplicable;
40  	
41  	private int channelId;
42  	
43  	private UnrealId targetId;
44  	
45  	private transient boolean resolved = false;
46  	private transient Serializable message = null;
47  	
48  	public TCMessage(UnrealId source, TCRecipient target, boolean excludeMyselfIfApplicable, IToken messageType, Serializable message, long simTime) {
49  		this.source = source;
50  		this.target = target;
51  		this.excludeMyselfIfApplicable = excludeMyselfIfApplicable;
52  		this.messageType = messageType;
53  		this.message = message;
54  		
55  		// TODO: use {@link ObjectManager} and pool instances!
56  		if (message == null) {
57  			this.messageData = null; 
58  		} else {
59  			ByteArrayOutputStream bos = new ByteArrayOutputStream();
60  			ObjectOutput out = null;
61  			try {
62  				out = new ObjectOutputStream(bos);
63  				out.writeObject(message);			
64  				this.messageData = bos.toByteArray();
65  			} catch (IOException e) {
66  				throw new PogamutException("Failed to serialize: " + message, e, this);
67  			} finally {
68  				if (out != null) {
69  					try {
70  						out.close();
71  					} catch (IOException e) {
72  					}
73  				}
74  				out = null;
75  				if (bos != null) {
76  					try {
77  						bos.close();
78  					} catch (IOException e) {
79  					}
80  					bos = null;
81  				}
82  			}
83  		}
84  		
85  		this.simTime = simTime;
86  	}
87  	
88  	private void readObject(ObjectInputStream ois) {
89  		try {
90  			ois.defaultReadObject();			
91  			if (this.messageType != null) {
92  				this.messageType = Tokens.get(this.messageType.getToken());
93  			}
94  			if (this.source != null) {
95  				this.source = UnrealId.get(source.getStringId());
96  			}
97  			
98  			this.resolved = false;
99  			this.message = null;
100 		} catch (RuntimeException re) {
101 			throw re;
102 		} catch (Exception e) {
103 			throw new RuntimeException("Failed to deserialize the object.", e);
104 		}
105 	}
106 	
107 	public IToken getMessageType() {
108 		return messageType;
109 	}
110 	
111 	public boolean isMessageType(String type) {
112 		return SafeEquals.equals(this.messageType, Tokens.get(type));
113 	}
114 	
115 	public boolean isMessageType(IToken type) {
116 		return SafeEquals.equals(this.messageType, type);
117 	}
118 	
119 	/**
120 	 * Attempts to deserialize {@link #messageData} and returns them.
121 	 * 
122 	 * Throws {@link PogamutException} if unsuccessful.
123 	 * 
124 	 * @return
125 	 * @throws PogamutException
126 	 */
127 	public Serializable getMessage() throws PogamutException {
128 		if (this.messageData == null) return null;
129 		if (this.message == null) {
130 			// DESERIALIZE
131 			// TODO: use {@link ObjectManager} and pool instances!
132 			ByteArrayInputStream bis = new ByteArrayInputStream(messageData);
133 			ObjectInput in = null;
134 			try {
135 			  in = new ObjectInputStream(bis);
136 			  message = (Serializable)in.readObject(); 		  
137 			} catch (Exception e) {
138 				throw new PogamutException("Failed to deserialize TCMessage of type " + messageType.getToken() + "...", this);
139 			} finally {
140 			  if (bis != null) {
141 				  try {
142 					bis.close();
143 				} catch (IOException e) {
144 				}
145 				  bis = null;
146 			  }
147 			  if (in != null) {
148 				  try {
149 					in.close();
150 				} catch (IOException e) {
151 				}
152 				in = null;
153 			  }
154 			}
155 		}
156 		return message;
157 	}
158 
159 	public Serializable getData() {
160 		return messageData;
161 	}
162 
163 	public TCRecipient getTarget() {
164 		return target;
165 	}
166 	
167 	public boolean isTarget(TCRecipient target) {
168 		return SafeEquals.equals(this.target, target);
169 	}
170 		
171 	public boolean isExcludeMyselfIfApplicable() {
172 		return excludeMyselfIfApplicable;
173 	}
174 
175 	public UnrealId getSource() {
176 		return source;
177 	}
178 	
179 	public int getChannelId() {
180 		return channelId;
181 	}
182 
183 	public void setChannelId(int channelId) {
184 		this.channelId = channelId;
185 	}
186 
187 	public UnrealId getTargetId() {
188 		return targetId;
189 	}
190 
191 	public void setTargetId(UnrealId targetId) {
192 		this.targetId = targetId;
193 	}
194 
195 	/**
196 	 * CLIENT SUPPORT for implementation of TCMessage filters, you can check whether this message has already been resolved by other filter. 
197 	 * @return
198 	 */
199 	public boolean isResolved() {
200 		return resolved;
201 	}
202 
203 	/**
204 	 * 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...
205 	 */
206 	public void markResolved() {
207 		this.resolved = true;
208 	}
209 
210 	@Override
211 	public long getSimTime() {
212 		return simTime;
213 	}
214 	
215 	@Override
216 	public String toString() {
217 		return "TCMessage[from=" + (source == null ? "NULL" : source.getStringId()) + ", messageType=" + (messageType == null ? "NULL" : messageType.getToken()) + ", target=" + target + "]";
218 	}
219 	
220 }