001 /**
002 * GRANITE DATA SERVICES
003 * Copyright (C) 2006-2013 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 package org.granite.client.messaging.messages;
021
022 import java.io.IOException;
023 import java.io.ObjectInput;
024 import java.io.ObjectOutput;
025 import java.util.HashMap;
026 import java.util.Map;
027
028 import org.granite.util.UUIDUtil;
029
030 /**
031 * @author Franck WOLFF
032 */
033 public abstract class AbstractMessage implements Message {
034
035 private String id = UUIDUtil.randomUUID();
036 private String clientId = null;
037
038 private long timestamp = 0L;
039 private long timeToLive = 0L;
040
041 private Map<String, Object> headers = new HashMap<String, Object>();
042
043 public AbstractMessage() {
044 }
045
046 public AbstractMessage(String clientId) {
047 this.clientId = clientId;
048 }
049
050 public AbstractMessage(
051 String id,
052 String clientId,
053 long timestamp,
054 long timeToLive,
055 Map<String, Object> headers) {
056
057 setId(id);
058 this.clientId = clientId;
059 this.timestamp = timestamp;
060 this.timeToLive = timeToLive;
061 this.headers = headers;
062 }
063
064 @Override
065 public String getId() {
066 return id;
067 }
068
069 @Override
070 public void setId(String id) {
071 if (id == null)
072 throw new NullPointerException("id cannot be null");
073 this.id = id;
074 }
075
076 @Override
077 public String getClientId() {
078 return clientId;
079 }
080
081 @Override
082 public void setClientId(String clientId) {
083 this.clientId = clientId;
084 }
085
086 @Override
087 public long getTimestamp() {
088 return timestamp;
089 }
090
091 @Override
092 public void setTimestamp(long timestamp) {
093 this.timestamp = timestamp;
094 }
095
096 @Override
097 public long getTimeToLive() {
098 return timeToLive;
099 }
100
101 @Override
102 public void setTimeToLive(long timeToLive) {
103 this.timeToLive = timeToLive;
104 }
105
106 @Override
107 public Map<String, Object> getHeaders() {
108 return headers;
109 }
110
111 @Override
112 public void setHeaders(Map<String, Object> headers) {
113 if (headers == null)
114 throw new NullPointerException("headers cannot be null");
115 this.headers = headers;
116 }
117
118 @Override
119 public Object getHeader(String name) {
120 return headers.get(name);
121 }
122
123 @Override
124 public void setHeader(String name, Object value) {
125 headers.put(name, value);
126 }
127
128 @Override
129 public boolean headerExists(String name) {
130 return headers.containsKey(name);
131 }
132
133 @Override
134 public boolean isExpired() {
135 return isExpired(System.currentTimeMillis());
136 }
137
138 @Override
139 public boolean isExpired(long currentTimeMillis) {
140 return getRemainingTimeToLive(currentTimeMillis) < 0;
141 }
142
143 @Override
144 public long getRemainingTimeToLive() {
145 return getRemainingTimeToLive(System.currentTimeMillis());
146 }
147
148 @Override
149 public long getRemainingTimeToLive(long currentTimeMillis) {
150 if (timestamp <= 0L || this.timeToLive <= 0L)
151 throw new IllegalStateException("Unset timestamp/timeToLive: {timestamp=" + timestamp + ", timeToLive=" + timeToLive + "}");
152 return timestamp + timeToLive - currentTimeMillis;
153 }
154
155 protected void copy(AbstractMessage message) {
156 message.id = id;
157 message.clientId = clientId;
158 message.timestamp = timestamp;
159 message.timeToLive = timeToLive;
160 message.headers.putAll(headers);
161 }
162
163 @Override
164 public Message clone() throws CloneNotSupportedException {
165 return copy();
166 }
167
168 @Override
169 @SuppressWarnings("unchecked")
170 public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
171 String id = in.readUTF();
172 if (id == null)
173 throw new RuntimeException("Message id cannot be null");
174 this.id = id;
175
176 clientId = in.readUTF();
177
178 timestamp = in.readLong();
179 timeToLive = in.readLong();
180
181 Map<String, Object> headers = (Map<String, Object>)in.readObject();
182 if (headers != null)
183 this.headers = headers;
184 }
185
186 @Override
187 public void writeExternal(ObjectOutput out) throws IOException {
188 out.writeUTF(id);
189 if (clientId != null)
190 out.writeUTF(clientId);
191 else
192 out.writeObject(null);
193
194 out.writeLong(timestamp);
195 out.writeLong(timeToLive);
196
197 if (headers.size() > 0)
198 out.writeObject(headers);
199 else
200 out.writeObject(null);
201 }
202
203 @Override
204 public boolean equals(Object obj) {
205 return (obj instanceof AbstractMessage && id.equals(((AbstractMessage)obj).id));
206 }
207
208 @Override
209 public int hashCode() {
210 return id.hashCode();
211 }
212
213 @Override
214 public String toString() {
215 return toString(new StringBuilder(getClass().getName()).append(" {")).append("\n}").toString();
216 }
217
218 public StringBuilder toString(StringBuilder sb) {
219 return sb
220 .append("\n id=").append(id)
221 .append("\n clientId=").append(clientId)
222 .append("\n timestamp=").append(timestamp)
223 .append("\n timeToLive=").append(timeToLive)
224 .append("\n headers=").append(headers);
225 }
226 }