/* * Copyright 2013 Eediom Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.araqne.logdb.client.http.impl; import java.io.StringReader; import java.io.StringWriter; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import org.araqne.logdb.client.Message; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.json.JSONTokener; import org.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * 아라크네 메시지버스 RPC 전문을 JSON으로 인코딩하거나 디코딩합니다. * * @author xeraph@eediom.com * */ public class MessageCodec { private MessageCodec() { } public static Message decode(String text) { try { JSONTokener tokenizer = new JSONTokener(new StringReader(text)); JSONArray container = (JSONArray) tokenizer.nextValue(); JSONObject header = container.getJSONObject(0); JSONObject body = container.getJSONObject(1); Message msg = new Message(); msg.setGuid(header.getString("guid").trim()); msg.setType(Message.Type.valueOf(header.getString("type").trim())); msg.setSource(header.getString("source")); msg.setTarget(header.getString("target")); msg.setMethod(header.getString("method").trim()); if (header.has("requestId")) msg.setRequestId(header.getString("requestId").trim()); if (header.has("errorCode")) { msg.setErrorCode(header.getString("errorCode")); if (!header.isNull("errorMessage")) msg.setErrorMessage(header.getString("errorMessage")); } msg.setParameters(parse(body)); return msg; } catch (JSONException e) { throw new IllegalStateException("json parse error: " + text, e); } } public static String encode(Message msg) { Map<String, Object> headers = new HashMap<String, Object>(); headers.put("guid", msg.getGuid()); if (msg.getRequestId() != null) headers.put("requestId", msg.getRequestId()); headers.put("type", msg.getType().toString()); headers.put("method", msg.getMethod()); headers.put("session", msg.getSession()); headers.put("source", msg.getSource()); headers.put("target", msg.getTarget()); if (msg.getErrorCode() != null) { headers.put("errorCode", msg.getErrorCode()); headers.put("errorMessage", msg.getErrorMessage()); } return jsonize(headers, msg.getParameters()); } private static Map<String, Object> parse(JSONObject obj) { Map<String, Object> m = new HashMap<String, Object>(); String[] names = JSONObject.getNames(obj); if (names == null) return m; for (String key : names) { try { Object value = obj.get(key); if (value == JSONObject.NULL) value = null; else if (value instanceof JSONArray) value = parse((JSONArray) value); else if (value instanceof JSONObject) value = parse((JSONObject) value); m.put(key, value); } catch (JSONException e) { Logger logger = LoggerFactory.getLogger(MessageCodec.class); logger.error("araqne logdb client: invalid msgbus json - " + obj, e); } } return m; } private static List<Object> parse(JSONArray arr) { List<Object> list = new ArrayList<Object>(); for (int i = 0; i < arr.length(); i++) { try { Object o = arr.get(i); if (o == JSONObject.NULL) list.add(null); else if (o instanceof JSONArray) list.add(parse((JSONArray) o)); else if (o instanceof JSONObject) list.add(parse((JSONObject) o)); else list.add(o); } catch (JSONException e) { Logger logger = LoggerFactory.getLogger(MessageCodec.class); logger.error("araqne logdb client: invalid msgbus json - " + arr, e); } } return list; } private static String jsonize(Map<String, Object> headers, Map<String, Object> properties) { StringWriter writer = new StringWriter(1024); JSONWriter jsonWriter = new JSONWriter(writer); try { jsonWriter.array(); jsonWriter.object(); for (String key : headers.keySet()) { jsonWriter.key(key).value(headers.get(key)); } jsonWriter.endObject(); jsonWriter.object(); properties = convertDate(properties); for (String key : properties.keySet()) { jsonWriter.key(key).value(properties.get(key)); } jsonWriter.endObject(); jsonWriter.endArray(); } catch (Exception e) { throw new IllegalStateException("cannot encode json", e); } return writer.toString(); } @SuppressWarnings("unchecked") private static Map<String, Object> convertDate(Map<String, Object> properties) { Map<String, Object> m = new HashMap<String, Object>(); if (properties == null) return m; SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssZ"); for (String key : properties.keySet()) { Object value = properties.get(key); if (value instanceof Date) m.put(key, dateFormat.format((Date) value)); else if (value instanceof Map) m.put(key, convertDate((Map<String, Object>) value)); else if (value instanceof Collection) { Collection<Object> c = new ArrayList<Object>(); for (Object v : (Collection<?>) value) { if (v instanceof Date) c.add(dateFormat.format((Date) v)); else c.add(v); } m.put(key, c); } else m.put(key, value); } return m; } }