Java tutorial
/* * Copyright 2015 Chiwan Park * * 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 com.chiwanpark.flume.plugins; import com.google.gson.JsonParser; import com.google.gson.JsonObject; import com.google.gson.JsonElement; import java.nio.charset.Charset; import java.nio.charset.UnsupportedCharsetException; import java.util.HashMap; import java.util.Map; import org.apache.flume.Event; import org.apache.flume.event.EventBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * * JSONHandler for RedisSource that accepts a string message. * * This handler throws exception if the deserialization fails because of bad * format or any other reason. * * * Each event must be encoded as a map with two key-value pairs. <p> 1. headers * - the key for this key-value pair is "headers". The value for this key is * another map, which represent the event headers. These headers are inserted * into the Flume event as is. <p> 2. body - The body is a string which * represents the body of the event. The key for this key-value pair is "body". * All key-value pairs are considered to be headers. An example: <p> [{"headers" * : {"a":"b", "c":"d"},"body": "random_body"}, {"headers" : {"e": "f"},"body": * "random_body2"}] <p> would be interpreted as the following two flume events: * <p> * Event with body: "random_body" (in UTF-8/UTF-16/UTF-32 encoded bytes) * and headers : (a:b, c:d) <p> * * Event with body: "random_body2" (in UTF-8/UTF-16/UTF-32 encoded bytes) and * headers : (e:f) <p> * * The charset of the body is read from the request and used. If no charset is * set in the request, then the charset is assumed to be JSON's default - UTF-8. * The JSON handler supports UTF-8, UTF-16 and UTF-32. * * To set the charset, the request must have content type specified as * "application/json; charset=UTF-8" (replace UTF-8 with UTF-16 or UTF-32 as * required). * */ public class JSONHandler extends RedisSourceHandler { private static final Logger LOG = LoggerFactory.getLogger(JSONHandler.class); private final JsonParser parser; /** * {@inheritDoc} */ public JSONHandler(String charset) { super(charset); //UTF-8 is default for JSON. If no charset is specified, UTF-8 is to //be assumed. if (charset == null) { LOG.debug("Charset is null, default charset of UTF-8 will be used."); charset = "UTF-8"; } else if (!(charset.equalsIgnoreCase("utf-8") || charset.equalsIgnoreCase("utf-16") || charset.equalsIgnoreCase("utf-32"))) { LOG.error("Unsupported character set in request {}. " + "JSON handler supports UTF-8, " + "UTF-16 and UTF-32 only.", charset); throw new UnsupportedCharsetException("JSON handler supports UTF-8, " + "UTF-16 and UTF-32 only."); } parser = new JsonParser(); } /** * {@inheritDoc} */ @Override public Event getEvent(String message) throws Exception { /* * Gson throws Exception if the data is not parseable to JSON. * Need not catch it since the source will catch it and return error. */ JsonObject json = parser.parse(message).getAsJsonObject(); String body = ""; JsonElement bodyElm = json.get("body"); if (bodyElm != null) { body = bodyElm.toString(); } HashMap<String, String> headers = null; if (json.has("headers")) { headers = new HashMap<String, String>(); for (Map.Entry<String, JsonElement> header : json.get("headers").getAsJsonObject().entrySet()) { if (header.getValue().isJsonPrimitive()) { headers.put(header.getKey(), header.getValue().getAsString()); } else { // If a header is not a json primitive (it contains subfields), // we have to use toString() to get it as valid json. headers.put(header.getKey(), header.getValue().toString()); } } } return EventBuilder.withBody(body.getBytes(charset), headers); } }