/*
 * Copyright 2012 Splunk, 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 com.splunk.external;

import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.splunk.ResultsReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;

public class ResultsReaderJson extends ResultsReader {

    private JsonReader jsonReader = null;

    /**
     * Class Constructor.
     *
     * Construct a streaming JSON reader for the event stream. One should only
     * attempt to parse a JSON stream with the JSON reader. Using a non-JSON
     * stream will yield unpredictable results.
     *
     * @param inputStream The stream to be parsed.
     * @throws Exception On exception.
     */
    public ResultsReaderJson(InputStream inputStream) throws Exception {
        super(inputStream);
        jsonReader = new JsonReader(new InputStreamReader(inputStream));
        jsonReader.beginArray();
    }

    /** {@inheritDoc} */
    @Override public void close() throws Exception {
        super.close();
        jsonReader.close();
        jsonReader = null;
    }

    /** {@inheritDoc} */
    @Override public HashMap<String, String> getNextEvent() throws Exception {
        HashMap<String, String> returnData = null;
        int level = 0;

        while (jsonReader.hasNext()) {
            if (returnData == null) {
                returnData = new HashMap<String, String>();
            }
            if (jsonReader.peek() == JsonToken.BEGIN_OBJECT) {
                jsonReader.beginObject();
                level++;
            }
            returnData.put(jsonReader.nextName(), jsonReader.nextString());
            if (jsonReader.peek() == JsonToken.END_OBJECT) {
                jsonReader.endObject();
                if (--level == 0)
                    break;
            }
            if (jsonReader.peek() == JsonToken.END_ARRAY) {
                jsonReader.endArray();
                break;
            }
        }
        return returnData;
    }
}

@@ -1857,16 +1857,465 @@
 el = 0;%0A
+        String name = %22%22;%0A%0A        // events are almost flat and names and strings, so no need for a true%0A        // general parser solution. But the Gson parser is a little unintuitive%0A        // here. Nested objects, have their own relative notion of hasNext. This%0A        // means that for every object or array start, hasNext() returns false%0A        // and one must consume the closing (END) object to get back to the%0A        // previous object.
 %0A       
@@ -2579,19 +2579,581 @@
     
+%7D%0A
     
-level++
+        if (jsonReader.peek() == JsonToken.BEGIN_ARRAY) %7B%0A                jsonReader.beginArray();%0A                // The Gson parser is a little unintuitive here. Nested objects,%0A                // have their own relative notion of hasNext.%0A                String data = %22%22;%0A                while (jsonReader.hasNext()) %7B%0A                    JsonToken jsonToken2 = jsonReader.peek();%0A                    if (jsonToken2 == JsonToken.STRING) %7B%0A                        data = data + (data.equals(%22%22) ? %22%22 : %22,%22) +%0A                                jsonReader.nextString()
 ;%0A  
@@ -3166,58 +3166,340 @@
     
+ 
-%7D%0A            returnData.put(jsonReader.nextName()
+       %7D%0A                %7D%0A                jsonReader.endArray();%0A                returnData.put(name, data);%0A            %7D%0A            if (jsonReader.peek() == JsonToken.NAME) %7B%0A                name = jsonReader.nextName();%0A            %7D%0A            if (jsonReader.peek() == JsonToken.STRING) %7B%0A                returnData.put(name
 , js
@@ -3518,24 +3518,38 @@
 tString());%0A
+            %7D%0A
             
@@ -3641,46 +3641,8 @@
 ();%0A
-                if (--level == 0)%0A    
     
@@ -3773,39 +3773,16 @@
 rray();%0A
-                break;%0A
         

Fix JSON reader when using export.