Refactor logging to use slf4j
[iotivity.git] / cloud / stack / src / main / java / org / iotivity / cloud / base / protocols / coap / CoapLogHandler.java
1 /*
2  * //******************************************************************
3  * //
4  * // Copyright 2016 Samsung Electronics All Rights Reserved.
5  * //
6  * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7  * //
8  * // Licensed under the Apache License, Version 2.0 (the "License");
9  * // you may not use this file except in compliance with the License.
10  * // You may obtain a copy of the License at
11  * //
12  * //      http://www.apache.org/licenses/LICENSE-2.0
13  * //
14  * // Unless required by applicable law or agreed to in writing, software
15  * // distributed under the License is distributed on an "AS IS" BASIS,
16  * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * // See the License for the specific language governing permissions and
18  * // limitations under the License.
19  * //
20  * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21  */
22 package org.iotivity.cloud.base.protocols.coap;
23
24 import java.util.ArrayList;
25
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
28 import org.iotivity.cloud.base.OICConstants;
29 import org.iotivity.cloud.base.protocols.enums.ContentFormat;
30 import org.iotivity.cloud.util.Cbor;
31
32 import com.google.gson.Gson;
33
34 import io.netty.channel.ChannelDuplexHandler;
35 import io.netty.channel.ChannelHandler.Sharable;
36 import io.netty.channel.ChannelHandlerContext;
37 import io.netty.channel.ChannelPromise;
38 import org.slf4j.MDC;
39
40 /**
41  *
42  * This class provides a set of APIs to print out logs for CoAP request and
43  * response.
44  *
45  */
46 @Sharable
47 public class CoapLogHandler extends ChannelDuplexHandler {
48     private final static Logger     Log                         = LoggerFactory.getLogger(CoapLogHandler.class);
49     public static final String      COAP_MESSAGE_PAYLOAD        = "coappayload";
50     private Cbor<Object>            mCbor                       = new Cbor<>();
51     private Gson                    mGson                       = new Gson();
52
53     @Override
54     public void channelActive(ChannelHandlerContext ctx) throws Exception {
55         Log.trace("[{}] Connected, Address: {}", ctx.channel().id().asLongText().substring(26),
56                 ctx.channel().remoteAddress().toString());
57
58         ctx.fireChannelActive();
59     }
60
61     @Override
62     public void channelInactive(ChannelHandlerContext ctx) throws Exception {
63         Log.trace("[{}] Disconnected, Address: {}", ctx.channel().id().asLongText().substring(26),
64                 ctx.channel().remoteAddress().toString());
65
66         ctx.fireChannelInactive();
67     }
68
69     @Override
70     public void write(ChannelHandlerContext ctx, Object msg,
71             ChannelPromise promise) {
72
73         String log = null;
74
75         if (msg instanceof CoapRequest) {
76             log = composeCoapRequest(
77                     ctx.channel().id().asLongText().substring(26),
78                     (CoapRequest) msg);
79         } else if (msg instanceof CoapResponse) {
80             log = composeCoapResponse(ctx.channel().id().asLongText()
81                     .substring(26), (CoapResponse) msg);
82         }
83
84         if (log != null) {
85             Log.trace(log);
86         }
87
88         ctx.writeAndFlush(msg);
89     }
90
91     @Override
92     public void channelRead(ChannelHandlerContext ctx, Object msg)
93             throws Exception {
94
95         String log = null;
96
97         if (msg instanceof CoapRequest) {
98             log = composeCoapRequest(
99                     ctx.channel().id().asLongText().substring(26),
100                     (CoapRequest) msg);
101         } else if (msg instanceof CoapResponse) {
102             log = composeCoapResponse(ctx.channel().id().asLongText()
103                     .substring(26), (CoapResponse) msg);
104         }
105
106         if (log != null) {
107             Log.trace(log);
108         }
109
110         ctx.fireChannelRead(msg);
111     }
112
113     private String composeCoapRequest(String channelId, CoapRequest request) {
114         StringBuilder strBuilder = new StringBuilder();
115
116         strBuilder.append("[" + channelId + "]");
117         strBuilder.append(" [" + request.getTokenString() + "]");
118
119         switch (request.getMethod()) {
120             case DELETE:
121                 strBuilder.append(" [DELETE] ");
122                 break;
123             case GET:
124                 switch (request.getObserve()) {
125                     case SUBSCRIBE:
126                         strBuilder.append(" [GET OBSERVE] ");
127                         break;
128                     case UNSUBSCRIBE:
129                         strBuilder.append(" [GET OBSERVE CANCEL] ");
130                         break;
131                     default:
132                         strBuilder.append(" [GET] ");
133                         break;
134                 }
135                 break;
136             case POST:
137                 strBuilder.append(" [POST] ");
138                 break;
139             case PUT:
140                 strBuilder.append(" [PUT] ");
141                 break;
142         }
143
144         strBuilder.append(request.getUriPath());
145         String query = request.getUriQuery();
146         if (query != null) {
147             strBuilder.append("/?" + query);
148         }
149
150         if (request.getPayloadSize() > 0) {
151             strBuilder.append(" CT:" + request.getContentFormat());
152             strBuilder.append(" SZ:" + request.getPayloadSize());
153             MDC.put(COAP_MESSAGE_PAYLOAD, "P: " + getJsonPayloadString(request));
154         }
155
156         return strBuilder.toString();
157     }
158
159     private String composeCoapResponse(String channelId,
160             CoapResponse response) {
161         StringBuilder strBuilder = new StringBuilder();
162
163         strBuilder.append("[" + channelId + "]");
164         strBuilder.append(" [" + response.getTokenString() + "]");
165
166         switch (response.getStatus()) {
167             case BAD_GATEWAY:
168                 strBuilder.append(" 5.02 Bad Gateway");
169                 break;
170             case BAD_OPTION:
171                 strBuilder.append(" 4.02 Bad Option");
172                 break;
173             case BAD_REQUEST:
174                 strBuilder.append(" 4.00 Bad Request");
175                 break;
176             case CHANGED:
177                 strBuilder.append(" 2.04 Changed");
178                 break;
179             case CONTENT:
180                 strBuilder.append(" 2.05 Content");
181                 break;
182             case CREATED:
183                 strBuilder.append(" 2.01 Created");
184                 break;
185             case DELETED:
186                 strBuilder.append(" 2.02 Deleted");
187                 break;
188             case FORBIDDEN:
189                 strBuilder.append(" 4.03 Forbidden");
190                 break;
191             case GATEWAY_TIMEOUT:
192                 strBuilder.append(" 5.04 Gateway Timeout");
193                 break;
194             case INTERNAL_SERVER_ERROR:
195                 strBuilder.append(" 5.00 Internal Server Error");
196                 break;
197             case METHOD_NOT_ALLOWED:
198                 strBuilder.append(" 4.05 Method Not Allowed");
199                 break;
200             case NOT_ACCEPTABLE:
201                 strBuilder.append(" 4.06 Not Acceptable");
202                 break;
203             case NOT_FOUND:
204                 strBuilder.append(" 4.04 Not Found");
205                 break;
206             case NOT_IMPLEMENTED:
207                 strBuilder.append(" 5.01 Not Implemented");
208                 break;
209             case PRECONDITION_FAILED:
210                 strBuilder.append(" 4.12 Precondition Failed");
211                 break;
212             case PROXY_NOT_SUPPORTED:
213                 strBuilder.append(" 5.05 Proxying Not Supported");
214                 break;
215             case REQUEST_ENTITY_TOO_LARGE:
216                 strBuilder.append(" 4.13 Request Entity Too Large");
217                 break;
218             case SERVICE_UNAVAILABLE:
219                 strBuilder.append(" 5.03 Service Unavailable");
220                 break;
221             case UNAUTHORIZED:
222                 strBuilder.append(" 4.01 Unauthorized");
223                 break;
224             case UNSUPPORTED_CONTENT_FORMAT:
225                 strBuilder.append(" 4.15 Unsupported Content-Format");
226                 break;
227             case VALID:
228                 strBuilder.append(" 2.03 Valid");
229                 break;
230             default:
231                 break;
232         }
233
234         switch (response.getObserve()) {
235             case SUBSCRIBE:
236                 strBuilder.append(" OBSERVE");
237                 break;
238             case UNSUBSCRIBE:
239                 strBuilder.append(" OBSERVE CANCEL");
240                 break;
241             case SEQUENCE_NUMBER:
242                 strBuilder.append(" OBSERVE SEQ:");
243                 strBuilder.append(response.getSequenceNumber());
244                 break;
245             default:
246                 break;
247         }
248
249         if (response.getPayloadSize() > 0) {
250             strBuilder.append(" CT:" + response.getContentFormat());
251             strBuilder.append(" SZ:" + response.getPayloadSize());
252             MDC.put(COAP_MESSAGE_PAYLOAD, "P: " + getJsonPayloadString(response));
253         }
254
255         return strBuilder.toString();
256     }
257
258     private String getJsonPayloadString(CoapMessage coapMessage) {
259         String jsonPayload = null;
260         if (coapMessage.getContentFormat() == ContentFormat.APPLICATION_CBOR) {
261
262             Object mapPayload = mCbor.parsePayloadFromCbor(
263                     coapMessage.getPayload(), Object.class);
264             if (coapMessage.getUriPath()
265                     .contains(OICConstants.WELL_KNOWN_FULL_URI)) {
266                 return mGson.toJson((ArrayList<Object>) mapPayload);
267             }
268             return mGson.toJson(mapPayload);
269         }
270         return jsonPayload;
271     }
272 }