1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.mina.coap;
21
22 import java.io.UnsupportedEncodingException;
23 import java.nio.ByteBuffer;
24 import java.nio.ByteOrder;
25 import java.util.ArrayList;
26 import java.util.Arrays;
27 import java.util.Collection;
28 import java.util.Comparator;
29
30 import org.apache.mina.filter.query.Request;
31 import org.apache.mina.filter.query.Response;
32
33
34
35
36
37
38 public class CoapMessage implements Request, Response {
39
40 public static final CoapMessage get(String url, boolean confimable) {
41
42 return new CoapMessage(1, confimable ? MessageType.CONFIRMABLE : MessageType.NON_CONFIRMABLE,
43 CoapCode.GET.getCode(), (int) (System.nanoTime() % 65536), null, optionsForUrl(url), null);
44 }
45
46 public static final CoapMessage post(String url, boolean confimable, byte[] payload) {
47
48 return new CoapMessage(1, confimable ? MessageType.CONFIRMABLE : MessageType.NON_CONFIRMABLE,
49 CoapCode.GET.getCode(), (int) (System.nanoTime() % 65536), null, optionsForUrl(url), payload);
50 }
51
52 private static final CoapOption[] optionsForUrl(String url) {
53 String[] parts = url.split("\\?");
54
55 String[] paths = parts[0].split("\\/");
56
57 String[] params = new String[] {};
58
59 if (parts.length > 1) {
60 params = parts[1].split("\\&");
61 }
62 CoapOption[] opt = new CoapOption[paths.length + params.length];
63 for (int i = 0; i < paths.length; i++) {
64 try {
65 opt[i] = new CoapOption(CoapOptionType.URI_PATH, paths[i].getBytes("UTF-8"));
66 } catch (UnsupportedEncodingException e) {
67 throw new IllegalStateException(e);
68 }
69 }
70
71 for (int i = 0; i < params.length; i++) {
72 try {
73 opt[paths.length + i] = new CoapOption(CoapOptionType.URI_QUERY, params[i].getBytes("UTF-8"));
74 } catch (UnsupportedEncodingException e) {
75 throw new IllegalStateException(e);
76 }
77 }
78
79 return opt;
80 }
81
82 private static final byte[] EMPTY_BYTE_ARRAY = new byte[] {};
83
84 private int version;
85
86 private MessageType type;
87
88 private int code;
89
90 private int id;
91
92 private byte[] token;
93
94 private byte[] payload;
95
96 private CoapOption[] options;
97
98
99
100
101
102
103
104
105
106
107
108
109 public CoapMessage(int version, MessageType type, int code, int id, byte[] token, CoapOption[] options,
110 byte[] payload) {
111 super();
112 this.version = version;
113 this.type = type;
114 this.code = code;
115 this.id = id;
116 this.token = token == null ? EMPTY_BYTE_ARRAY : token;
117 this.payload = payload == null ? EMPTY_BYTE_ARRAY : payload;
118 this.options = options == null ? new CoapOption[] {} : options;
119
120
121 Arrays.<CoapOption> sort(this.options, new Comparator<CoapOption>() {
122 @Override
123 public int compare(CoapOption o1, CoapOption o2) {
124 return o1.getType().getCode() < o2.getType().getCode() ? -1 : (o1.getType().getCode() == o2.getType()
125 .getCode() ? 0 : 1);
126 };
127 });
128 }
129
130
131
132
133 @Override
134 public Object requestId() {
135 return id;
136 }
137
138 public int getVersion() {
139 return version;
140 }
141
142 public int getCode() {
143 return code;
144 }
145
146 public int getId() {
147 return id;
148 }
149
150 public byte[] getToken() {
151 return token;
152 }
153
154 public byte[] getPayload() {
155 return payload;
156
157 }
158
159 public CoapOption[] getOptions() {
160 return options;
161 }
162
163 public MessageType getType() {
164 return type;
165 }
166
167
168
169
170
171
172 public String[] getUriPath() {
173 return strArrayOptions(CoapOptionType.URI_PATH);
174 }
175
176
177
178
179 public String[] getUriQuery() {
180 return strArrayOptions(CoapOptionType.URI_QUERY);
181 }
182
183
184
185
186 public String getUriHost() {
187 return strOption(CoapOptionType.URI_HOST);
188 }
189
190
191
192
193 public Integer getUriPort() {
194 return intOption(CoapOptionType.URI_PORT);
195 }
196
197
198
199
200 public String getProxyUri() {
201 return strOption(CoapOptionType.PROXY_URI);
202 }
203
204
205
206
207 public String getProxyScheme() {
208 return strOption(CoapOptionType.PROXY_SCHEME);
209 }
210
211
212
213
214 public Integer getContentFormat() {
215 return intOption(CoapOptionType.CONTENT_FORMAT);
216 }
217
218
219
220
221 public Integer getAccept() {
222 return intOption(CoapOptionType.ACCEPT);
223 }
224
225
226
227
228 public Integer getMaxAge() {
229 return intOption(CoapOptionType.MAX_AGE);
230 }
231
232
233
234
235 public String[] getLocationPath() {
236 return strArrayOptions(CoapOptionType.LOCATION_PATH);
237 }
238
239
240
241
242 public String[] getLocationQuery() {
243 return strArrayOptions(CoapOptionType.LOCATION_QUERY);
244 }
245
246 private String strOption(CoapOptionType type) {
247 if (options != null) {
248 for (CoapOption option : options) {
249 if (type.equals(option.getType())) {
250 try {
251 return new String(option.getData(), "UTF-8");
252 } catch (UnsupportedEncodingException e) {
253 throw new IllegalStateException(e);
254 }
255 }
256 }
257 }
258 return null;
259 }
260
261 private String[] strArrayOptions(CoapOptionType type) {
262 Collection<String> opts = new ArrayList<>();
263
264 if (options != null) {
265 for (CoapOption option : options) {
266 if (type.equals(option.getType())) {
267 try {
268 opts.add(new String(option.getData(), "UTF-8"));
269 } catch (UnsupportedEncodingException e) {
270 throw new IllegalStateException(e);
271 }
272 }
273 }
274 }
275
276 return opts.toArray(new String[0]);
277 }
278
279 private Integer intOption(CoapOptionType type) {
280 if (options != null) {
281 for (CoapOption option : options) {
282 if (type.equals(option.getType())) {
283 ByteBuffer bb = ByteBuffer.wrap(option.getData());
284 bb.order(ByteOrder.BIG_ENDIAN);
285 return bb.getInt();
286 }
287 }
288 }
289 return null;
290 }
291
292
293
294
295 @Override
296 public String toString() {
297 StringBuilder builder = new StringBuilder();
298 CoapCode c = CoapCode.fromCode(code);
299 String cstr;
300 if (c == null) {
301 cstr = String.valueOf(code);
302 } else {
303 cstr = c.getText();
304 }
305
306 builder.append("CoapMessage [version=").append(version).append(", type=").append(type).append(", code=")
307 .append(cstr).append(", id=").append(id).append(", token=").append(Arrays.toString(token))
308 .append(", payload=").append(Arrays.toString(payload)).append(", options=")
309 .append(Arrays.toString(options)).append("]");
310
311 return builder.toString();
312 }
313
314
315
316
317 @Override
318 public int hashCode() {
319 final int prime = 31;
320 int result = 1;
321 result = prime * result + code;
322 result = prime * result + id;
323 result = prime * result + Arrays.hashCode(options);
324 result = prime * result + Arrays.hashCode(payload);
325 result = prime * result + Arrays.hashCode(token);
326 result = prime * result + ((type == null) ? 0 : type.hashCode());
327 result = prime * result + version;
328
329 return result;
330 }
331
332
333
334
335 @Override
336 public boolean equals(Object obj) {
337 if (this == obj) {
338 return true;
339 }
340
341 if (obj == null) {
342 return false;
343 }
344
345 if (getClass() != obj.getClass()) {
346 return false;
347 }
348
349 CoapMessage other = (CoapMessage) obj;
350
351 if (code != other.code) {
352 return false;
353 }
354
355 if (id != other.id) {
356 return false;
357 }
358
359 if (!Arrays.equals(options, other.options)) {
360 return false;
361 }
362
363 if (!Arrays.equals(payload, other.payload)) {
364 return false;
365 }
366
367 if (!Arrays.equals(token, other.token)) {
368 return false;
369 }
370
371 if (type != other.type) {
372 return false;
373 }
374
375 if (version != other.version) {
376 return false;
377 }
378
379 return true;
380 }
381
382 public void setVersion(int version) {
383 this.version = version;
384 }
385
386 public void setType(MessageType type) {
387 this.type = type;
388 }
389
390 public void setCode(int code) {
391 this.code = code;
392 }
393
394 public void setId(int id) {
395 this.id = id;
396 }
397
398 public void setToken(byte[] token) {
399 this.token = token;
400 }
401
402 public void setPayload(byte[] payload) {
403 this.payload = payload;
404 }
405
406 public void setOptions(CoapOption[] options) {
407 this.options = options;
408 }
409
410 }