/*
 * Copyright (C) 2009 Google 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.google.gson;

import java.io.EOFException;
import java.io.Reader;
import java.io.StringReader;
import java.util.Iterator;
import java.util.NoSuchElementException;

/**
 * A streaming parser that allows reading of multiple {@link JsonElement}s from the specified reader
 * asynchronously. This class is not thread-safe.
 *
 * @author Inderjeet Singh
 * @author Joel Leitch
 * @since 1.4
 */
public final class JsonStreamParser implements Iterator<JsonElement> {

  private final JsonParserJavacc parser;
  private JsonElement nextElement;

  /**
   * @param json The string containing JSON elements concatenated to each other.
   * @since 1.4
   */
  public JsonStreamParser(String json) {
    this(new StringReader(json));      
  }
  
  /**
   * @param reader The data stream containing JSON elements concatenated to each other.
   * @since 1.4
   */
  public JsonStreamParser(Reader reader) {
    parser = new JsonParserJavacc(reader);      
    nextElement = null;
  }
  
  /**
   * Returns the next available {@link JsonElement} on the reader. Null if none available.
   * 
   * @return the next available {@link JsonElement} on the reader. Null if none available.
   * @throws JsonParseException if the incoming stream is malformed JSON.
   * @since 1.4
   */
  public JsonElement next() throws JsonParseException {
    if (nextElement != null) {
      JsonElement returnValue = nextElement;
      nextElement = null;
      return returnValue;
    }
    try {
      return parser.parse();
    } catch (TokenMgrError e) {
      throw new JsonParseException("Failed parsing JSON source to Json", e);
    } catch (ParseException e) {
      throw new JsonParseException("Failed parsing JSON source to Json", e);
    } catch (StackOverflowError e) {
      throw new JsonParseException("Failed parsing JSON source to Json", e);
    } catch (OutOfMemoryError e) {
      throw new JsonParseException("Failed parsing JSON source to Json", e);
    } catch (JsonParseException e) {
      if (e.getCause() instanceof EOFException) {
        throw new NoSuchElementException();
      } else {
        throw e;
      }
    }
  }

  public boolean hasNext() {
    try {
      nextElement = next();
      return true;
    } catch (NoSuchElementException e) {
      nextElement = null;
      return false;
    }
  }

  public void remove() {
    throw new UnsupportedOperationException();
  }
}

@@ -887,17 +887,27 @@
 onously.
- 
+%0A * %0A * %3Cp%3E
 This cla
@@ -916,24 +916,508 @@
  is 
-not thread-safe.
+thread-compatible. For some more literature on these definitions, refer to%0A * Effective Java.%0A *%0A * %3Cp%3ETo properly use this class across multiple thread, you will need to add some external%0A * synchronization to your classes/thread to get this to work properly.  For example:%0A * %0A * %3Cpre%3E%0A * JsonStreamParser parser = new JsonStreamParser(%22blah blah blah%22);%0A * JsonElement element;%0A * synchronized (someCommonObject) %7B%0A *   if (parser.hasNext()) %7B%0A *     element = parser.next();%0A *   %7D%0A * %7D%0A * %3C/pre%3E
 %0A *%0A
@@ -1597,16 +1597,45 @@
 parser;%0A
+  private final Object lock;%0A
   privat
@@ -2060,22 +2060,41 @@
 reader);
+%0A
     
-  
+lock = new Object();
 %0A    nex
@@ -2463,16 +2463,44 @@
 ption %7B%0A
+    synchronized (lock) %7B%0A  
     if (
@@ -2518,24 +2518,26 @@
  != null) %7B%0A
+  
       JsonEl
@@ -2569,16 +2569,18 @@
 lement;%0A
+  
       ne
@@ -2599,24 +2599,26 @@
 null;%0A      
+  
 return retur
@@ -2625,22 +2625,31 @@
 nValue;%0A
+      %7D%0A
     %7D%0A
+%0A
     try 
@@ -3331,24 +3331,52 @@
 hasNext() %7B%0A
+    synchronized (lock) %7B%0A  
     try %7B%0A  
@@ -3371,32 +3371,34 @@
     try %7B%0A      
+ 
+ 
 nextElement = ne
@@ -3399,24 +3399,26 @@
 t = next();%0A
+  
       return
@@ -3424,24 +3424,26 @@
 n true;%0A    
+  
 %7D catch (NoS
@@ -3469,24 +3469,26 @@
  e) %7B%0A      
+ 
+ 
 nextElement 
@@ -3497,24 +3497,26 @@
 null;%0A      
+  
 return false
@@ -3517,16 +3517,24 @@
  false;%0A
+      %7D%0A
     %7D%0A  

Add some synchronization to the JsonStreamParser to ensure that the "next" method behaves according to the API.