001 /*
002 GRANITE DATA SERVICES
003 Copyright (C) 2012 GRANITE DATA SERVICES S.A.S.
004
005 This file is part of Granite Data Services.
006
007 Granite Data Services is free software; you can redistribute it and/or modify
008 it under the terms of the GNU Library General Public License as published by
009 the Free Software Foundation; either version 2 of the License, or (at your
010 option) any later version.
011
012 Granite Data Services is distributed in the hope that it will be useful, but
013 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
014 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
015 for more details.
016
017 You should have received a copy of the GNU Library General Public License
018 along with this library; if not, see <http://www.gnu.org/licenses/>.
019 */
020
021 package org.granite.client.messaging.messages;
022
023 import java.io.IOException;
024 import java.io.ObjectInput;
025 import java.io.ObjectOutput;
026 import java.util.HashMap;
027 import java.util.Map;
028
029 import org.granite.util.UUIDUtil;
030
031 /**
032 * @author Franck WOLFF
033 */
034 public abstract class AbstractMessage implements Message {
035
036 private String id = UUIDUtil.randomUUID();
037 private String clientId = null;
038
039 private long timestamp = 0L;
040 private long timeToLive = 0L;
041
042 private Map<String, Object> headers = new HashMap<String, Object>();
043
044 public AbstractMessage() {
045 }
046
047 public AbstractMessage(String clientId) {
048 this.clientId = clientId;
049 }
050
051 public AbstractMessage(
052 String id,
053 String clientId,
054 long timestamp,
055 long timeToLive,
056 Map<String, Object> headers) {
057
058 setId(id);
059 this.clientId = clientId;
060 this.timestamp = timestamp;
061 this.timeToLive = timeToLive;
062 this.headers = headers;
063 }
064
065 @Override
066 public String getId() {
067 return id;
068 }
069
070 @Override
071 public void setId(String id) {
072 if (id == null)
073 throw new NullPointerException("id cannot be null");
074 this.id = id;
075 }
076
077 @Override
078 public String getClientId() {
079 return clientId;
080 }
081
082 @Override
083 public void setClientId(String clientId) {
084 this.clientId = clientId;
085 }
086
087 @Override
088 public long getTimestamp() {
089 return timestamp;
090 }
091
092 @Override
093 public void setTimestamp(long timestamp) {
094 this.timestamp = timestamp;
095 }
096
097 @Override
098 public long getTimeToLive() {
099 return timeToLive;
100 }
101
102 @Override
103 public void setTimeToLive(long timeToLive) {
104 this.timeToLive = timeToLive;
105 }
106
107 @Override
108 public Map<String, Object> getHeaders() {
109 return headers;
110 }
111
112 @Override
113 public void setHeaders(Map<String, Object> headers) {
114 if (headers == null)
115 throw new NullPointerException("headers cannot be null");
116 this.headers = headers;
117 }
118
119 @Override
120 public Object getHeader(String name) {
121 return headers.get(name);
122 }
123
124 @Override
125 public void setHeader(String name, Object value) {
126 headers.put(name, value);
127 }
128
129 @Override
130 public boolean headerExists(String name) {
131 return headers.containsKey(name);
132 }
133
134 @Override
135 public boolean isExpired() {
136 return isExpired(System.currentTimeMillis());
137 }
138
139 @Override
140 public boolean isExpired(long currentTimeMillis) {
141 return getRemainingTimeToLive(currentTimeMillis) < 0;
142 }
143
144 @Override
145 public long getRemainingTimeToLive() {
146 return getRemainingTimeToLive(System.currentTimeMillis());
147 }
148
149 @Override
150 public long getRemainingTimeToLive(long currentTimeMillis) {
151 if (timestamp <= 0L || this.timeToLive <= 0L)
152 throw new IllegalStateException("Unset timestamp/timeToLive: {timestamp=" + timestamp + ", timeToLive=" + timeToLive + "}");
153 return timestamp + timeToLive - currentTimeMillis;
154 }
155
156 protected void copy(AbstractMessage message) {
157 message.id = id;
158 message.clientId = clientId;
159 message.timestamp = timestamp;
160 message.timeToLive = timeToLive;
161 message.headers.putAll(headers);
162 }
163
164 @Override
165 public Message clone() throws CloneNotSupportedException {
166 return copy();
167 }
168
169 @Override
170 @SuppressWarnings("unchecked")
171 public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
172 String id = in.readUTF();
173 if (id == null)
174 throw new RuntimeException("Message id cannot be null");
175 this.id = id;
176
177 clientId = in.readUTF();
178
179 timestamp = in.readLong();
180 timeToLive = in.readLong();
181
182 Map<String, Object> headers = (Map<String, Object>)in.readObject();
183 if (headers != null)
184 this.headers = headers;
185 }
186
187 @Override
188 public void writeExternal(ObjectOutput out) throws IOException {
189 out.writeUTF(id);
190 if (clientId != null)
191 out.writeUTF(clientId);
192 else
193 out.writeObject(null);
194
195 out.writeLong(timestamp);
196 out.writeLong(timeToLive);
197
198 if (headers.size() > 0)
199 out.writeObject(headers);
200 else
201 out.writeObject(null);
202 }
203
204 @Override
205 public boolean equals(Object obj) {
206 return (obj instanceof AbstractMessage && id.equals(((AbstractMessage)obj).id));
207 }
208
209 @Override
210 public int hashCode() {
211 return id.hashCode();
212 }
213
214 @Override
215 public String toString() {
216 return toString(new StringBuilder(getClass().getName()).append(" {")).append("\n}").toString();
217 }
218
219 public StringBuilder toString(StringBuilder sb) {
220 return sb
221 .append("\n id=").append(id)
222 .append("\n clientId=").append(clientId)
223 .append("\n timestamp=").append(timestamp)
224 .append("\n timeToLive=").append(timeToLive)
225 .append("\n headers=").append(headers);
226 }
227 }