| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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.netbeans.lib.v8debug; |
| |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.LinkedHashMap; |
| import java.util.Map; |
| import org.json.simple.JSONArray; |
| import org.json.simple.JSONObject; |
| import static org.netbeans.lib.v8debug.JSONConstants.*; |
| import org.netbeans.lib.v8debug.commands.Backtrace; |
| import org.netbeans.lib.v8debug.commands.ChangeBreakpoint; |
| import org.netbeans.lib.v8debug.commands.ChangeLive; |
| import org.netbeans.lib.v8debug.commands.ClearBreakpoint; |
| import org.netbeans.lib.v8debug.commands.ClearBreakpointGroup; |
| import org.netbeans.lib.v8debug.commands.Continue; |
| import org.netbeans.lib.v8debug.commands.Evaluate; |
| import org.netbeans.lib.v8debug.commands.Flags; |
| import org.netbeans.lib.v8debug.commands.Frame; |
| import org.netbeans.lib.v8debug.commands.GC; |
| import org.netbeans.lib.v8debug.commands.ListBreakpoints; |
| import org.netbeans.lib.v8debug.commands.Lookup; |
| import org.netbeans.lib.v8debug.commands.References; |
| import org.netbeans.lib.v8debug.commands.RestartFrame; |
| import org.netbeans.lib.v8debug.commands.Scope; |
| import org.netbeans.lib.v8debug.commands.Scopes; |
| import org.netbeans.lib.v8debug.commands.Scripts; |
| import org.netbeans.lib.v8debug.commands.SetBreakpoint; |
| import org.netbeans.lib.v8debug.commands.SetExceptionBreak; |
| import org.netbeans.lib.v8debug.commands.SetVariableValue; |
| import org.netbeans.lib.v8debug.commands.Source; |
| import org.netbeans.lib.v8debug.commands.Threads; |
| import org.netbeans.lib.v8debug.commands.V8Flags; |
| import org.netbeans.lib.v8debug.commands.Version; |
| import org.netbeans.lib.v8debug.events.AfterCompileEventBody; |
| import org.netbeans.lib.v8debug.events.BreakEventBody; |
| import org.netbeans.lib.v8debug.events.CompileErrorEventBody; |
| import org.netbeans.lib.v8debug.events.ExceptionEventBody; |
| import org.netbeans.lib.v8debug.events.ScriptCollectedEventBody; |
| import org.netbeans.lib.v8debug.vars.NewValue; |
| import org.netbeans.lib.v8debug.vars.ReferencedValue; |
| import org.netbeans.lib.v8debug.vars.V8Boolean; |
| import org.netbeans.lib.v8debug.vars.V8Function; |
| import org.netbeans.lib.v8debug.vars.V8Generator; |
| import org.netbeans.lib.v8debug.vars.V8Number; |
| import org.netbeans.lib.v8debug.vars.V8Object; |
| import org.netbeans.lib.v8debug.vars.V8ScriptValue; |
| import org.netbeans.lib.v8debug.vars.V8String; |
| import org.netbeans.lib.v8debug.vars.V8Value; |
| |
| /** |
| * Translator of JSON objects into the corresponding Java API classes. |
| * |
| * @author Martin Entlicher |
| */ |
| public class JSONReader { |
| |
| private JSONReader() {} |
| |
| public static V8Type getType(JSONObject obj) throws IllegalArgumentException { |
| String type = (String) obj.get(TYPE); |
| if (type == null) { |
| throw new IllegalArgumentException("No type in "+obj.toJSONString()); |
| } |
| return V8Type.valueOf(type); |
| } |
| |
| public static V8Response getResponse(JSONObject obj) throws IllegalArgumentException { |
| long sequence = (Long) obj.get(SEQ); |
| V8Type type = getType(obj); |
| long requestSequence = (Long) obj.get(SEQ_REQUEST); |
| String commandName = (String) obj.get(COMMAND); |
| V8Command command = (commandName != null) ? V8Command.fromString(commandName) : null; |
| Boolean runningObj = (Boolean) obj.get(RUNNING); |
| boolean running = (runningObj != null) ? runningObj : false; |
| boolean success = (Boolean) obj.get(SUCCESS); |
| V8Body body = null; |
| String errorMessage = null; |
| if (success) { |
| Object bodyObj = obj.get(BODY); |
| if (bodyObj instanceof JSONObject) { |
| body = getBody(command, (JSONObject) bodyObj); |
| } else if (bodyObj instanceof JSONArray) { |
| body = getBody(command, (JSONArray) bodyObj); |
| } else if (body != null) { |
| throw new IllegalArgumentException("Unknown body "+bodyObj+" in "+obj.toJSONString()); |
| } |
| } else { |
| errorMessage = (String) obj.get(MESSAGE); |
| } |
| ReferencedValue[] refs = getRefs((JSONArray) obj.get(REFS)); |
| return new V8Response(sequence, requestSequence, command, body, refs, running, success, errorMessage); |
| } |
| |
| public static V8Event getEvent(JSONObject obj) throws IllegalArgumentException { |
| long sequence = (Long) obj.get(SEQ); |
| String eventName = (String) obj.get(EVENT); |
| V8Event.Kind eventKind; |
| V8Body body = null; |
| if (eventName != null) { |
| eventKind = V8Event.Kind.fromString(eventName); |
| JSONObject bodyObj = (JSONObject) obj.get(BODY); |
| switch (eventKind) { |
| case AfterCompile: |
| V8Script script = getScript((JSONObject) bodyObj.get(EVT_SCRIPT)); |
| body = new AfterCompileEventBody(script); |
| break; |
| case CompileError: |
| script = getScript((JSONObject) bodyObj.get(EVT_SCRIPT)); |
| body = new CompileErrorEventBody(script); |
| break; |
| case ScriptCollected: |
| long scriptId = getLong((JSONObject) bodyObj.get(EVT_SCRIPT), ID); |
| body = new ScriptCollectedEventBody(scriptId); |
| break; |
| case Break: |
| String invocationText = (String) bodyObj.get(EVT_INVOCATION_TEXT); |
| long sourceLine = getLong(bodyObj, EVT_SOURCE_LINE); |
| long sourceColumn = getLong(bodyObj, EVT_SOURCE_COLUMN); |
| String sourceLineText = (String) bodyObj.get(EVT_SOURCE_LINE_TEXT); |
| V8ScriptLocation scriptLocation = getScriptLocation((JSONObject) bodyObj.get(EVT_SCRIPT)); |
| long[] breakpoints = getLongArray((JSONArray) bodyObj.get(EVT_BREAKPOINTS)); |
| body = new BreakEventBody(invocationText, sourceLine, sourceColumn, sourceLineText, scriptLocation, breakpoints); |
| break; |
| case Exception: |
| boolean uncaught = (boolean) bodyObj.get(EVT_UNCAUGHT); |
| V8Value exception = getValue((JSONObject) bodyObj.get(EVT_EXCEPTION)); |
| sourceLine = getLong(bodyObj, EVT_SOURCE_LINE); |
| sourceColumn = getLong(bodyObj, EVT_SOURCE_COLUMN); |
| sourceLineText = (String) bodyObj.get(EVT_SOURCE_LINE_TEXT); |
| script = getScript((JSONObject) bodyObj.get(EVT_SCRIPT)); |
| body = new ExceptionEventBody(uncaught, exception, sourceLine, sourceColumn, sourceLineText, script); |
| break; |
| default: |
| new IllegalArgumentException("Unknown event "+eventName+" in "+obj.toJSONString()).printStackTrace(); |
| } |
| } else { |
| // Handle events like: {"seq":218,"type":"event","success":false,"message":"SyntaxError: Unexpected token C","running":false} |
| eventKind = null; |
| } |
| ReferencedValue[] refs = getRefs((JSONArray) obj.get(REFS)); |
| Boolean running = (Boolean) obj.get(RUNNING); |
| Boolean success = (Boolean) obj.get(SUCCESS); |
| String errorMessage = (String) obj.get(MESSAGE); |
| return new V8Event(sequence, eventKind, body, refs, running, success, errorMessage); |
| } |
| |
| public static V8Request getRequest(JSONObject obj) { |
| long sequence = (Long) obj.get(SEQ); |
| V8Type type = getType(obj); |
| if (V8Type.request != type) { |
| throw new IllegalArgumentException("Expecting request type. Actual type = "+type); |
| } |
| String commandName = (String) obj.get(COMMAND); |
| V8Command command = V8Command.fromString(commandName); |
| JSONObject argsObj = (JSONObject) obj.get(ARGUMENTS); |
| V8Arguments args; |
| if (argsObj != null) { |
| args = getArguments(command, argsObj); |
| } else { |
| args = getSpecialArguments(command, obj); |
| } |
| return new V8Request(sequence, command, args); |
| } |
| |
| private static V8Body getBody(V8Command command, JSONObject obj) { |
| switch (command) { |
| case Listbreakpoints: |
| V8Breakpoint[] breakpoints = getBreakpoints((JSONArray) obj.get(BREAK_POINTS)); |
| boolean breakOnExceptions = getBoolean(obj, BREAK_ON_EXCEPTIONS); |
| boolean breakOnUncaughtExceptions = getBoolean(obj, BREAK_ON_UNCAUGHT_EXCEPTIONS); |
| return new ListBreakpoints.ResponseBody(breakpoints, breakOnExceptions, breakOnUncaughtExceptions); |
| case Setbreakpoint: |
| String type = getString(obj, TYPE); |
| long bpId = getLong(obj, BREAK_POINT); |
| String scriptName = null; |
| if ("scriptName".equals(type)) { |
| scriptName = getString(obj, SCRIPT_NAME); |
| } |
| Long line = getLongOrNull(obj, LINE); |
| Long column = getLongOrNull(obj, COLUMN); |
| V8Breakpoint.ActualLocation[] actualLocations = getActualLocations((JSONArray) obj.get(BREAK_ACTUAL_LOCATIONS)); |
| return new SetBreakpoint.ResponseBody(V8Breakpoint.Type.valueOf(type), bpId, |
| scriptName, line, column, actualLocations); |
| case Setexceptionbreak: |
| String typeName = getString(obj, TYPE); |
| V8ExceptionBreakType extype = V8ExceptionBreakType.valueOf(typeName); |
| if (extype == null) { |
| throw new IllegalArgumentException("Unknown exception breakpoint type: '"+typeName+"'."); |
| } |
| boolean enabled = getBoolean(obj, BREAK_ENABLED); |
| return new SetExceptionBreak.ResponseBody(extype, enabled); |
| case Clearbreakpoint: |
| bpId = getLong(obj, BREAK_POINT); |
| return new ClearBreakpoint.ResponseBody(bpId); |
| case Clearbreakpointgroup: |
| long[] bpIds = getLongArray((JSONArray) obj.get(BREAK_POINTS)); |
| return new ClearBreakpointGroup.ResponseBody(bpIds); |
| case Backtrace: |
| long fromFrame = getLong(obj, FROM_FRAME); |
| long toFrame = getLong(obj, TO_FRAME); |
| long totalFrames = getLong(obj, TOTAL_FRAMES); |
| V8Frame[] frames = getFrames((JSONArray) obj.get(FRAMES)); |
| return new Backtrace.ResponseBody(fromFrame, toFrame, totalFrames, frames); |
| case Frame: |
| V8Frame frame = getFrame(obj); |
| return new Frame.ResponseBody(frame); |
| case Restartframe: |
| JSONObject resultObj = (JSONObject) obj.get(RESULT); |
| if (resultObj == null) { |
| return null; |
| } |
| return new RestartFrame.ResponseBody(resultObj); |
| case Changelive: |
| resultObj = (JSONObject) obj.get(RESULT); |
| if (resultObj == null) { |
| return null; |
| } |
| ChangeLive.ChangeLog changeLog = getChangeLog((JSONArray) obj.get(CHANGE_LOG)); |
| ChangeLive.Result result = getChangeLiveResult(resultObj); |
| Boolean stepInRecommended = getBooleanOrNull(obj, STEP_IN_RECOMMENDED); |
| return new ChangeLive.ResponseBody(changeLog, result, stepInRecommended); |
| case Lookup: |
| Map<Long, V8Value> valuesByHandle = new LinkedHashMap<>(); |
| for (Object element : obj.values()) { |
| V8Value value = getValue((JSONObject) element); |
| valuesByHandle.put(value.getHandle(), value); |
| } |
| return new Lookup.ResponseBody(valuesByHandle); |
| case Evaluate: |
| V8Value value = getValue(obj); |
| return new Evaluate.ResponseBody(value); |
| case SetVariableValue: |
| value = getValue((JSONObject) obj.get(NEW_VALUE)); |
| return new SetVariableValue.ResponseBody(value); |
| case Scope: |
| V8Scope scope = getScope(obj, null); |
| return new Scope.ResponseBody(scope); |
| case Scopes: |
| long fromScope = getLong(obj, FROM_SCOPE); |
| long toScope = getLong(obj, TO_SCOPE); |
| long totalScopes = getLong(obj, TOTAL_SCOPES); |
| V8Scope[] scopes = getScopes((JSONArray) obj.get(SCOPES), null); |
| return new Scopes.ResponseBody(fromScope, toScope, totalScopes, scopes); |
| case Source: |
| String source = getString(obj, SOURCE); |
| long fromLine = getLong(obj, FROM_LINE); |
| long toLine = getLong(obj, TO_LINE); |
| long fromPosition = getLong(obj, FROM_POSITION); |
| long toPosition = getLong(obj, TO_POSITION); |
| long totalLines = getLong(obj, TOTAL_LINES); |
| return new Source.ResponseBody(source, fromLine, toLine, fromPosition, toPosition, totalLines); |
| case Threads: |
| long numThreads = getLong(obj, TOTAL_THREADS); |
| Map<Long, Boolean> threads = getThreads((JSONArray) obj.get(THREADS)); |
| return new Threads.ResponseBody(numThreads, threads); |
| case Gc: |
| long before = getLong(obj, GC_BEFORE); |
| long after = getLong(obj, GC_AFTER); |
| return new GC.ResponseBody(before, after); |
| case Version: |
| String version = getString(obj, BODY_VERSION); |
| return new Version.ResponseBody(version); |
| case Flags: |
| JSONArray flagsArray = (JSONArray) obj.get(FLAGS); |
| Map<String, Boolean> flags = new LinkedHashMap<>(); |
| for (Object fObj : flagsArray) { |
| JSONObject flag = (JSONObject) fObj; |
| flags.put(getString(flag, NAME), getBoolean(flag, VALUE)); |
| } |
| return new Flags.ResponseBody(flags); |
| default: |
| return null; |
| } |
| } |
| |
| private static V8Body getBody(V8Command command, JSONArray array) { |
| switch (command) { |
| case Scripts: |
| int n = array.size(); |
| V8Script[] scripts = new V8Script[n]; |
| for (int i = 0; i < n; i++) { |
| scripts[i] = getScript((JSONObject) array.get(i)); |
| } |
| return new Scripts.ResponseBody(scripts); |
| case References: |
| n = array.size(); |
| V8Value[] refs = new V8Value[n]; |
| for (int i = 0; i < n; i++) { |
| refs[i] = getValue((JSONObject) array.get(i)); |
| } |
| return new References.ResponseBody(refs); |
| default: |
| return null; |
| } |
| } |
| |
| private static V8Arguments getArguments(V8Command command, JSONObject obj) { |
| switch (command) { |
| case Backtrace: |
| return new Backtrace.Arguments( |
| getLongOrNull(obj, FROM_FRAME), getLongOrNull(obj, TO_FRAME), |
| getBooleanOrNull(obj, BOTTOM), getBooleanOrNull(obj, INLINE_REFS)); |
| case Changebreakpoint: |
| return new ChangeBreakpoint.Arguments( |
| getLong(obj, BREAK_POINT), getBooleanOrNull(obj, BREAK_ENABLED), |
| getString(obj, BREAK_CONDITION), getLongOrNull(obj, BREAK_IGNORE_COUNT)); |
| case Changelive: |
| return new ChangeLive.Arguments( |
| getLong(obj, SCRIPT_ID), getString(obj, NEW_SOURCE), |
| getBooleanOrNull(obj, PREVIEW_ONLY)); |
| case Clearbreakpoint: |
| return new ClearBreakpoint.Arguments(getLong(obj, BREAK_POINT)); |
| case Clearbreakpointgroup: |
| return new ClearBreakpointGroup.Arguments(getLong(obj, BREAK_GROUP_ID)); |
| case Continue: |
| String step = getString(obj, ARGS_STEP_ACTION); |
| if (step == null) { |
| return null; |
| } |
| return new Continue.Arguments( |
| V8StepAction.valueOf(step), |
| getLongOrNull(obj, ARGS_STEP_COUNT)); |
| case Evaluate: |
| return new Evaluate.Arguments( |
| getString(obj, EVAL_EXPRESSION), |
| getLongOrNull(obj, FRAME), |
| getBooleanOrNull(obj, EVAL_GLOBAL), |
| getBooleanOrNull(obj, EVAL_DISABLE_BREAK), |
| getAdditionalContext(obj.get(EVAL_ADDITIONAL_CONTEXT))); |
| case Flags: |
| Object fobj = obj.get(FLAGS); |
| if (!(fobj instanceof JSONArray)) { |
| return null; |
| } |
| JSONArray farray = (JSONArray) fobj; |
| Map<String, Boolean> flags = new LinkedHashMap<>(); |
| for (int i = 0; i < farray.size(); i++) { |
| Object felm = farray.get(i); |
| if (felm instanceof JSONObject) { |
| JSONObject fo = (JSONObject) felm; |
| flags.put(getString(fo, NAME), getBooleanOrNull(fo, VALUE)); |
| } |
| } |
| return new Flags.Arguments(flags); |
| case Frame: |
| return new Frame.Arguments(getLongOrNull(obj, NUMBER)); |
| case Gc: |
| return new GC.Arguments(getString(obj, TYPE)); |
| case Lookup: |
| long[] handles = null; |
| Object hObj = obj.get(HANDLES); |
| if (hObj instanceof JSONArray) { |
| handles = getLongArray((JSONArray) hObj); |
| } |
| return new Lookup.Arguments(handles, getBooleanOrNull(obj, INCLUDE_SOURCE)); |
| case References: |
| References.Type rType; |
| String rTypeStr = getString(obj, TYPE); |
| if (rTypeStr != null) { |
| rType = References.Type.valueOf(rTypeStr); |
| } else { |
| rType = null; |
| } |
| return new References.Arguments(rType, getLong(obj, HANDLE)); |
| case Restartframe: |
| return new RestartFrame.Arguments(getLongOrNull(obj, FRAME)); |
| case Scope: |
| return new Scope.Arguments(getLong(obj, NUMBER), getLongOrNull(obj, FRAME_NUMBER)); |
| case Scopes: |
| return new Scopes.Arguments(getLongOrNull(obj, FRAME_NUMBER)); |
| case Scripts: |
| V8Script.Types scrTypes = null; |
| long types = getLong(obj, TYPES); |
| if (types >= 0) { |
| scrTypes = new V8Script.Types((int) types); |
| } |
| long[] ids = null; |
| Object idsObj = obj.get(IDs); |
| if (idsObj instanceof JSONArray) { |
| ids = getLongArray((JSONArray) idsObj); |
| } |
| Boolean includeSource = getBooleanOrNull(obj, INCLUDE_SOURCE); |
| Object filter = obj.get(FILTER); |
| if (filter instanceof String) { |
| return new Scripts.Arguments(scrTypes, ids, includeSource, (String) filter); |
| } else { |
| if (!(filter instanceof Long)) { |
| return null; |
| } |
| return new Scripts.Arguments(scrTypes, ids, includeSource, (Long) filter); |
| } |
| case SetVariableValue: |
| Object nvObj = obj.get(NEW_VALUE); |
| if (!(nvObj instanceof JSONObject)) { |
| return null; |
| } |
| NewValue nv; |
| Long handle = getLongOrNull((JSONObject) nvObj, HANDLE); |
| if (handle != null) { |
| nv = new NewValue(handle); |
| } else { |
| Object typeObj = ((JSONObject) nvObj).get(TYPE); |
| if (!(typeObj instanceof String)) { |
| return null; |
| } |
| V8Value.Type type = V8Value.Type.fromString((String) typeObj); |
| nv = new NewValue(type, STRING_DESCRIPTION); |
| } |
| Object scopeObj = obj.get(SCOPE); |
| if (!(scopeObj instanceof JSONObject)) { |
| return null; |
| } |
| return new SetVariableValue.Arguments( |
| getString(obj, NAME), nv, |
| getLong((JSONObject) scopeObj, NUMBER), |
| getLongOrNull((JSONObject) scopeObj, FRAME_NUMBER)); |
| case Setbreakpoint: |
| Object bpTypeObj = obj.get(TYPE); |
| if (!(bpTypeObj instanceof String)) { |
| return null; |
| } |
| String bpType = (String) bpTypeObj; |
| if ("script".equals(bpType)) { |
| bpType = V8Breakpoint.Type.scriptName.toString(); |
| } |
| return new SetBreakpoint.Arguments( |
| V8Breakpoint.Type.valueOf(bpType), |
| getString(obj, TARGET), |
| getLongOrNull(obj, LINE), getLongOrNull(obj, COLUMN), |
| getBooleanOrNull(obj, BREAK_ENABLED), |
| getString(obj, BREAK_CONDITION), |
| getLongOrNull(obj, BREAK_IGNORE_COUNT), |
| getLongOrNull(obj, BREAK_GROUP_ID)); |
| case Setexceptionbreak: |
| bpTypeObj = obj.get(TYPE); |
| if (!(bpTypeObj instanceof String)) { |
| return null; |
| } |
| bpType = (String) bpTypeObj; |
| return new SetExceptionBreak.Arguments( |
| V8ExceptionBreakType.valueOf(bpType), |
| getBoolean(obj, BREAK_ENABLED)); |
| case Source: |
| return new Source.Arguments( |
| getLongOrNull(obj, FRAME), |
| getLongOrNull(obj, FROM_LINE), |
| getLongOrNull(obj, TO_LINE)); |
| case V8flags: |
| return new V8Flags.Arguments(getString(obj, FLAGS)); |
| default: |
| return null; |
| } |
| } |
| |
| private static V8Arguments getSpecialArguments(V8Command command, JSONObject obj) { |
| // Arguments that are directly on the command request: |
| switch (command) { |
| case Source: |
| return new Source.Arguments( |
| getLongOrNull(obj, FRAME), |
| getLongOrNull(obj, FROM_LINE), |
| getLongOrNull(obj, TO_LINE)); |
| default: |
| return null; |
| } |
| } |
| |
| private static Evaluate.Arguments.Context[] getAdditionalContext(Object obj) { |
| if (!(obj instanceof JSONArray)) { |
| return null; |
| } |
| JSONArray array = (JSONArray) obj; |
| int n = array.size(); |
| Evaluate.Arguments.Context[] context = new Evaluate.Arguments.Context[n]; |
| for (int i = 0; i < n; i++) { |
| context[i] = getContext(array.get(i)); |
| } |
| return context; |
| } |
| |
| private static Evaluate.Arguments.Context getContext(Object obj) { |
| if (!(obj instanceof JSONObject)) { |
| return null; |
| } |
| JSONObject jobj = (JSONObject) obj; |
| return new Evaluate.Arguments.Context(getString(jobj, NAME), |
| getLong(jobj, HANDLE)); |
| } |
| |
| /** |
| * @return the String property value, or <code>null</code> when not defined. |
| */ |
| private static String getString(JSONObject obj, String propertyName) { |
| return (String) obj.get(propertyName); |
| } |
| |
| private static String[] getStringValuesFromArray(JSONArray array, String propertyName) { |
| int l = array.size(); |
| String[] strings = new String[l]; |
| for (int i = 0; i < l; i++) { |
| strings[i] = getString((JSONObject) array.get(i), propertyName); |
| } |
| return strings; |
| } |
| |
| /** |
| * @return the long property value, or <code>-1</code> when not defined. |
| */ |
| private static long getLong(JSONObject obj, String propertyName) { |
| return getLong(obj, propertyName, -1); |
| } |
| |
| /** |
| * @return the long property value, or the defaultValue when not defined. |
| */ |
| private static long getLong(JSONObject obj, String propertyName, long defaultValue) { |
| Object prop = obj.get(propertyName); |
| if (prop == null) { |
| return defaultValue; |
| } |
| if (prop instanceof Long) { |
| return (Long) prop; |
| } else { |
| String str = (String) prop; |
| return Long.parseLong(str); |
| } |
| } |
| |
| private static Long getLongOrNull(JSONObject obj, String propertyName) { |
| Object prop = obj.get(propertyName); |
| if (prop == null) { |
| return null; |
| } |
| return (Long) prop; |
| } |
| |
| private static PropertyLong getLongProperty(JSONObject obj, String propertyName) { |
| Object prop = obj.get(propertyName); |
| if (prop == null) { |
| return new PropertyLong(null); |
| } |
| if (prop instanceof Long) { |
| return new PropertyLong((Long) prop); |
| } else { |
| String str = (String) prop; |
| return new PropertyLong(Long.parseLong(str)); |
| } |
| } |
| |
| /** |
| * @return the boolean property value, or <code>false</code> when not defined. |
| */ |
| private static boolean getBoolean(JSONObject obj, String propertyName) { |
| Object prop = obj.get(propertyName); |
| if (prop == null) { |
| return false; |
| } |
| return (Boolean) prop; |
| } |
| |
| private static Boolean getBooleanOrNull(JSONObject obj, String propertyName) { |
| Object prop = obj.get(propertyName); |
| if (prop == null) { |
| return null; |
| } |
| return (Boolean) prop; |
| } |
| |
| private static V8ScriptLocation getScriptLocation(JSONObject obj) { |
| long id = getLong(obj, ID); |
| String name = getString(obj, NAME); |
| long line = getLong(obj, SCRIPT_LINE_OFFSET); |
| long column = getLong(obj, SCRIPT_COLUMN_OFFSET); |
| long lineCount = getLong(obj, SCRIPT_LINE_COUNT); |
| return new V8ScriptLocation(id, name, line, column, lineCount); |
| } |
| |
| private static V8Script getScript(JSONObject obj) { |
| long handle = getLong(obj, HANDLE); |
| String name = getString(obj, NAME); |
| long id = getLong(obj, ID); |
| long lineOffset = getLong(obj, SCRIPT_LINE_OFFSET); |
| long columnOffset = getLong(obj, SCRIPT_COLUMN_OFFSET); |
| long lineCount = getLong(obj, SCRIPT_LINE_COUNT); |
| Object data = obj.get(DATA); |
| String source = getString(obj, SOURCE); |
| String sourceStart = getString(obj, SOURCE_START); |
| Long sourceLength = getLongOrNull(obj, SOURCE_LENGTH); |
| ReferencedValue context = getReferencedValue(obj, CONTEXT); |
| String text = getString(obj, TEXT); |
| long scriptTypeNum = getLong(obj, SCRIPT_TYPE); |
| V8Script.Type scriptType = (scriptTypeNum >= 0) ? V8Script.Type.valueOf((int) scriptTypeNum) : null; |
| long compilationTypeNum = getLong(obj, COMPILATION_TYPE); |
| V8Script.CompilationType compilationType = (compilationTypeNum >= 0) ? V8Script.CompilationType.valueOf((int) compilationTypeNum) : null; |
| ReferencedValue evalFromScript = getReferencedValue(obj, EVAL_FROM_SCRIPT); |
| V8Script.EvalFromLocation evalFromLocation; |
| if (V8Script.CompilationType.EVAL.equals(compilationType)) { |
| evalFromLocation = new V8Script.EvalFromLocation(getLong(obj, LINE), getLong(obj, COLUMN)); |
| } else { |
| evalFromLocation = null; |
| } |
| return new V8Script(handle, name, id, lineOffset, columnOffset, lineCount, data, source, sourceStart, sourceLength, context, text, scriptType, compilationType, evalFromScript, evalFromLocation); |
| } |
| |
| private static V8Value getValue(JSONObject obj) { |
| return getValue(obj, -1); |
| } |
| |
| private static V8Value getValue(JSONObject obj, long handle) { |
| if (handle < 0) { |
| handle = getLong(obj, HANDLE); |
| } |
| V8Value.Type type = V8Value.Type.fromString(getString(obj, TYPE)); |
| String text = getString(obj, TEXT); |
| switch (type) { |
| case Boolean: |
| return new V8Boolean(handle, getBoolean(obj, VALUE), text); |
| case Number: |
| Object nVal = obj.get(VALUE); |
| if (nVal instanceof Long) { |
| return new V8Number(handle, (Long) nVal, text); |
| } |
| if (nVal instanceof Double) { |
| return new V8Number(handle, (Double) nVal, text); |
| } |
| if (nVal == null) { |
| return new V8Number(handle, -1l, text); |
| } |
| if (INFINITY.equals(nVal)) { |
| return new V8Number(handle, Double.POSITIVE_INFINITY, text); |
| } |
| if (("-"+INFINITY).equals(nVal)) { |
| return new V8Number(handle, Double.NEGATIVE_INFINITY, text); |
| } |
| if (NaN.equals(nVal)) { |
| return new V8Number(handle, Double.NaN, text); |
| } |
| throw new IllegalArgumentException("Unknown variable value type: "+nVal); |
| case String: |
| return new V8String(handle, getString(obj, VALUE), text); |
| case Function: |
| String name = getString(obj, NAME); |
| String inferredName = getString(obj, FUNCTION_INFERRED_NAME); |
| Boolean resolved = getBooleanOrNull(obj, FUNCTION_RESOLVED); |
| String source = getString(obj, SOURCE); |
| PropertyLong scriptRef = getReferenceProperty(obj, SCRIPT); |
| Long scriptId = getLongOrNull(obj, SCRIPTID); |
| PropertyLong position = getLongProperty(obj, POSITION); |
| PropertyLong line = getLongProperty(obj, LINE); |
| PropertyLong column = getLongProperty(obj, COLUMN); |
| PropertyLong constructorFunctionHandle = getReferenceProperty(obj, VALUE_CONSTRUCTOR_FUNCTION); |
| PropertyLong protoObject = getReferenceProperty(obj, VALUE_PROTO_OBJECT); |
| PropertyLong prototypeObject = getReferenceProperty(obj, VALUE_PROTOTYPE_OBJECT); |
| V8Scope[] scopes = null; |
| if (obj.get(SCOPES) instanceof JSONArray) { |
| scopes = getScopes((JSONArray) obj.get(SCOPES), null); |
| } |
| Map<String, V8Object.Property> properties = getProperties((JSONArray) obj.get(VALUE_PROPERTIES), null); |
| return new V8Function(handle, constructorFunctionHandle, |
| protoObject, prototypeObject, |
| name, inferredName, resolved, |
| source, scriptRef, scriptId, |
| position, line, column, scopes, properties, text); |
| case Generator: |
| String className = getString(obj, VALUE_CLASS_NAME); |
| constructorFunctionHandle = getReferenceProperty(obj, VALUE_CONSTRUCTOR_FUNCTION); |
| protoObject = getReferenceProperty(obj, VALUE_PROTO_OBJECT); |
| prototypeObject = getReferenceProperty(obj, VALUE_PROTOTYPE_OBJECT); |
| PropertyLong function = getReferenceProperty(obj, FRAME_FUNC); |
| PropertyLong receiver = getReferenceProperty(obj, FRAME_RECEIVER); |
| properties = getProperties((JSONArray) obj.get(VALUE_PROPERTIES), null); |
| return new V8Generator(handle, className, constructorFunctionHandle, protoObject, prototypeObject, function, receiver, properties, text); |
| case Object: |
| case Error: |
| case Regexp: |
| className = getString(obj, VALUE_CLASS_NAME); |
| constructorFunctionHandle = getReferenceProperty(obj, VALUE_CONSTRUCTOR_FUNCTION); |
| protoObject = getReferenceProperty(obj, VALUE_PROTO_OBJECT); |
| prototypeObject = getReferenceProperty(obj, VALUE_PROTOTYPE_OBJECT); |
| V8Object.Array[] arrayRef; |
| boolean isArray = "Array".equals(className); |
| if (isArray) { |
| arrayRef = new V8Object.Array[] { null }; |
| } else { |
| arrayRef = null; |
| } |
| properties = getProperties((JSONArray) obj.get(VALUE_PROPERTIES), arrayRef); |
| if (isArray && arrayRef[0] == null) { |
| arrayRef[0] = new V8Object.DefaultArray(); |
| } |
| V8Object.Array array = (arrayRef != null) ? arrayRef[0] : null; |
| return new V8Object(handle, type, className, |
| constructorFunctionHandle, |
| protoObject, prototypeObject, |
| properties, array, text); |
| case Frame: |
| // ? TODO |
| return new V8Value(handle, type, text); |
| case Script: |
| V8Script script = getScript(obj); |
| return new V8ScriptValue(handle, script, text); |
| default: // null, undefined |
| return new V8Value(handle, type, text); |
| } |
| } |
| |
| private static long[] getLongArray(JSONArray array) { |
| if (array == null) { |
| return null; |
| } |
| int n = array.size(); |
| long[] iarr = new long[n]; |
| for (int i = 0; i < n; i++) { |
| iarr[i] = (Long) array.get(i); |
| } |
| return iarr; |
| } |
| |
| private static V8Breakpoint[] getBreakpoints(JSONArray array) { |
| int n = array.size(); |
| V8Breakpoint[] breakpoints = new V8Breakpoint[n]; |
| for (int i = 0; i < n; i++) { |
| breakpoints[i] = getBreakpoint((JSONObject) array.get(i)); |
| } |
| return breakpoints; |
| } |
| |
| private static V8Breakpoint getBreakpoint(JSONObject obj) { |
| String typeStr = (String) obj.get(TYPE); |
| /*if ("scriptName".equals(typeStr)) { |
| typeStr = V8Breakpoint.Type.script.name(); |
| }*/ |
| V8Breakpoint.Type type = V8Breakpoint.Type.valueOf(typeStr); |
| PropertyLong scriptId; |
| String scriptName; |
| if (V8Breakpoint.Type.scriptId.equals(type)) { |
| scriptId = new PropertyLong(getLong(obj, SCRIPT_ID)); |
| scriptName = null; |
| } else { |
| scriptId = new PropertyLong(null); |
| scriptName = getString(obj, SCRIPT_NAME); |
| } |
| long number = getLong(obj, NUMBER); |
| PropertyLong line = getLongProperty(obj, LINE); |
| PropertyLong column = getLongProperty(obj, COLUMN); |
| PropertyLong groupId = getLongProperty(obj, BREAK_GROUP_ID); |
| long hitCount = getLong(obj, BREAK_HIT_COUNT, 0); |
| boolean active = getBoolean(obj, BREAK_ACTIVE); |
| Object conditionObject = obj.get(BREAK_CONDITION); |
| String condition; |
| if (conditionObject instanceof String) { |
| condition = (String) conditionObject; |
| } else { |
| condition = null; |
| } |
| long ignoreCount = getLong(obj, BREAK_IGNORE_COUNT, 0); |
| V8Breakpoint.ActualLocation[] actualLocations = getActualLocations((JSONArray) obj.get(BREAK_ACTUAL_LOCATIONS)); |
| return new V8Breakpoint(type, scriptId, scriptName, number, line, column, groupId, hitCount, active, condition, ignoreCount, actualLocations); |
| } |
| |
| private static V8Breakpoint.ActualLocation[] getActualLocations(JSONArray array) { |
| int n = array.size(); |
| V8Breakpoint.ActualLocation[] locations = new V8Breakpoint.ActualLocation[n]; |
| for (int i = 0; i < n; i++) { |
| JSONObject location = (JSONObject) array.get(i); |
| long line = getLong(location, LINE); |
| long column = getLong(location, COLUMN); |
| String scriptName = getString(location, SCRIPT_NAME); |
| if (scriptName != null) { |
| locations[i] = new V8Breakpoint.ActualLocation(line, column, scriptName); |
| } else { |
| long scriptId = getLong(location, SCRIPT_ID); |
| locations[i] = new V8Breakpoint.ActualLocation(line, column, scriptId); |
| } |
| } |
| return locations; |
| } |
| |
| private static V8Frame[] getFrames(JSONArray array) { |
| if (array == null) { |
| return new V8Frame[]{}; |
| } |
| int n = array.size(); |
| V8Frame[] frames = new V8Frame[n]; |
| for (int i = 0; i < n; i++) { |
| frames[i] = getFrame((JSONObject) array.get(i)); |
| } |
| return frames; |
| } |
| |
| private static V8Frame getFrame(JSONObject obj) { |
| Long index = getLongOrNull(obj, INDEX); |
| ReferencedValue receiver = getReferencedValue(obj, FRAME_RECEIVER); |
| ReferencedValue func = getReferencedValue(obj, FRAME_FUNC); |
| long scriptRef = getReference(obj, SCRIPT); |
| boolean constructCall = getBoolean(obj, FRAME_CONSTRUCT_CALL); |
| boolean atReturn = getBoolean(obj, FRAME_AT_RETURN); |
| boolean debuggerFrame = getBoolean(obj, FRAME_DEBUGGER); |
| Map<String, ReferencedValue> arguments = getReferences((JSONArray) obj.get(FRAME_ARGUMENTS)); |
| Map<String, ReferencedValue> locals = getReferences((JSONArray) obj.get(FRAME_LOCALS)); |
| long position = getLong(obj, POSITION); |
| long line = getLong(obj, LINE); |
| long column = getLong(obj, COLUMN); |
| String sourceLineText = getString(obj, EVT_SOURCE_LINE_TEXT); |
| V8Scope[] scopes = getScopes((JSONArray) obj.get(SCOPES), null); |
| String text = getString(obj, TEXT); |
| return new V8Frame(index, receiver, func, scriptRef, constructCall, atReturn, |
| debuggerFrame, arguments, locals, position, line, column, |
| sourceLineText, scopes, text); |
| } |
| |
| private static Map<String, ReferencedValue> getReferences(JSONArray array) { |
| if (array == null) { |
| return null; |
| } |
| Map<String, ReferencedValue> references = new LinkedHashMap<>(); |
| for (Object obj : array) { |
| String name = getString((JSONObject) obj, NAME); |
| ReferencedValue ref = getReferencedValue((JSONObject) obj, VALUE); |
| references.put(name, ref); |
| } |
| return references; |
| } |
| |
| private static Map<String, V8Object.Property> getProperties(JSONArray array, V8Object.Array[] oArrayRef) { |
| if (array == null) { |
| return null; |
| } |
| if (array.isEmpty()) { |
| return Collections.EMPTY_MAP; |
| } |
| Map<String, V8Object.Property> properties = new LinkedHashMap<>(); |
| V8Object.Property.Type[] types = V8Object.Property.Type.values(); |
| V8Object.DefaultArray oArray = null; |
| for (Object obj : array) { |
| JSONObject prop = (JSONObject) obj; |
| Object nameObj = prop.get(NAME); |
| if (nameObj == null) { |
| continue; |
| } |
| //String name = getString(prop, NAME); |
| long ref = getReference(prop); |
| if (oArrayRef != null && nameObj instanceof Long) { |
| // An array |
| if (oArray == null) { |
| oArray = new V8Object.DefaultArray(); |
| } |
| long index = (Long) nameObj; |
| oArray.putReferenceAt(index, ref); |
| } else { |
| String name = nameObj.toString(); |
| long attributes = getLong(prop, ATTRIBUTES, 0); |
| long propertyTypeNum = getLong(prop, PROPERTY_TYPE); |
| V8Object.Property.Type type; |
| if (propertyTypeNum < 0) { |
| type = null; |
| } else if (propertyTypeNum < types.length) { |
| type = types[(int) propertyTypeNum]; |
| } else { |
| throw new IllegalArgumentException("Unknown property type: "+propertyTypeNum); |
| } |
| V8Object.Property property = new V8Object.Property(name, type, (int) attributes, ref); |
| properties.put(name, property); |
| } |
| } |
| if (oArrayRef != null) { |
| oArrayRef[0] = oArray; |
| } |
| return properties; |
| } |
| |
| private static ReferencedValue[] getRefs(JSONArray array) { |
| if (array == null) { |
| return null; |
| } |
| int n = array.size(); |
| ReferencedValue[] refs = new ReferencedValue[n]; |
| for (int i = 0; i < n; i++) { |
| JSONObject obj = (JSONObject) array.get(i); |
| long ref = getReference(obj); |
| V8Value value = getValue(obj, ref); |
| if (value != null) { |
| refs[i] = new ReferencedValue(value.getHandle(), value); |
| } else { |
| refs[i] = new ReferencedValue(ref, value); |
| } |
| } |
| return refs; |
| } |
| |
| private static long getReference(JSONObject obj) { |
| return getLong(obj, REF); |
| } |
| |
| private static Long getReference(JSONObject obj, String propertyName) { |
| JSONObject ref = (JSONObject) obj.get(propertyName); |
| if (ref == null) { |
| return null; |
| } |
| return getReference(ref); |
| } |
| |
| private static PropertyLong getReferenceProperty(JSONObject obj, String propertyName) { |
| JSONObject ref = (JSONObject) obj.get(propertyName); |
| if (ref == null) { |
| return new PropertyLong(null); |
| } |
| return getLongProperty(ref, REF); |
| } |
| |
| private static ReferencedValue getReferencedValue(JSONObject obj, String propertyName) { |
| JSONObject ref = (JSONObject) obj.get(propertyName); |
| if (ref == null) { |
| return null; |
| } |
| long reference = getReference(ref); |
| V8Value value = null; |
| if (getString(ref, TYPE) != null) { |
| value = getValue(ref, reference); |
| } |
| return new ReferencedValue(reference, value); |
| } |
| |
| private static V8Scope[] getScopes(JSONArray array, Long frameIndex) { |
| int n = array.size(); |
| V8Scope[] scopes = new V8Scope[n]; |
| for (int i = 0; i < n; i++) { |
| scopes[i] = getScope((JSONObject) array.get(i), frameIndex); |
| } |
| return scopes; |
| } |
| |
| private static V8Scope getScope(JSONObject scope, Long frameIndex) { |
| V8Scope.Type type = V8Scope.Type.valueOf((int) getLong(scope, TYPE)); |
| long index = getLong(scope, SCOPE_INDEX); |
| PropertyLong scopeFrameIndex = getLongProperty(scope, FRAME_INDEX); |
| if (!scopeFrameIndex.hasValue() && frameIndex != null) { |
| scopeFrameIndex = new PropertyLong(frameIndex); |
| } |
| ReferencedValue referencedValue = getReferencedValue(scope, OBJECT); |
| ReferencedValue<V8Object> referencedObject; |
| if (referencedValue != null) { |
| V8Object object = referencedValue.hasValue() ? (V8Object) referencedValue.getValue() : null; |
| referencedObject = new ReferencedValue<>(referencedValue.getReference(), object); |
| } else { |
| referencedObject = null; |
| } |
| String text = getString(scope, TEXT); |
| return new V8Scope(index, scopeFrameIndex, type, referencedObject, text); |
| } |
| |
| private static Map<Long, Boolean> getThreads(JSONArray array) { |
| Map<Long, Boolean> threads = new LinkedHashMap<>(); |
| for (Object o : array) { |
| JSONObject obj = (JSONObject) o; |
| threads.put(getLong(obj, ID), getBoolean(obj, CURRENT)); |
| } |
| return threads; |
| } |
| |
| private static ChangeLive.Result getChangeLiveResult(JSONObject resultObj) { |
| ChangeLive.Result.ChangeTree changeTree = getChangeTree((JSONObject) resultObj.get(CHANGE_TREE)); |
| ChangeLive.Result.TextualDiff diff = getTextualDiff((JSONObject) resultObj.get(TEXTUAL_DIFF)); |
| boolean updated = getBoolean(resultObj, UPDATED); |
| Boolean stackModified = getBooleanOrNull(resultObj, STACK_MODIFIED); |
| Boolean stackUpdateNeedsStepIn = getBooleanOrNull(resultObj, STACK_UPDATE_NEEDS_STEP_IN); |
| String createdScriptName = getString(resultObj, CREATED_SCRIPT_NAME); |
| return new ChangeLive.Result(changeTree, diff, updated, stackModified, stackUpdateNeedsStepIn, createdScriptName); |
| } |
| |
| private static ChangeLive.Result.ChangeTree getChangeTree(JSONObject obj) { |
| String name = getString(obj, NAME); |
| ChangeLive.Result.ChangeTree.Positions positions = getChangeTreePositions((JSONObject) obj.get(POSITIONS)); |
| ChangeLive.Result.ChangeTree.Positions newPositions = getChangeTreePositions((JSONObject) obj.get(NEW_POSITIONS)); |
| ChangeLive.Result.ChangeTree.FunctionStatus status; |
| String statusStr = getString(obj, STATUS); |
| if (statusStr != null) { |
| status = ChangeLive.Result.ChangeTree.FunctionStatus.fromString(statusStr); |
| } else { |
| status = null; |
| } |
| String statusExplanation = getString(obj, STATUS_EXPLANATION); |
| ChangeLive.Result.ChangeTree[] children = getChangeTreeChildren((JSONArray) obj.get(CHILDREN)); |
| ChangeLive.Result.ChangeTree[] newChildren = getChangeTreeChildren((JSONArray) obj.get(NEW_CHILDREN)); |
| return new ChangeLive.Result.ChangeTree(name, positions, newPositions, status, statusExplanation, children, newChildren); |
| } |
| |
| private static ChangeLive.Result.ChangeTree[] getChangeTreeChildren(JSONArray array) { |
| if (array == null) { |
| return null; |
| } |
| int n = array.size(); |
| ChangeLive.Result.ChangeTree[] ch = new ChangeLive.Result.ChangeTree[n]; |
| for (int i = 0; i < n; i++) { |
| ch[i] = getChangeTree((JSONObject) array.get(i)); |
| } |
| return ch; |
| } |
| |
| private static ChangeLive.Result.TextualDiff getTextualDiff(JSONObject obj) { |
| long oldLen = getLong(obj, OLD_LEN); |
| long newLen = getLong(obj, NEW_LEN); |
| long[] chunks = getLongArray((JSONArray) obj.get(CHUNKS)); |
| return new ChangeLive.Result.TextualDiff(oldLen, newLen, chunks); |
| } |
| |
| private static ChangeLive.Result.ChangeTree.Positions getChangeTreePositions(JSONObject obj) { |
| if (obj == null) { |
| return null; |
| } |
| long startPosition = getLong(obj, START_POSITION); |
| long endPosition = getLong(obj, END_POSITION); |
| return new ChangeLive.Result.ChangeTree.Positions(startPosition, endPosition); |
| } |
| |
| private static ChangeLive.ChangeLog getChangeLog(JSONArray array) { |
| int n = array.size(); |
| if (n == 0) { |
| return null; |
| } |
| ChangeLive.ChangeLog.BreakpointUpdate[] breakpointsUpdate = null; |
| String[] namesLinkedToOldScript = null; |
| String[] droppedFrames = null; |
| ChangeLive.ChangeLog.FunctionPatched functionPatched = null; |
| ChangeLive.ChangeLog.PositionPatched[] patchedPositions = null; |
| for (Object aelem : array) { |
| if (!(aelem instanceof JSONObject)) { |
| continue; |
| } |
| JSONObject obj = (JSONObject) aelem; |
| JSONArray breakpointsUpdateArr = (JSONArray) obj.get(BREAK_POINTS_UPDATE); |
| if (breakpointsUpdateArr != null) { |
| breakpointsUpdate = getChangeLogBreakpointsUpdate(breakpointsUpdateArr); |
| } |
| JSONArray linkedToOldScriptArr = (JSONArray) obj.get(LINKED_TO_OLD_SCRIPT); |
| if (linkedToOldScriptArr != null) { |
| namesLinkedToOldScript = getStringValuesFromArray(linkedToOldScriptArr, NAME); |
| } |
| JSONArray droppedFromStack = (JSONArray) obj.get(DROPPED_FROM_STACK); |
| if (droppedFromStack != null) { |
| droppedFrames = getStringValuesFromArray(droppedFromStack, NAME); |
| } |
| String fp = (String) obj.get(FUNCTION_PATCHED); |
| if (fp != null) { |
| Boolean finf = getBooleanOrNull(obj, FUNCTION_INFO_NOT_FOUND); |
| functionPatched = new ChangeLive.ChangeLog.FunctionPatched(fp, new PropertyBoolean(finf)); |
| } |
| JSONArray positionPatchedArr = (JSONArray) obj.get(POSITION_PATCHED); |
| if (positionPatchedArr != null) { |
| patchedPositions = getPatchedPositions(positionPatchedArr); |
| } |
| } |
| return new ChangeLive.ChangeLog(breakpointsUpdate, namesLinkedToOldScript, |
| droppedFrames, functionPatched, patchedPositions); |
| } |
| |
| private static ChangeLive.ChangeLog.BreakpointUpdate[] getChangeLogBreakpointsUpdate(JSONArray array) { |
| int l = array.size(); |
| ChangeLive.ChangeLog.BreakpointUpdate[] bpus = new ChangeLive.ChangeLog.BreakpointUpdate[l]; |
| for (int i = 0; i < l; i++) { |
| JSONObject bpu = (JSONObject) array.get(i); |
| String typeRaw = getString(bpu, TYPE); |
| ChangeLive.ChangeLog.BreakpointUpdate.Type type = |
| ChangeLive.ChangeLog.BreakpointUpdate.Type.fromString(typeRaw); |
| long id = getLong(bpu, ID); |
| PropertyLong newId = getLongProperty(bpu, NEW_ID); |
| ChangeLive.ChangeLog.BreakpointUpdate.Position oldPositions = null; |
| ChangeLive.ChangeLog.BreakpointUpdate.Position newPositions = null; |
| JSONObject positionsObj = (JSONObject) bpu.get(OLD_POSITIONS); |
| if (positionsObj != null) { |
| oldPositions = getPositions(positionsObj); |
| } |
| positionsObj = (JSONObject) bpu.get(POSITIONS); |
| if (positionsObj == null) { |
| positionsObj = (JSONObject) bpu.get(NEW_POSITIONS); |
| } |
| if (positionsObj != null) { |
| newPositions = getPositions(positionsObj); |
| } |
| bpus[i] = new ChangeLive.ChangeLog.BreakpointUpdate(type, id, newId, |
| oldPositions, newPositions); |
| } |
| return bpus; |
| } |
| |
| private static ChangeLive.ChangeLog.BreakpointUpdate.Position getPositions(JSONObject positionObj) { |
| long position = getLong(positionObj, POSITION); |
| long line = getLong(positionObj, LINE); |
| long column = getLong(positionObj, COLUMN); |
| return new ChangeLive.ChangeLog.BreakpointUpdate.Position(position, line, column); |
| } |
| |
| private static ChangeLive.ChangeLog.PositionPatched[] getPatchedPositions(JSONArray array) { |
| int l = array.size(); |
| ChangeLive.ChangeLog.PositionPatched[] pps = new ChangeLive.ChangeLog.PositionPatched[l]; |
| for (int i = 0; i < l; i++) { |
| JSONObject pp = (JSONObject) array.get(i); |
| String name = getString(pp, NAME); |
| Boolean infoNF = getBooleanOrNull(pp, INFO_NOT_FOUND); |
| pps[i] = new ChangeLive.ChangeLog.PositionPatched(name, new PropertyBoolean(infoNF)); |
| } |
| return pps; |
| } |
| |
| } |