[ee4j_8] fix for regression #104 (#127) (#128)

Signed-off-by: Lukas Jungmann <lukas.jungmann@oracle.com>
diff --git a/impl/src/main/java/org/glassfish/json/JsonParserImpl.java b/impl/src/main/java/org/glassfish/json/JsonParserImpl.java
index 1857a92..899cfe0 100644
--- a/impl/src/main/java/org/glassfish/json/JsonParserImpl.java
+++ b/impl/src/main/java/org/glassfish/json/JsonParserImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2017 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v. 2.0, which is available at
@@ -282,6 +282,7 @@
         if (currentEvent == Event.START_ARRAY) {
             currentContext.skip();
             currentContext = stack.pop();
+            currentEvent = Event.END_ARRAY;
         }
     }
 
@@ -290,6 +291,7 @@
         if (currentEvent == Event.START_OBJECT) {
             currentContext.skip();
             currentContext = stack.pop();
+            currentEvent = Event.END_OBJECT;
         }
     }
 
@@ -328,7 +330,18 @@
 
     @Override
     public boolean hasNext() {
-        return tokenizer.hasNextToken();
+        if (stack.isEmpty() && (currentEvent != null && currentEvent.compareTo(Event.KEY_NAME) > 0)) {
+            JsonToken token = tokenizer.nextToken();
+            if (token != JsonToken.EOF) {
+                throw new JsonParsingException(JsonMessages.PARSER_EXPECTED_EOF(token),
+                        getLastCharLocation());
+            }
+            return false;
+        } else if (!stack.isEmpty() && !tokenizer.hasNextToken()) {
+            currentEvent = currentContext.getNextEvent();
+            return false;
+        }
+        return true;
     }
 
     @Override
@@ -427,7 +440,16 @@
         public Event getNextEvent() {
             // Handle 1. }   2. name:value   3. ,name:value
             JsonToken token = tokenizer.nextToken();
-            if (currentEvent == Event.KEY_NAME) {
+            if (token == JsonToken.EOF) {
+                switch (currentEvent) {
+                    case START_OBJECT:
+                        throw parsingException(token, "[STRING, CURLYCLOSE]");
+                    case KEY_NAME:
+                        throw parsingException(token, "[COLON]");
+                    default:
+                        throw parsingException(token, "[COMMA, CURLYCLOSE]");
+                }
+            } else if (currentEvent == Event.KEY_NAME) {
                 // Handle 1. :value
                 if (token != JsonToken.COLON) {
                     throw parsingException(token, "[COLON]");
@@ -492,6 +514,14 @@
         @Override
         public Event getNextEvent() {
             JsonToken token = tokenizer.nextToken();
+            if (token == JsonToken.EOF) {
+                switch (currentEvent) {
+                    case START_ARRAY:
+                        throw parsingException(token, "[CURLYOPEN, SQUAREOPEN, STRING, NUMBER, TRUE, FALSE, NULL]");
+                    default:
+                        throw parsingException(token, "[COMMA, CURLYCLOSE]");
+                }
+            }
             if (token == JsonToken.SQUARECLOSE) {
                 currentContext = stack.pop();
                 return Event.END_ARRAY;
diff --git a/tests/src/test/java/org/glassfish/json/tests/JsonParserSkipTest.java b/tests/src/test/java/org/glassfish/json/tests/JsonParserSkipTest.java
index a44e214..c77d87b 100644
--- a/tests/src/test/java/org/glassfish/json/tests/JsonParserSkipTest.java
+++ b/tests/src/test/java/org/glassfish/json/tests/JsonParserSkipTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/src/test/java/org/glassfish/json/tests/JsonParserTest.java b/tests/src/test/java/org/glassfish/json/tests/JsonParserTest.java
index 0f6ca53..83eb517 100644
--- a/tests/src/test/java/org/glassfish/json/tests/JsonParserTest.java
+++ b/tests/src/test/java/org/glassfish/json/tests/JsonParserTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2017 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v. 2.0, which is available at
@@ -36,6 +36,7 @@
 import java.util.NoSuchElementException;
 import java.util.Random;
 import java.util.Scanner;
+import javax.json.stream.JsonParsingException;
 
 import org.glassfish.json.api.BufferPool;
 
@@ -763,4 +764,64 @@
         }
     }
 
+    public void testExceptionsFromHasNext() {
+        checkExceptionFromHasNext("{");
+        checkExceptionFromHasNext("{\"key\"");
+        checkExceptionFromHasNext("{\"name\" : \"prop\"");
+        checkExceptionFromHasNext("{\"name\" : 3");
+        checkExceptionFromHasNext("{\"name\" : true");
+        checkExceptionFromHasNext("{\"name\" : null");
+        checkExceptionFromHasNext("{\"name\" : {\"$eq\":\"cdc\"}");
+        checkExceptionFromHasNext("{\"name\" : [{\"$eq\":\"cdc\"}]");
+        checkExceptionFromHasNext("[");
+        checkExceptionFromHasNext("{\"name\" : [{\"key\" : [[{\"a\" : 1}]");
+        checkExceptionFromHasNext("{\"unique\":true,\"name\":\"jUnitTestIndexNeg005\", \"fields\":[{\"order\":-1,\"path\":\"city.zip\"}");
+    }
+
+    public void testEOFFromHasNext() {
+        checkExceptionFromHasNext("{ \"d\" : 1 } 2 3 4");
+        checkExceptionFromHasNext("[ {\"d\" : 1 }] 2 3 4");
+        checkExceptionFromHasNext("1 2 3 4");
+        checkExceptionFromHasNext("null 2 3 4");
+    }
+
+    public void testExceptionsFromNext() {
+        checkExceptionFromNext("{\"name\" : fal");
+        checkExceptionFromNext("{\"name\" : nu");
+        checkExceptionFromNext("{\"name\" : \"pro");
+        checkExceptionFromNext("{\"key\":");
+        checkExceptionFromNext("fal");
+    }
+
+    private void checkExceptionFromHasNext(String input) {
+        try (JsonParser parser = Json.createParser(new StringReader(input))) {
+            try {
+                while (parser.hasNext()) {
+                    try {
+                        parser.next();
+                    } catch (Throwable t1) {
+                        fail("Exception should occur from hasNext() for '" + input + "'");
+                    }
+                }
+            } catch (JsonParsingException t) {
+                //this is OK
+                return;
+            }
+        }
+        fail();
+    }
+
+    private void checkExceptionFromNext(String input) {
+        try (JsonParser parser = Json.createParser(new StringReader(input))) {
+            while (parser.hasNext()) {
+                try {
+                    parser.next();
+                } catch (JsonParsingException t) {
+                    //this is OK
+                    return;
+                }
+            }
+        }
+        fail();
+    }
 }