From 7a2a3149281ccc7f627564037ea73d028dd17094 Mon Sep 17 00:00:00 2001 From: LAX1DUDE Date: Wed, 30 Mar 2022 17:00:53 -0700 Subject: [PATCH] added MOTD and javascript query system --- .../main/java/net/md_5/bungee/api/MOTD.java | 24 + .../net/md_5/bungee/api/QueryConnection.java | 66 + .../java/net/md_5/bungee/api/ServerIcon.java | 34 + .../md_5/bungee/api/config/ListenerInfo.java | 26 + .../bungee/api/event/WebsocketMOTDEvent.java | 15 + .../bungee/api/event/WebsocketQueryEvent.java | 33 + .../eaglercraft/MOTDConnectionImpl.java | 153 + .../eaglercraft/QueryConnectionImpl.java | 119 + .../bungee/eaglercraft/WebSocketListener.java | 43 + .../adapter/EaglerAdapterImpl2.java | 121 +- .../net/lax1dude/eaglercraft/ServerQuery.java | 105 + .../net/minecraft/src/GuiMultiplayer.java | 157 +- src/main/java/net/minecraft/src/GuiSlot.java | 19 +- .../java/net/minecraft/src/GuiSlotServer.java | 74 +- .../java/net/minecraft/src/ServerData.java | 95 +- .../java/net/minecraft/src/ServerList.java | 114 +- src/main/java/org/json/CDL.java | 287 ++ src/main/java/org/json/Cookie.java | 224 ++ src/main/java/org/json/CookieList.java | 86 + src/main/java/org/json/HTTP.java | 162 + src/main/java/org/json/HTTPTokener.java | 77 + src/main/java/org/json/JSONArray.java | 1716 +++++++++++ src/main/java/org/json/JSONException.java | 69 + src/main/java/org/json/JSONML.java | 542 ++++ src/main/java/org/json/JSONObject.java | 2732 +++++++++++++++++ src/main/java/org/json/JSONPointer.java | 295 ++ .../java/org/json/JSONPointerException.java | 45 + .../java/org/json/JSONPropertyIgnore.java | 43 + src/main/java/org/json/JSONPropertyName.java | 47 + src/main/java/org/json/JSONString.java | 43 + src/main/java/org/json/JSONStringer.java | 79 + src/main/java/org/json/JSONTokener.java | 545 ++++ src/main/java/org/json/JSONWriter.java | 414 +++ src/main/java/org/json/Property.java | 75 + src/main/java/org/json/XML.java | 884 ++++++ .../java/org/json/XMLParserConfiguration.java | 320 ++ src/main/java/org/json/XMLTokener.java | 416 +++ .../java/org/json/XMLXsiTypeConverter.java | 66 + .../adapter/EaglerAdapterImpl2.java | 112 + .../bukkit_command/craftbukkit-1.5.2-R1.0.jar | Bin 12900598 -> 12897333 bytes stable-download/java/bungee_command/bans.txt | 51 + .../java/bungee_command/bungee-dist.jar | Bin 12390078 -> 12514637 bytes .../java/bungee_command/config.yml | 27 +- .../java/bungee_command/server-icon.png | Bin 0 -> 8854 bytes 44 files changed, 10369 insertions(+), 186 deletions(-) create mode 100644 eaglercraftbungee/src/main/java/net/md_5/bungee/api/MOTD.java create mode 100644 eaglercraftbungee/src/main/java/net/md_5/bungee/api/QueryConnection.java create mode 100644 eaglercraftbungee/src/main/java/net/md_5/bungee/api/ServerIcon.java create mode 100644 eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/WebsocketMOTDEvent.java create mode 100644 eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/WebsocketQueryEvent.java create mode 100644 eaglercraftbungee/src/main/java/net/md_5/bungee/eaglercraft/MOTDConnectionImpl.java create mode 100644 eaglercraftbungee/src/main/java/net/md_5/bungee/eaglercraft/QueryConnectionImpl.java create mode 100644 src/main/java/net/lax1dude/eaglercraft/ServerQuery.java create mode 100644 src/main/java/org/json/CDL.java create mode 100644 src/main/java/org/json/Cookie.java create mode 100644 src/main/java/org/json/CookieList.java create mode 100644 src/main/java/org/json/HTTP.java create mode 100644 src/main/java/org/json/HTTPTokener.java create mode 100644 src/main/java/org/json/JSONArray.java create mode 100644 src/main/java/org/json/JSONException.java create mode 100644 src/main/java/org/json/JSONML.java create mode 100644 src/main/java/org/json/JSONObject.java create mode 100644 src/main/java/org/json/JSONPointer.java create mode 100644 src/main/java/org/json/JSONPointerException.java create mode 100644 src/main/java/org/json/JSONPropertyIgnore.java create mode 100644 src/main/java/org/json/JSONPropertyName.java create mode 100644 src/main/java/org/json/JSONString.java create mode 100644 src/main/java/org/json/JSONStringer.java create mode 100644 src/main/java/org/json/JSONTokener.java create mode 100644 src/main/java/org/json/JSONWriter.java create mode 100644 src/main/java/org/json/Property.java create mode 100644 src/main/java/org/json/XML.java create mode 100644 src/main/java/org/json/XMLParserConfiguration.java create mode 100644 src/main/java/org/json/XMLTokener.java create mode 100644 src/main/java/org/json/XMLXsiTypeConverter.java create mode 100644 stable-download/java/bungee_command/bans.txt create mode 100644 stable-download/java/bungee_command/server-icon.png diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/MOTD.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/MOTD.java new file mode 100644 index 0000000..2ba072e --- /dev/null +++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/MOTD.java @@ -0,0 +1,24 @@ +package net.md_5.bungee.api; + +import java.util.List; + +public interface MOTD extends QueryConnection { + + public void sendToUser(); + + public String getLine1(); + public String getLine2(); + public List getPlayerList(); + public int[] getBitmap(); + public int getOnlinePlayers(); + public int getMaxPlayers(); + + public void setLine1(String p); + public void setLine2(String p); + public void setPlayerList(List p); + public void setPlayerList(String... p); + public void setBitmap(int[] p); + public void setOnlinePlayers(int i); + public void setMaxPlayers(int i); + +} diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/QueryConnection.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/QueryConnection.java new file mode 100644 index 0000000..35b7127 --- /dev/null +++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/QueryConnection.java @@ -0,0 +1,66 @@ +package net.md_5.bungee.api; + +import java.net.InetAddress; + +import org.json.JSONObject; + +import net.md_5.bungee.BungeeCord; +import net.md_5.bungee.api.config.ListenerInfo; +import net.md_5.bungee.eaglercraft.EaglercraftBungee; + +public interface QueryConnection { + + public InetAddress getRemoteAddress(); + public ListenerInfo getListener(); + + public String getAccept(); + public void setReturnType(String type); + public String getReturnType(); + + public int availableRequests(); + + public default JSONObject readRequestData() { + String s = readRequestString(); + return s == null ? null : new JSONObject(s); + } + + public String readRequestString(); + public long getConnectionTimestamp(); + + public default long getConnectionAge() { + return System.currentTimeMillis() - getConnectionTimestamp(); + } + + public default void writeResponse(JSONObject msg) { + JSONObject toSend = new JSONObject(); + toSend.put("type", getReturnType()); + toSend.put("name", BungeeCord.getInstance().config.getServerName()); + toSend.put("brand", EaglercraftBungee.brand); + toSend.put("vers", EaglercraftBungee.version); + toSend.put("cracked", EaglercraftBungee.cracked); + toSend.put("time", System.currentTimeMillis()); + toSend.put("data", msg); + writeResponseRaw(toSend.toString()); + } + + public default void writeResponse(String msg) { + JSONObject toSend = new JSONObject(); + toSend.put("type", getReturnType()); + toSend.put("name", BungeeCord.getInstance().config.getServerName()); + toSend.put("brand", EaglercraftBungee.brand); + toSend.put("vers", EaglercraftBungee.version); + toSend.put("cracked", EaglercraftBungee.cracked); + toSend.put("time", System.currentTimeMillis()); + toSend.put("data", msg); + writeResponseRaw(toSend.toString()); + } + + public void writeResponseRaw(String msg); + public void writeResponseBinary(byte[] blob); + + public void keepAlive(boolean yes); + public boolean shouldKeepAlive(); + public boolean isClosed(); + public void close(); + +} diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/ServerIcon.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/ServerIcon.java new file mode 100644 index 0000000..81bf55a --- /dev/null +++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/ServerIcon.java @@ -0,0 +1,34 @@ +package net.md_5.bungee.api; + +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.InputStream; + +import javax.imageio.ImageIO; + +public class ServerIcon { + + public static int[] createServerIcon(BufferedImage awtIcon) { + if(awtIcon.getWidth() != 64 || awtIcon.getHeight() != 64) { + throw new IllegalArgumentException("Image must be 64x64 (was " + awtIcon.getWidth() + "x" + awtIcon.getHeight() + ")"); + } + return awtIcon.getRGB(0, 0, 64, 64, new int[4096], 0, 64); + } + + public static int[] createServerIcon(InputStream f) { + try { + return createServerIcon(ImageIO.read(f)); + }catch(Throwable t) { + return null; + } + } + + public static int[] createServerIcon(File f) { + try { + return createServerIcon(ImageIO.read(f)); + }catch(Throwable t) { + return null; + } + } + +} diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/config/ListenerInfo.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/config/ListenerInfo.java index 9efb56c..0143722 100644 --- a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/config/ListenerInfo.java +++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/config/ListenerInfo.java @@ -252,4 +252,30 @@ public class ListenerInfo { return forwardIp; } + public String getServerIcon() { + return serverIcon; + } + + public int[] getServerIconCache() { + if(!serverIconLoaded) { + if(serverIcon != null) { + int[] img = ServerIcon.createServerIcon(new File(serverIcon)); + if(img != null) { + System.arraycopy(img, 0, serverIconCache, 0, img.length); + serverIconSet = true; + }else { + serverIconSet = false; + } + }else { + serverIconSet = false; + } + serverIconLoaded = true; + } + return serverIconCache; + } + + public boolean isIconSet() { + getServerIconCache(); + return serverIconSet; + } } diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/WebsocketMOTDEvent.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/WebsocketMOTDEvent.java new file mode 100644 index 0000000..3c665f0 --- /dev/null +++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/WebsocketMOTDEvent.java @@ -0,0 +1,15 @@ +package net.md_5.bungee.api.event; + +import net.md_5.bungee.api.MOTD; + +public class WebsocketMOTDEvent extends WebsocketQueryEvent { + + public WebsocketMOTDEvent(MOTD connection) { + super(connection); + } + + public MOTD getMOTD() { + return (MOTD)connection; + } + +} diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/WebsocketQueryEvent.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/WebsocketQueryEvent.java new file mode 100644 index 0000000..52ba23b --- /dev/null +++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/WebsocketQueryEvent.java @@ -0,0 +1,33 @@ +package net.md_5.bungee.api.event; + +import java.net.InetAddress; + +import net.md_5.bungee.api.QueryConnection; +import net.md_5.bungee.api.config.ListenerInfo; +import net.md_5.bungee.api.plugin.Event; + +public class WebsocketQueryEvent extends Event { + + protected final QueryConnection connection; + + public WebsocketQueryEvent(QueryConnection connection) { + this.connection = connection; + } + + public InetAddress getRemoteAddress() { + return connection.getRemoteAddress(); + } + + public ListenerInfo getListener() { + return connection.getListener(); + } + + public String getAccept() { + return connection.getAccept(); + } + + public QueryConnection getQuery() { + return connection; + } + +} diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/eaglercraft/MOTDConnectionImpl.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/eaglercraft/MOTDConnectionImpl.java new file mode 100644 index 0000000..b95699e --- /dev/null +++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/eaglercraft/MOTDConnectionImpl.java @@ -0,0 +1,153 @@ +package net.md_5.bungee.eaglercraft; + +import java.net.InetAddress; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.java_websocket.WebSocket; +import org.json.JSONArray; +import org.json.JSONObject; + +import net.md_5.bungee.BungeeCord; +import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.api.MOTD; +import net.md_5.bungee.api.config.ListenerInfo; +import net.md_5.bungee.api.connection.ProxiedPlayer; + +public class MOTDConnectionImpl extends QueryConnectionImpl implements MOTD { + + private String line1; + private String line2; + private List players; + private int[] bitmap; + private int onlinePlayers; + private int maxPlayers; + private boolean hasIcon; + private boolean iconDirty; + + public MOTDConnectionImpl(ListenerInfo listener, InetAddress addr, WebSocket socket) { + super(listener, addr, socket, "motd"); + String[] lns = listener.getMotd().split("\n"); + if(lns.length >= 1) { + line1 = lns[0].trim(); + } + if(lns.length >= 2) { + line2 = lns[1].trim(); + } + maxPlayers = listener.getMaxPlayers(); + onlinePlayers = BungeeCord.getInstance().getOnlineCount(); + players = new ArrayList(); + for(ProxiedPlayer pp : BungeeCord.getInstance().getPlayers()) { + players.add(pp.getDisplayName()); + if(players.size() >= 9) { + players.add("" + ChatColor.GRAY + ChatColor.ITALIC + "(" + (onlinePlayers - players.size()) + " more)"); + break; + } + } + bitmap = new int[4096]; + iconDirty = hasIcon = listener.isIconSet(); + if(hasIcon) { + System.arraycopy(listener.getServerIconCache(), 0, bitmap, 0, 4096); + } + setReturnType("motd"); + } + + @Override + public String getLine1() { + return line1; + } + + @Override + public String getLine2() { + return line2; + } + + @Override + public List getPlayerList() { + return players; + } + + @Override + public int[] getBitmap() { + return bitmap; + } + + @Override + public int getOnlinePlayers() { + return onlinePlayers; + } + + @Override + public int getMaxPlayers() { + return maxPlayers; + } + + @Override + public void setLine1(String p) { + line1 = p; + } + + @Override + public void setLine2(String p) { + line2 = p; + } + + @Override + public void setPlayerList(List p) { + players = p; + } + + @Override + public void setPlayerList(String... p) { + players = Arrays.asList(p); + } + + @Override + public void setBitmap(int[] p) { + iconDirty = hasIcon = true; + bitmap = p; + } + + @Override + public void setOnlinePlayers(int i) { + onlinePlayers = i; + } + + @Override + public void setMaxPlayers(int i) { + maxPlayers = i; + } + + @Override + public void sendToUser() { + if(!isClosed()) { + JSONObject obj = new JSONObject(); + JSONArray motd = new JSONArray(); + if(line1 != null && line1.length() > 0) motd.put(line1); + if(line2 != null && line2.length() > 0) motd.put(line2); + obj.put("motd", motd); + obj.put("icon", hasIcon); + obj.put("online", onlinePlayers); + obj.put("max", maxPlayers); + JSONArray playerz = new JSONArray(); + for(String s : players) { + playerz.put(s); + } + obj.put("players", playerz); + writeResponse(obj); + if(hasIcon && iconDirty && bitmap != null) { + byte[] iconPixels = new byte[16384]; + for(int i = 0; i < 4096; ++i) { + iconPixels[i * 4] = (byte)((bitmap[i] >> 16) & 0xFF); + iconPixels[i * 4 + 1] = (byte)((bitmap[i] >> 8) & 0xFF); + iconPixels[i * 4 + 2] = (byte)(bitmap[i] & 0xFF); + iconPixels[i * 4 + 3] = (byte)((bitmap[i] >> 24) & 0xFF); + } + writeResponseBinary(iconPixels); + iconDirty = false; + } + } + } + +} diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/eaglercraft/QueryConnectionImpl.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/eaglercraft/QueryConnectionImpl.java new file mode 100644 index 0000000..a9d5955 --- /dev/null +++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/eaglercraft/QueryConnectionImpl.java @@ -0,0 +1,119 @@ +package net.md_5.bungee.eaglercraft; + +import java.net.InetAddress; +import java.util.LinkedList; +import java.util.List; + +import org.java_websocket.WebSocket; + +import net.md_5.bungee.api.QueryConnection; +import net.md_5.bungee.api.config.ListenerInfo; + +public class QueryConnectionImpl implements QueryConnection { + + protected ListenerInfo listener; + protected InetAddress addr; + protected WebSocket socket; + protected String accept; + protected String responseType; + protected List packetBuffer = new LinkedList(); + protected long creationTime; + protected boolean keepAlive = false; + + public QueryConnectionImpl(ListenerInfo listener, InetAddress addr, WebSocket socket, String accept) { + this.listener = listener; + this.addr = addr; + this.socket = socket; + this.accept = accept.toLowerCase(); + this.responseType = "unknown"; + this.creationTime = System.currentTimeMillis(); + } + + public void postMessage(String m) { + synchronized(packetBuffer) { + packetBuffer.add(m); + } + } + + @Override + public InetAddress getRemoteAddress() { + return addr; + } + + @Override + public ListenerInfo getListener() { + return listener; + } + + @Override + public String getAccept() { + return accept; + } + + @Override + public int availableRequests() { + synchronized(packetBuffer) { + return packetBuffer.size(); + } + } + + @Override + public String readRequestString() { + synchronized(packetBuffer) { + if(packetBuffer.size() > 0) { + return packetBuffer.remove(0); + }else { + return null; + } + } + } + + @Override + public long getConnectionTimestamp() { + return creationTime; + } + + @Override + public void writeResponseRaw(String msg) { + socket.send(msg); + } + + @Override + public void writeResponseBinary(byte[] blob) { + socket.send(blob); + } + + @Override + public void keepAlive(boolean yes) { + keepAlive = yes; + } + + @Override + public boolean shouldKeepAlive() { + return keepAlive; + } + + @Override + public boolean isClosed() { + return socket.isClosing() || socket.isClosed(); + } + + @Override + public void close() { + socket.close(); + } + + @Override + public void setReturnType(String type) { + if(!"unknown".equals(responseType) && !type.equalsIgnoreCase(responseType)) { + throw new IllegalStateException("Tried to change query return type to '" + type + "' when it was already set to '" + responseType + "'"); + } + responseType = type; + } + + @Override + public String getReturnType() { + return responseType; + } + +} diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/eaglercraft/WebSocketListener.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/eaglercraft/WebSocketListener.java index c23ce41..fcfdd57 100644 --- a/eaglercraftbungee/src/main/java/net/md_5/bungee/eaglercraft/WebSocketListener.java +++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/eaglercraft/WebSocketListener.java @@ -10,8 +10,11 @@ import org.java_websocket.handshake.ClientHandshake; import org.java_websocket.server.WebSocketServer; import net.md_5.bungee.BungeeCord; +import net.md_5.bungee.api.MOTD; import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.config.ListenerInfo; +import net.md_5.bungee.api.event.WebsocketMOTDEvent; +import net.md_5.bungee.api.event.WebsocketQueryEvent; public class WebSocketListener extends WebSocketServer { @@ -56,6 +59,46 @@ public class WebSocketListener extends WebSocketServer { @Override public void onMessage(WebSocket arg0, String arg1) { + Object o = arg0.getAttachment(); + if(o != null) { + if(o instanceof PendingSocket) { + InetAddress realAddr = ((PendingSocket)o).realAddress; + arg1 = arg1.trim().toLowerCase(); + if(arg1.startsWith("accept:")) { + arg1 = arg1.substring(7).trim(); + QueryConnectionImpl con; + WebsocketQueryEvent evt; + if(arg1.equals("motd")) { + System.out.println("requested motd - " + realAddr); + con = new MOTDConnectionImpl(info, realAddr, arg0); + evt = new WebsocketMOTDEvent((MOTD)con); + }else { + System.out.println("connection is query - accepts '" + arg1 + "' - " + realAddr); + con = new QueryConnectionImpl(info, realAddr, arg0, arg1); + evt = new WebsocketQueryEvent(con); + } + BungeeCord.getInstance().getPluginManager().callEvent(evt); + if(con instanceof MOTDConnectionImpl) { + ((MOTDConnectionImpl)con).sendToUser(); + } + if(!con.shouldKeepAlive() && !con.isClosed()) { + con.close(); + }else { + arg0.setAttachment(con); + } + }else { + System.err.println("unknown accept type - " + arg0.getRemoteSocketAddress()); + arg0.close(); + } + return; + }else if(o instanceof QueryConnectionImpl) { + ((QueryConnectionImpl)o).postMessage(arg1); + }else { + System.out.println("error: recieved text data on binary websocket - " + arg0.getRemoteSocketAddress()); + } + }else { + arg0.close(); + } } @Override diff --git a/src/lwjgl/java/net/lax1dude/eaglercraft/adapter/EaglerAdapterImpl2.java b/src/lwjgl/java/net/lax1dude/eaglercraft/adapter/EaglerAdapterImpl2.java index 94cf971..098ac6f 100644 --- a/src/lwjgl/java/net/lax1dude/eaglercraft/adapter/EaglerAdapterImpl2.java +++ b/src/lwjgl/java/net/lax1dude/eaglercraft/adapter/EaglerAdapterImpl2.java @@ -33,6 +33,7 @@ import javax.swing.filechooser.FileFilter; import org.java_websocket.client.WebSocketClient; import org.java_websocket.handshake.ServerHandshake; +import org.json.JSONObject; import org.lwjgl.LWJGLException; import org.lwjgl.Sys; import org.lwjgl.input.Keyboard; @@ -57,6 +58,7 @@ import org.lwjgl.util.glu.GLU; import de.cuina.fireandfuel.CodecJLayerMP3; import net.lax1dude.eaglercraft.AssetRepository; import net.lax1dude.eaglercraft.EarlyLoadScreen; +import net.lax1dude.eaglercraft.ServerQuery; import net.lax1dude.eaglercraft.adapter.lwjgl.GameWindowListener; import net.minecraft.src.MathHelper; import paulscode.sound.SoundSystem; @@ -889,17 +891,18 @@ public class EaglerAdapterImpl2 { } public static final boolean startConnection(String uri) { - if(clientSocket == null) { - try { - clientSocket = new EaglerSocketClient(new URI(uri)); - return true; - }catch(InterruptedException e) { - clientSocket = null; - } catch (URISyntaxException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } + if(clientSocket != null) { + clientSocket.close(); + } + try { + clientSocket = new EaglerSocketClient(new URI(uri)); + return true; + }catch(InterruptedException e) { + clientSocket = null; + } catch (URISyntaxException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); } return false; } @@ -1174,5 +1177,101 @@ public class EaglerAdapterImpl2 { appendbuffer.flip(); return appendbuffer; } + private static class ServerQueryImpl extends WebSocketClient implements ServerQuery { + + private final LinkedList queryResponses = new LinkedList(); + private final LinkedList queryResponsesBytes = new LinkedList(); + private final String type; + private boolean open; + private ServerQueryImpl(String type, URI serverUri) { + super(serverUri); + this.type = type; + this.open = true; + this.setConnectionLostTimeout(5); + this.setTcpNoDelay(true); + this.connect(); + } + + @Override + public int responseAvailable() { + synchronized(queryResponses) { + return queryResponses.size(); + } + } + + @Override + public int responseBinaryAvailable() { + synchronized(queryResponsesBytes) { + return queryResponsesBytes.size(); + } + } + + @Override + public QueryResponse getResponse() { + synchronized(queryResponses) { + return queryResponses.size() > 0 ? queryResponses.remove(0) : null; + } + } + + @Override + public byte[] getBinaryResponse() { + synchronized(queryResponsesBytes) { + return queryResponsesBytes.size() > 0 ? queryResponsesBytes.remove(0) : null; + } + } + + @Override + public void onClose(int arg0, String arg1, boolean arg2) { + open = false; + } + + @Override + public void onError(Exception arg0) { + System.err.println("WebSocket query error: " + arg0.toString()); + open = false; + this.close(); + } + + @Override + public void onMessage(String arg0) { + synchronized(queryResponses) { + try { + queryResponses.add(new QueryResponse(new JSONObject(arg0))); + }catch(Throwable t) { + System.err.println("Query response parse error: " + t.toString()); + } + } + } + + @Override + public void onMessage(ByteBuffer arg0) { + synchronized(queryResponsesBytes) { + byte[] pkt = new byte[arg0.limit()]; + arg0.get(pkt); + queryResponsesBytes.add(pkt); + } + } + + @Override + public void onOpen(ServerHandshake arg0) { + send("Accept: " + type); + } + + @Override + public boolean isQueryOpen() { + return open; + } + + } + + public static final ServerQuery openQuery(String type, String uri) { + try { + return new ServerQueryImpl(type, new URI(uri)); + }catch(Throwable t) { + System.err.println("WebSocket query error: " + t.toString()); + return null; + } + } + } diff --git a/src/main/java/net/lax1dude/eaglercraft/ServerQuery.java b/src/main/java/net/lax1dude/eaglercraft/ServerQuery.java new file mode 100644 index 0000000..4df994f --- /dev/null +++ b/src/main/java/net/lax1dude/eaglercraft/ServerQuery.java @@ -0,0 +1,105 @@ +package net.lax1dude.eaglercraft; + +import org.json.JSONObject; + +public interface ServerQuery { + + public static final long defaultTimeout = 10000l; + + public static class QueryResponse { + public final String responseType; + private final Object responseData; + public final String serverVersion; + public final String serverBrand; + public final String serverName; + public final long serverTime; + public final long clientTime; + public final boolean serverCracked; + public QueryResponse(JSONObject obj) { + this.responseType = obj.getString("type").toLowerCase(); + this.responseData = obj.get("data"); + this.serverVersion = obj.getString("vers"); + this.serverBrand = obj.getString("brand"); + this.serverName = obj.getString("name"); + this.serverTime = obj.getLong("time"); + this.clientTime = System.currentTimeMillis(); + this.serverCracked = obj.has("cracked") ? obj.getBoolean("cracked") : false; + } + public boolean isResponseString() { + return responseData instanceof String; + } + public boolean isResponseJSON() { + return responseData instanceof JSONObject; + } + public String getResponseString() { + return (String)responseData; + } + public JSONObject getResponseJSON() { + return (JSONObject)responseData; + } + } + + public boolean isQueryOpen(); + public void close(); + + public void send(String str); + + public default void send(JSONObject obj) { + send(obj.toString()); + } + + public int responseAvailable(); + public int responseBinaryAvailable(); + public QueryResponse getResponse(); + public byte[] getBinaryResponse(); + + // normally I wouldn't resort to race conditions but TeaVM has no + // java.util.concurrent classes for semaphore-like behavior + + public default boolean awaitResponseAvailable(long timeout) { + long start = System.currentTimeMillis(); + while(isQueryOpen() && responseAvailable() <= 0 && (timeout <= 0l || System.currentTimeMillis() - start < timeout)) { + try { + Thread.sleep(0l, 250000); + } catch (InterruptedException e) { + } + } + return responseAvailable() > 0; + } + + public default boolean awaitResponseAvailable() { + return awaitResponseAvailable(defaultTimeout); + } + + public default boolean awaitResponseBinaryAvailable(long timeout) { + long start = System.currentTimeMillis(); + while(isQueryOpen() && responseBinaryAvailable() <= 0 && (timeout <= 0l || System.currentTimeMillis() - start < timeout)) { + try { + Thread.sleep(0l, 250000); + } catch (InterruptedException e) { + } + } + return responseBinaryAvailable() > 0; + } + + public default boolean awaitResponseBinaryAvailable() { + return awaitResponseBinaryAvailable(defaultTimeout); + } + + public default QueryResponse awaitResponse(long timeout) { + return awaitResponseAvailable(timeout) ? getResponse() : null; + } + + public default QueryResponse awaitResponse() { + return awaitResponseAvailable() ? getResponse() : null; + } + + public default byte[] awaitResponseBinary(long timeout) { + return awaitResponseBinaryAvailable(timeout) ? getBinaryResponse() : null; + } + + public default byte[] awaitResponseBinary() { + return awaitResponseBinaryAvailable() ? getBinaryResponse() : null; + } + +} diff --git a/src/main/java/net/minecraft/src/GuiMultiplayer.java b/src/main/java/net/minecraft/src/GuiMultiplayer.java index 0e279d8..0b6d7e3 100644 --- a/src/main/java/net/minecraft/src/GuiMultiplayer.java +++ b/src/main/java/net/minecraft/src/GuiMultiplayer.java @@ -1,10 +1,5 @@ package net.minecraft.src; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.Socket; import java.util.Collections; import java.util.List; @@ -108,6 +103,7 @@ public class GuiMultiplayer extends GuiScreen { */ public void updateScreen() { super.updateScreen(); + internetServerList.updateServerPing(); ++this.ticksOpened; } @@ -116,6 +112,10 @@ public class GuiMultiplayer extends GuiScreen { */ public void onGuiClosed() { EaglerAdapter.enableRepeatEvents(false); + if(field_74024_A) { + internetServerList.freeServerIcons(); + field_74024_A = false; + } } /** @@ -198,6 +198,7 @@ public class GuiMultiplayer extends GuiScreen { var3.serverName = this.theServerData.serverName; var3.serverIP = this.theServerData.serverIP; var3.setHideAddress(this.theServerData.isHidingAddress()); + var3.pingSentTime = -1l; this.internetServerList.saveServerList(); } @@ -269,120 +270,38 @@ public class GuiMultiplayer extends GuiScreen { this.mc.displayGuiScreen(new GuiConnecting(this, this.mc, par1ServerData)); } - private static void func_74017_b(ServerData par1ServerData) throws IOException { - ServerAddress var1 = ServerAddress.func_78860_a(par1ServerData.serverIP); - Socket var2 = null; - DataInputStream var3 = null; - DataOutputStream var4 = null; - - try { - var2 = new Socket(); - var2.setSoTimeout(3000); - var2.setTcpNoDelay(true); - var2.setTrafficClass(18); - var2.connect(new InetSocketAddress(var1.getIP(), var1.getPort()), 3000); - var3 = new DataInputStream(var2.getInputStream()); - var4 = new DataOutputStream(var2.getOutputStream()); - var4.write(254); - var4.write(1); - - if (var3.read() != 255) { - throw new IOException("Bad message"); - } - - String var5 = Packet.readString(var3, 256); - char[] var6 = var5.toCharArray(); - - for (int var7 = 0; var7 < var6.length; ++var7) { - if (var6[var7] != 167 && var6[var7] != 0 && ChatAllowedCharacters.allowedCharacters.indexOf(var6[var7]) < 0) { - var6[var7] = 63; - } - } - - var5 = new String(var6); - int var8; - int var9; - String[] var26; - - if (var5.startsWith("\u00a7") && var5.length() > 1) { - var26 = var5.substring(1).split("\u0000"); - - if (MathHelper.parseIntWithDefault(var26[0], 0) == 1) { - par1ServerData.serverMOTD = var26[3]; - par1ServerData.field_82821_f = MathHelper.parseIntWithDefault(var26[1], par1ServerData.field_82821_f); - par1ServerData.gameVersion = var26[2]; - var8 = MathHelper.parseIntWithDefault(var26[4], 0); - var9 = MathHelper.parseIntWithDefault(var26[5], 0); - - if (var8 >= 0 && var9 >= 0) { - par1ServerData.populationInfo = EnumChatFormatting.GRAY + "" + var8 + "" + EnumChatFormatting.DARK_GRAY + "/" + EnumChatFormatting.GRAY + var9; - } else { - par1ServerData.populationInfo = "" + EnumChatFormatting.DARK_GRAY + "???"; - } - } else { - par1ServerData.gameVersion = "???"; - par1ServerData.serverMOTD = "" + EnumChatFormatting.DARK_GRAY + "???"; - par1ServerData.field_82821_f = 62; - par1ServerData.populationInfo = "" + EnumChatFormatting.DARK_GRAY + "???"; - } - } else { - var26 = var5.split("\u00a7"); - var5 = var26[0]; - var8 = -1; - var9 = -1; - - try { - var8 = Integer.parseInt(var26[1]); - var9 = Integer.parseInt(var26[2]); - } catch (Exception var24) { - ; - } - - par1ServerData.serverMOTD = EnumChatFormatting.GRAY + var5; - - if (var8 >= 0 && var9 > 0) { - par1ServerData.populationInfo = EnumChatFormatting.GRAY + "" + var8 + "" + EnumChatFormatting.DARK_GRAY + "/" + EnumChatFormatting.GRAY + var9; - } else { - par1ServerData.populationInfo = "" + EnumChatFormatting.DARK_GRAY + "???"; - } - - par1ServerData.gameVersion = "1.3"; - par1ServerData.field_82821_f = 60; - } - } finally { - try { - if (var3 != null) { - var3.close(); - } - } catch (Throwable var23) { - ; - } - - try { - if (var4 != null) { - var4.close(); - } - } catch (Throwable var22) { - ; - } - - try { - if (var2 != null) { - var2.close(); - } - } catch (Throwable var21) { - ; - } - } - } - protected void func_74007_a(String par1Str, int par2, int par3) { if (par1Str != null) { - int var4 = par2 + 12; - int var5 = par3 - 12; - int var6 = this.fontRenderer.getStringWidth(par1Str); - this.drawGradientRect(var4 - 3, var5 - 3, var4 + var6 + 3, var5 + 8 + 3, -1073741824, -1073741824); - this.fontRenderer.drawStringWithShadow(par1Str, var4, var5, -1); + if(par1Str.indexOf('\n') >= 0) { + String[] strs = par1Str.split("\n"); + int var6 = 0; + int full = 0; + for(int i = 0; i < strs.length; ++i) { + strs[i] = strs[i].replace('\r', ' ').trim(); + if(strs[i].length() > 0) { + int w = this.fontRenderer.getStringWidth(strs[i]); + if(w > var6) { + var6 = w; + } + ++full; + } + } + int var4 = par2 + 12; + int var5 = par3 - 12; + this.drawGradientRect(var4 - 3, var5 - 3, var4 + var6 + 3, var5 + full * 9 + 2, -1073741824, -1073741824); + full = 0; + for(int i = 0; i < strs.length; ++i) { + if(strs[i].length() > 0) { + this.fontRenderer.drawStringWithShadow(strs[i], var4, var5 + 9 * full++, -1); + } + } + }else { + int var4 = par2 + 12; + int var5 = par3 - 12; + int var6 = this.fontRenderer.getStringWidth(par1Str); + this.drawGradientRect(var4 - 3, var5 - 3, var4 + var6 + 3, var5 + 8 + 3, -1073741824, -1073741824); + this.fontRenderer.drawStringWithShadow(par1Str, var4, var5, -1); + } } } @@ -446,10 +365,6 @@ public class GuiMultiplayer extends GuiScreen { return threadsPending++; } - static void func_82291_a(ServerData par0ServerData) throws IOException { - func_74017_b(par0ServerData); - } - static int decreaseThreadsPending() { return threadsPending--; } diff --git a/src/main/java/net/minecraft/src/GuiSlot.java b/src/main/java/net/minecraft/src/GuiSlot.java index 7772101..ab39ca4 100644 --- a/src/main/java/net/minecraft/src/GuiSlot.java +++ b/src/main/java/net/minecraft/src/GuiSlot.java @@ -7,7 +7,7 @@ import net.lax1dude.eaglercraft.TextureLocation; import net.lax1dude.eaglercraft.adapter.Tessellator; public abstract class GuiSlot { - private final Minecraft mc; + protected final Minecraft mc; /** * The width of the GuiScreen. Affects the container rendering, but not the @@ -66,6 +66,7 @@ public abstract class GuiSlot { private boolean showSelectionBox = true; private boolean field_77243_s; private int field_77242_t; + protected int elementWidth = 110; public GuiSlot(Minecraft par1Minecraft, int par2, int par3, int par4, int par5, int par6) { this.mc = par1Minecraft; @@ -137,8 +138,8 @@ public abstract class GuiSlot { } public int func_77210_c(int par1, int par2) { - int var3 = this.width / 2 - 110; - int var4 = this.width / 2 + 110; + int var3 = this.width / 2 - elementWidth; + int var4 = this.width / 2 + elementWidth; int var5 = par2 - this.top - this.field_77242_t + (int) this.amountScrolled - 4; int var6 = var5 / this.slotHeight; return par1 >= var3 && par1 <= var4 && var6 >= 0 && var5 >= 0 && var6 < this.getSize() ? var6 : -1; @@ -219,8 +220,8 @@ public abstract class GuiSlot { boolean var7 = true; if (par2 >= this.top && par2 <= this.bottom) { - int var8 = this.width / 2 - 110; - var9 = this.width / 2 + 110; + int var8 = this.width / 2 - elementWidth; + var9 = this.width / 2 + elementWidth; var10 = par2 - this.top - this.field_77242_t + (int) this.amountScrolled - 4; var11 = var10 / this.slotHeight; @@ -301,7 +302,7 @@ public abstract class GuiSlot { var18.addVertexWithUV((double) this.right, (double) this.top, 0.0D, (double) ((float) this.right / var17), (double) ((float) (this.top + (int) this.amountScrolled) / var17)); var18.addVertexWithUV((double) this.left, (double) this.top, 0.0D, (double) ((float) this.left / var17), (double) ((float) (this.top + (int) this.amountScrolled) / var17)); var18.draw(); - var9 = this.width / 2 - 92 - 16; + var9 = this.width / 2 + 2 - elementWidth; var10 = this.top + 4 - (int) this.amountScrolled; if (this.field_77243_s) { @@ -316,8 +317,8 @@ public abstract class GuiSlot { if (var20 <= this.bottom && var20 + var13 >= this.top) { if (this.showSelectionBox && this.isSelected(var11)) { - var14 = this.width / 2 - 110; - int var15 = this.width / 2 + 110; + var14 = this.width / 2 - elementWidth; + int var15 = this.width / 2 + elementWidth; EaglerAdapter.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); EaglerAdapter.glDisable(EaglerAdapter.GL_TEXTURE_2D); var18.startDrawingQuads(); @@ -414,7 +415,7 @@ public abstract class GuiSlot { } protected int getScrollBarX() { - return this.width / 2 + 124; + return this.width / 2 + elementWidth + 14; } /** diff --git a/src/main/java/net/minecraft/src/GuiSlotServer.java b/src/main/java/net/minecraft/src/GuiSlotServer.java index 28b7dd5..b6922fb 100644 --- a/src/main/java/net/minecraft/src/GuiSlotServer.java +++ b/src/main/java/net/minecraft/src/GuiSlotServer.java @@ -8,10 +8,13 @@ import net.lax1dude.eaglercraft.adapter.Tessellator; class GuiSlotServer extends GuiSlot { /** Instance to the GUI this list is on. */ final GuiMultiplayer parentGui; + + private static final TextureLocation defaultServerIcon = new TextureLocation("/gui/unknown_pack.png"); public GuiSlotServer(GuiMultiplayer par1GuiMultiplayer) { super(par1GuiMultiplayer.mc, par1GuiMultiplayer.width, par1GuiMultiplayer.height, 32, par1GuiMultiplayer.height - 64, 36); this.parentGui = par1GuiMultiplayer; + this.elementWidth = 128; } /** @@ -76,22 +79,55 @@ class GuiSlotServer extends GuiSlot { boolean var7 = var6.field_82821_f > 61; boolean var8 = var6.field_82821_f < 61; boolean var9 = var7 || var8; - this.parentGui.drawString(this.parentGui.fontRenderer, var6.serverName, par2 + 2, par3 + 1, 16777215); - this.parentGui.drawString(this.parentGui.fontRenderer, var6.serverMOTD, par2 + 2, par3 + 12, 8421504); - this.parentGui.drawString(this.parentGui.fontRenderer, var6.populationInfo, par2 + 215 - this.parentGui.fontRenderer.getStringWidth(var6.populationInfo), par3 + 12, 8421504); + this.parentGui.drawString(this.parentGui.fontRenderer, var6.serverName, par2 + 38, par3 + 1, 16777215); + if(var6.hasPing && var6.pingToServer > 0) { + int i = var6.serverMOTD.indexOf('\n'); + if(i > 0) { + this.parentGui.drawString(this.parentGui.fontRenderer, var6.serverMOTD.substring(0, i), par2 + 38, par3 + 12, 8421504); + this.parentGui.drawString(this.parentGui.fontRenderer, var6.serverMOTD.substring(i + 1), par2 + 38, par3 + 12 + 11, 8421504); + }else { + this.parentGui.drawString(this.parentGui.fontRenderer, var6.serverMOTD, par2 + 38, par3 + 12, 8421504); + if (!this.parentGui.mc.gameSettings.hideServerAddress && !var6.isHidingAddress()) { + this.parentGui.drawString(this.parentGui.fontRenderer, var6.serverIP, par2 + 38, par3 + 12 + 11, 3158064); + } else { + this.parentGui.drawString(this.parentGui.fontRenderer, StatCollector.translateToLocal("selectServer.hiddenAddress"), par2 + 38, par3 + 12 + 11, 3158064); + } + } + this.parentGui.drawString(this.parentGui.fontRenderer, var6.populationInfo, par2 + 251 - this.parentGui.fontRenderer.getStringWidth(var6.populationInfo), par3 + 12, 8421504); + }else { + if (!this.parentGui.mc.gameSettings.hideServerAddress && !var6.isHidingAddress()) { + this.parentGui.drawString(this.parentGui.fontRenderer, var6.serverIP, par2 + 38, par3 + 12 + 11, 3158064); + } else { + this.parentGui.drawString(this.parentGui.fontRenderer, StatCollector.translateToLocal("selectServer.hiddenAddress"), par2 + 38, par3 + 12 + 11, 3158064); + } + } if (var9) { String var10 = EnumChatFormatting.DARK_RED + var6.gameVersion; - this.parentGui.drawString(this.parentGui.fontRenderer, var10, par2 + 200 - this.parentGui.fontRenderer.getStringWidth(var10), par3 + 1, 8421504); - } - - if (!this.parentGui.mc.gameSettings.hideServerAddress && !var6.isHidingAddress()) { - this.parentGui.drawString(this.parentGui.fontRenderer, var6.serverIP, par2 + 2, par3 + 12 + 11, 3158064); - } else { - this.parentGui.drawString(this.parentGui.fontRenderer, StatCollector.translateToLocal("selectServer.hiddenAddress"), par2 + 2, par3 + 12 + 11, 3158064); + this.parentGui.drawString(this.parentGui.fontRenderer, var10, par2 + 240 - this.parentGui.fontRenderer.getStringWidth(var10), par3 + 1, 8421504); } EaglerAdapter.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); + + var6.refreshIcon(); + if(var6.serverIconEnabled && var6.serverIconGL != -1) { + this.mc.renderEngine.bindTexture(var6.serverIconGL); + }else { + defaultServerIcon.bindTexture(); + } + + int iconX = par2 + 2; + int iconY = par3 + 2; + int iconSize = 28; + + Tessellator var14 = Tessellator.instance; + var14.startDrawingQuads(); + var14.addVertexWithUV((double) (iconX + 0), (double) (iconY + iconSize), 0.0d, 0.0d, 1.0d); + var14.addVertexWithUV((double) (iconX + iconSize), (double) (iconY + iconSize), 0.0d, 1.0d, 1.0d); + var14.addVertexWithUV((double) (iconX + iconSize), (double) (iconY + 0), 0.0d, 1.0d, 0.0d); + var14.addVertexWithUV((double) (iconX + 0), (double) (iconY + 0), 0.0d, 0.0d, 0.0d); + var14.draw(); + icons.bindTexture(); byte var15 = 0; boolean var11 = false; @@ -101,7 +137,7 @@ class GuiSlotServer extends GuiSlot { if (var9) { var12 = var7 ? "Client out of date!" : "Server out of date!"; var16 = 5; - } else if (var6.field_78841_f && var6.pingToServer != -2L) { + } else if (var6.hasPing && var6.pingToServer != -2L) { if (var6.pingToServer < 0L) { var16 = 5; } else if (var6.pingToServer < 150L) { @@ -119,7 +155,7 @@ class GuiSlotServer extends GuiSlot { if (var6.pingToServer < 0L) { var12 = "(no connection)"; } else { - var12 = "default"; //var6.pingToServer + "ms"; + var12 = var6.pingToServer + "ms"; } } else { var15 = 1; @@ -129,14 +165,22 @@ class GuiSlotServer extends GuiSlot { var16 = 8 - var16; } - var12 = "3rd party"; + var12 = "Polling.."; } - this.parentGui.drawTexturedModalRect(par2 + 205, par3, 0 + var15 * 10, 176 + var16 * 8, 10, 8); + this.parentGui.drawTexturedModalRect(par2 + 241, par3, 0 + var15 * 10, 176 + var16 * 8, 10, 8); byte var13 = 4; - if (this.mouseX >= par2 + 205 - var13 && this.mouseY >= par3 - var13 && this.mouseX <= par2 + 205 + 10 + var13 && this.mouseY <= par3 + 8 + var13) { + if (this.mouseX >= par2 + 245 - var13 && this.mouseY >= par3 - var13 && this.mouseX <= par2 + 245 + 10 + var13 && this.mouseY <= par3 + 4 + var13) { GuiMultiplayer.getAndSetLagTooltip(this.parentGui, var12); + }else if (this.mouseX >= par2 + 230 - var13 && this.mouseY >= par3 - var13 + 4 && this.mouseX <= par2 + 245 + 10 + var13 && this.mouseY <= par3 + 8 + var13 + 8) { + if(var6.playerList.size() > 0) { + var12 = ""; + for(String s : var6.playerList) { + var12 += (s + "\n"); + } + GuiMultiplayer.getAndSetLagTooltip(this.parentGui, var12); + } } } } diff --git a/src/main/java/net/minecraft/src/ServerData.java b/src/main/java/net/minecraft/src/ServerData.java index 9bf75a5..c36d472 100644 --- a/src/main/java/net/minecraft/src/ServerData.java +++ b/src/main/java/net/minecraft/src/ServerData.java @@ -1,5 +1,17 @@ package net.minecraft.src; +import java.nio.IntBuffer; +import java.util.ArrayList; +import java.util.List; + +import org.json.JSONArray; +import org.json.JSONObject; + +import net.lax1dude.eaglercraft.EaglerAdapter; +import net.lax1dude.eaglercraft.ServerQuery; +import net.lax1dude.eaglercraft.ServerQuery.QueryResponse; +import net.minecraft.client.Minecraft; + public class ServerData { public String serverName; public String serverIP; @@ -19,13 +31,20 @@ public class ServerData { /** last server ping that showed up in the server browser */ public long pingToServer; + public long pingSentTime; public int field_82821_f = 61; /** Game version for this server. */ public String gameVersion = "1.5.2"; - public boolean field_78841_f = false; + public boolean hasPing = false; private boolean field_78842_g = true; private boolean acceptsTextures = false; + public ServerQuery currentQuery = null; + public int[] serverIcon = null; + public boolean serverIconDirty = false; + public boolean serverIconEnabled = false; + public List playerList = new ArrayList(); + public int serverIconGL = -1; /** Whether to hide the IP address for this server. */ private boolean hideAddress = false; @@ -76,12 +95,74 @@ public class ServerData { public static ServerData getServerDataFromNBTCompound(NBTTagCompound par0NBTTagCompound) { ServerData var1 = new ServerData(par0NBTTagCompound.getString("name"), par0NBTTagCompound.getString("ip")); var1.hideAddress = par0NBTTagCompound.getBoolean("hideAddress"); - var1.serverMOTD = par0NBTTagCompound.getString("forcedMOTD"); - if(!var1.serverMOTD.isEmpty()) { - var1.populationInfo = "|>"; - var1.pingToServer = 0l; - var1.field_78841_f = true; - } return var1; } + + public void setMOTDFromQuery(QueryResponse pkt) { + if(!pkt.serverCracked) { + this.gameVersion = ""; + this.serverIconEnabled = false; + this.serverMOTD = "" + EnumChatFormatting.RED + "Error: account required"; + this.populationInfo = ""; + if(pingSentTime > 0l) { + pingToServer = pkt.clientTime - pingSentTime; + pingSentTime = 0l; + } + } + JSONObject motdData = pkt.getResponseJSON(); + JSONArray motd = motdData.getJSONArray("motd"); + this.serverMOTD = motd.length() > 0 ? (motd.length() > 1 ? motd.getString(0) + "\n" + motd.getString(1) : motd.getString(0)) : ""; + this.populationInfo = "" + motdData.getInt("online") + "/" + motdData.getInt("max"); + this.playerList.clear(); + JSONArray players = motdData.getJSONArray("players"); + for(int i = 0, l = players.length(); i < l; ++i) { + this.playerList.add(players.getString(i)); + } + serverIconEnabled = motdData.getBoolean("icon"); + if(!serverIconEnabled) { + if(serverIconGL != -1) { + EaglerAdapter.glDeleteTextures(serverIconGL); + serverIconGL = -1; + } + } + + } + + public void refreshIcon() { + if(serverIconEnabled) { + if(serverIconDirty && serverIcon != null) { + if(serverIconGL == -1) { + serverIconGL = EaglerAdapter.glGenTextures(); + Minecraft.getMinecraft().renderEngine.bindTexture(serverIconGL); + EaglerAdapter.glTexParameteri(EaglerAdapter.GL_TEXTURE_2D, EaglerAdapter.GL_TEXTURE_WRAP_S, EaglerAdapter.GL_REPEAT); + EaglerAdapter.glTexParameteri(EaglerAdapter.GL_TEXTURE_2D, EaglerAdapter.GL_TEXTURE_WRAP_T, EaglerAdapter.GL_REPEAT); + EaglerAdapter.glTexParameteri(EaglerAdapter.GL_TEXTURE_2D, EaglerAdapter.GL_TEXTURE_MIN_FILTER, EaglerAdapter.GL_NEAREST); + EaglerAdapter.glTexParameteri(EaglerAdapter.GL_TEXTURE_2D, EaglerAdapter.GL_TEXTURE_MAG_FILTER, EaglerAdapter.GL_NEAREST); + }else { + Minecraft.getMinecraft().renderEngine.bindTexture(serverIconGL); + } + IntBuffer buf = GLAllocation.createDirectIntBuffer(4096); + buf.put(serverIcon); + buf.flip(); + EaglerAdapter.glTexImage2D(EaglerAdapter.GL_TEXTURE_2D, 0, EaglerAdapter.GL_RGBA, 64, 64, 0, EaglerAdapter.GL_BGRA, EaglerAdapter.GL_UNSIGNED_INT_8_8_8_8_REV, buf); + serverIconDirty = false; + } + }else { + if(serverIconGL != -1) { + EaglerAdapter.glDeleteTextures(serverIconGL); + serverIconGL = -1; + serverIconDirty = false; + } + } + } + + public void freeIcon() { + if(serverIconGL != -1) { + EaglerAdapter.glDeleteTextures(serverIconGL); + serverIconGL = -1; + } + serverIconDirty = false; + serverIconEnabled = false; + } + } diff --git a/src/main/java/net/minecraft/src/ServerList.java b/src/main/java/net/minecraft/src/ServerList.java index b49ee2d..ebc63c6 100644 --- a/src/main/java/net/minecraft/src/ServerList.java +++ b/src/main/java/net/minecraft/src/ServerList.java @@ -6,7 +6,9 @@ import java.util.List; import net.lax1dude.eaglercraft.Base64; import net.lax1dude.eaglercraft.ConfigConstants; +import net.lax1dude.eaglercraft.EaglerAdapter; import net.lax1dude.eaglercraft.LocalStorageManager; +import net.lax1dude.eaglercraft.ServerQuery.QueryResponse; import net.minecraft.client.Minecraft; public class ServerList { @@ -14,7 +16,7 @@ public class ServerList { private final Minecraft mc; /** List of ServerData instances. */ - private final List servers = new ArrayList(); + private final List servers = new ArrayList(); public static final List forcedServers = new ArrayList(); @@ -45,8 +47,13 @@ public class ServerList { * "servers" tag list. */ public void loadServerList() { + freeServerIcons(); this.servers.clear(); - this.servers.addAll(forcedServers); + for(ServerData dat : forcedServers) { + dat.pingSentTime = -1l; + dat.hasPing = false; + this.servers.add(dat); + } NBTTagList servers = LocalStorageManager.gameSettingsStorage.getTagList("servers"); for (int i = 0; i < servers.tagCount(); ++i) { this.servers.add(ServerData.getServerDataFromNBTCompound((NBTTagCompound) servers.tagAt(i))); @@ -77,13 +84,18 @@ public class ServerList { * Removes the ServerData instance stored for the given index in the list. */ public void removeServerData(int par1) { - this.servers.remove(par1); + ServerData dat = this.servers.remove(par1); + if(dat != null) { + dat.freeIcon(); + } } /** * Adds the given ServerData instance to the list. */ public void addServerData(ServerData par1ServerData) { + par1ServerData.pingSentTime = -1l; + par1ServerData.hasPing = false; this.servers.add(par1ServerData); } @@ -110,20 +122,92 @@ public class ServerList { public void setServer(int par1, ServerData par2ServerData) { this.servers.set(par1, par2ServerData); } - - public static void func_78852_b(ServerData par0ServerData) { - ServerList var1 = new ServerList(Minecraft.getMinecraft()); - var1.loadServerList(); - - for (int var2 = 0; var2 < var1.countServers(); ++var2) { - ServerData var3 = var1.getServerData(var2); - - if (var3.serverName.equals(par0ServerData.serverName) && var3.serverIP.equals(par0ServerData.serverIP)) { - var1.setServer(var2, par0ServerData); + + public void freeServerIcons() { + for(ServerData dat : servers) { + if(dat.currentQuery != null && dat.currentQuery.isQueryOpen()) { + dat.currentQuery.close(); + } + if(dat.serverIconGL != -1) { + EaglerAdapter.glDeleteTextures(dat.serverIconGL); + dat.serverIconGL = -1; + } + dat.serverIconDirty = false; + dat.serverIconEnabled = false; + } + } + + public void refreshServerPing() { + for(ServerData dat : servers) { + if(dat.currentQuery != null && dat.currentQuery.isQueryOpen()) { + dat.currentQuery.close(); + } + dat.hasPing = false; + dat.pingSentTime = -1l; + } + } + + public void updateServerPing() { + int total = 0; + for(ServerData dat : servers) { + if(dat.pingSentTime <= 0l) { + dat.pingToServer = -2l; + String addr = dat.serverIP; + if(!addr.startsWith("ws://") && !addr.startsWith("wss://")) { + if(EaglerAdapter.isSSLPage()) { + addr = "wss://" + addr; + }else { + addr = "ws://" + addr; + } + } + dat.pingSentTime = System.currentTimeMillis(); + dat.currentQuery = EaglerAdapter.openQuery("MOTD", addr); + if(dat.currentQuery == null) { + dat.hasPing = true; + }else { + ++total; + } + }else if(dat.currentQuery != null) { + if(!dat.hasPing) { + ++total; + } + if(dat.currentQuery.responseAvailable() > 0) { + QueryResponse pkt; + do { + pkt = dat.currentQuery.getResponse(); + }while(dat.currentQuery.responseAvailable() > 0); + if(pkt.responseType.equalsIgnoreCase("MOTD") && pkt.isResponseJSON()) { + dat.setMOTDFromQuery(pkt); + if(!dat.hasPing) { + dat.pingToServer = pkt.clientTime - dat.pingSentTime; + dat.hasPing = true; + } + } + } + if(dat.currentQuery.responseBinaryAvailable() > 0) { + byte[] r; + do { + r = dat.currentQuery.getBinaryResponse(); + }while(dat.currentQuery.responseBinaryAvailable() > 0); + if(r.length == 4096 * 4) { + if(dat.serverIcon == null) { + dat.serverIcon = new int[4096]; + } + for(int i = 0; i < 4096; ++i) { + dat.serverIcon[i] = (((int)r[i * 4 + 3]&0xFF) << 24) | (((int)r[i * 4]&0xFF) << 16) | (((int)r[i * 4 + 1]&0xFF) << 8) | ((int)r[i * 4 + 2]&0xFF); + } + dat.serverIconDirty = true; + } + } + if(!dat.currentQuery.isQueryOpen() && dat.pingSentTime > 0l && !dat.hasPing) { + dat.pingToServer = -1l; + dat.hasPing = true; + } + } + if(total >= 4) { break; } } - - var1.saveServerList(); } + } diff --git a/src/main/java/org/json/CDL.java b/src/main/java/org/json/CDL.java new file mode 100644 index 0000000..f12cfc0 --- /dev/null +++ b/src/main/java/org/json/CDL.java @@ -0,0 +1,287 @@ +package org.json; + +/* +Copyright (c) 2002 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ + +/** + * This provides static methods to convert comma delimited text into a + * JSONArray, and to convert a JSONArray into comma delimited text. Comma + * delimited text is a very popular format for data interchange. It is + * understood by most database, spreadsheet, and organizer programs. + *

+ * Each row of text represents a row in a table or a data record. Each row + * ends with a NEWLINE character. Each row contains one or more values. + * Values are separated by commas. A value can contain any character except + * for comma, unless is is wrapped in single quotes or double quotes. + *

+ * The first row usually contains the names of the columns. + *

+ * A comma delimited list can be converted into a JSONArray of JSONObjects. + * The names for the elements in the JSONObjects can be taken from the names + * in the first row. + * @author JSON.org + * @version 2016-05-01 + */ +public class CDL { + + /** + * Get the next value. The value can be wrapped in quotes. The value can + * be empty. + * @param x A JSONTokener of the source text. + * @return The value string, or null if empty. + * @throws JSONException if the quoted string is badly formed. + */ + private static String getValue(JSONTokener x) throws JSONException { + char c; + char q; + StringBuilder sb; + do { + c = x.next(); + } while (c == ' ' || c == '\t'); + switch (c) { + case 0: + return null; + case '"': + case '\'': + q = c; + sb = new StringBuilder(); + for (;;) { + c = x.next(); + if (c == q) { + //Handle escaped double-quote + char nextC = x.next(); + if(nextC != '\"') { + // if our quote was the end of the file, don't step + if(nextC > 0) { + x.back(); + } + break; + } + } + if (c == 0 || c == '\n' || c == '\r') { + throw x.syntaxError("Missing close quote '" + q + "'."); + } + sb.append(c); + } + return sb.toString(); + case ',': + x.back(); + return ""; + default: + x.back(); + return x.nextTo(','); + } + } + + /** + * Produce a JSONArray of strings from a row of comma delimited values. + * @param x A JSONTokener of the source text. + * @return A JSONArray of strings. + * @throws JSONException if a called function fails + */ + public static JSONArray rowToJSONArray(JSONTokener x) throws JSONException { + JSONArray ja = new JSONArray(); + for (;;) { + String value = getValue(x); + char c = x.next(); + if (value == null || + (ja.length() == 0 && value.length() == 0 && c != ',')) { + return null; + } + ja.put(value); + for (;;) { + if (c == ',') { + break; + } + if (c != ' ') { + if (c == '\n' || c == '\r' || c == 0) { + return ja; + } + throw x.syntaxError("Bad character '" + c + "' (" + + (int)c + ")."); + } + c = x.next(); + } + } + } + + /** + * Produce a JSONObject from a row of comma delimited text, using a + * parallel JSONArray of strings to provides the names of the elements. + * @param names A JSONArray of names. This is commonly obtained from the + * first row of a comma delimited text file using the rowToJSONArray + * method. + * @param x A JSONTokener of the source text. + * @return A JSONObject combining the names and values. + * @throws JSONException if a called function fails + */ + public static JSONObject rowToJSONObject(JSONArray names, JSONTokener x) + throws JSONException { + JSONArray ja = rowToJSONArray(x); + return ja != null ? ja.toJSONObject(names) : null; + } + + /** + * Produce a comma delimited text row from a JSONArray. Values containing + * the comma character will be quoted. Troublesome characters may be + * removed. + * @param ja A JSONArray of strings. + * @return A string ending in NEWLINE. + */ + public static String rowToString(JSONArray ja) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < ja.length(); i += 1) { + if (i > 0) { + sb.append(','); + } + Object object = ja.opt(i); + if (object != null) { + String string = object.toString(); + if (string.length() > 0 && (string.indexOf(',') >= 0 || + string.indexOf('\n') >= 0 || string.indexOf('\r') >= 0 || + string.indexOf(0) >= 0 || string.charAt(0) == '"')) { + sb.append('"'); + int length = string.length(); + for (int j = 0; j < length; j += 1) { + char c = string.charAt(j); + if (c >= ' ' && c != '"') { + sb.append(c); + } + } + sb.append('"'); + } else { + sb.append(string); + } + } + } + sb.append('\n'); + return sb.toString(); + } + + /** + * Produce a JSONArray of JSONObjects from a comma delimited text string, + * using the first row as a source of names. + * @param string The comma delimited text. + * @return A JSONArray of JSONObjects. + * @throws JSONException if a called function fails + */ + public static JSONArray toJSONArray(String string) throws JSONException { + return toJSONArray(new JSONTokener(string)); + } + + /** + * Produce a JSONArray of JSONObjects from a comma delimited text string, + * using the first row as a source of names. + * @param x The JSONTokener containing the comma delimited text. + * @return A JSONArray of JSONObjects. + * @throws JSONException if a called function fails + */ + public static JSONArray toJSONArray(JSONTokener x) throws JSONException { + return toJSONArray(rowToJSONArray(x), x); + } + + /** + * Produce a JSONArray of JSONObjects from a comma delimited text string + * using a supplied JSONArray as the source of element names. + * @param names A JSONArray of strings. + * @param string The comma delimited text. + * @return A JSONArray of JSONObjects. + * @throws JSONException if a called function fails + */ + public static JSONArray toJSONArray(JSONArray names, String string) + throws JSONException { + return toJSONArray(names, new JSONTokener(string)); + } + + /** + * Produce a JSONArray of JSONObjects from a comma delimited text string + * using a supplied JSONArray as the source of element names. + * @param names A JSONArray of strings. + * @param x A JSONTokener of the source text. + * @return A JSONArray of JSONObjects. + * @throws JSONException if a called function fails + */ + public static JSONArray toJSONArray(JSONArray names, JSONTokener x) + throws JSONException { + if (names == null || names.length() == 0) { + return null; + } + JSONArray ja = new JSONArray(); + for (;;) { + JSONObject jo = rowToJSONObject(names, x); + if (jo == null) { + break; + } + ja.put(jo); + } + if (ja.length() == 0) { + return null; + } + return ja; + } + + + /** + * Produce a comma delimited text from a JSONArray of JSONObjects. The + * first row will be a list of names obtained by inspecting the first + * JSONObject. + * @param ja A JSONArray of JSONObjects. + * @return A comma delimited text. + * @throws JSONException if a called function fails + */ + public static String toString(JSONArray ja) throws JSONException { + JSONObject jo = ja.optJSONObject(0); + if (jo != null) { + JSONArray names = jo.names(); + if (names != null) { + return rowToString(names) + toString(names, ja); + } + } + return null; + } + + /** + * Produce a comma delimited text from a JSONArray of JSONObjects using + * a provided list of names. The list of names is not included in the + * output. + * @param names A JSONArray of strings. + * @param ja A JSONArray of JSONObjects. + * @return A comma delimited text. + * @throws JSONException if a called function fails + */ + public static String toString(JSONArray names, JSONArray ja) + throws JSONException { + if (names == null || names.length() == 0) { + return null; + } + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < ja.length(); i += 1) { + JSONObject jo = ja.optJSONObject(i); + if (jo != null) { + sb.append(rowToString(jo.toJSONArray(names))); + } + } + return sb.toString(); + } +} diff --git a/src/main/java/org/json/Cookie.java b/src/main/java/org/json/Cookie.java new file mode 100644 index 0000000..1c5fb78 --- /dev/null +++ b/src/main/java/org/json/Cookie.java @@ -0,0 +1,224 @@ +package org.json; + +import java.util.Locale; + +/* +Copyright (c) 2002 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +/** + * Convert a web browser cookie specification to a JSONObject and back. + * JSON and Cookies are both notations for name/value pairs. + * See also: https://tools.ietf.org/html/rfc6265 + * @author JSON.org + * @version 2015-12-09 + */ +public class Cookie { + + /** + * Produce a copy of a string in which the characters '+', '%', '=', ';' + * and control characters are replaced with "%hh". This is a gentle form + * of URL encoding, attempting to cause as little distortion to the + * string as possible. The characters '=' and ';' are meta characters in + * cookies. By convention, they are escaped using the URL-encoding. This is + * only a convention, not a standard. Often, cookies are expected to have + * encoded values. We encode '=' and ';' because we must. We encode '%' and + * '+' because they are meta characters in URL encoding. + * @param string The source string. + * @return The escaped result. + */ + public static String escape(String string) { + char c; + String s = string.trim(); + int length = s.length(); + StringBuilder sb = new StringBuilder(length); + for (int i = 0; i < length; i += 1) { + c = s.charAt(i); + if (c < ' ' || c == '+' || c == '%' || c == '=' || c == ';') { + sb.append('%'); + sb.append(Character.forDigit((char)((c >>> 4) & 0x0f), 16)); + sb.append(Character.forDigit((char)(c & 0x0f), 16)); + } else { + sb.append(c); + } + } + return sb.toString(); + } + + + /** + * Convert a cookie specification string into a JSONObject. The string + * must contain a name value pair separated by '='. The name and the value + * will be unescaped, possibly converting '+' and '%' sequences. The + * cookie properties may follow, separated by ';', also represented as + * name=value (except the Attribute properties like "Secure" or "HttpOnly", + * which do not have a value. The value {@link Boolean#TRUE} will be used for these). + * The name will be stored under the key "name", and the value will be + * stored under the key "value". This method does not do checking or + * validation of the parameters. It only converts the cookie string into + * a JSONObject. All attribute names are converted to lower case keys in the + * JSONObject (HttpOnly => httponly). If an attribute is specified more than + * once, only the value found closer to the end of the cookie-string is kept. + * @param string The cookie specification string. + * @return A JSONObject containing "name", "value", and possibly other + * members. + * @throws JSONException If there is an error parsing the Cookie String. + * Cookie strings must have at least one '=' character and the 'name' + * portion of the cookie must not be blank. + */ + public static JSONObject toJSONObject(String string) { + final JSONObject jo = new JSONObject(); + String name; + Object value; + + + JSONTokener x = new JSONTokener(string); + + name = unescape(x.nextTo('=').trim()); + //per RFC6265, if the name is blank, the cookie should be ignored. + if("".equals(name)) { + throw new JSONException("Cookies must have a 'name'"); + } + jo.put("name", name); + // per RFC6265, if there is no '=', the cookie should be ignored. + // the 'next' call here throws an exception if the '=' is not found. + x.next('='); + jo.put("value", unescape(x.nextTo(';')).trim()); + // discard the ';' + x.next(); + // parse the remaining cookie attributes + while (x.more()) { + name = unescape(x.nextTo("=;")).trim().toLowerCase(Locale.ROOT); + // don't allow a cookies attributes to overwrite its name or value. + if("name".equalsIgnoreCase(name)) { + throw new JSONException("Illegal attribute name: 'name'"); + } + if("value".equalsIgnoreCase(name)) { + throw new JSONException("Illegal attribute name: 'value'"); + } + // check to see if it's a flag property + if (x.next() != '=') { + value = Boolean.TRUE; + } else { + value = unescape(x.nextTo(';')).trim(); + x.next(); + } + // only store non-blank attributes + if(!"".equals(name) && !"".equals(value)) { + jo.put(name, value); + } + } + return jo; + } + + + /** + * Convert a JSONObject into a cookie specification string. The JSONObject + * must contain "name" and "value" members (case insensitive). + * If the JSONObject contains other members, they will be appended to the cookie + * specification string. User-Agents are instructed to ignore unknown attributes, + * so ensure your JSONObject is using only known attributes. + * See also: https://tools.ietf.org/html/rfc6265 + * @param jo A JSONObject + * @return A cookie specification string + * @throws JSONException thrown if the cookie has no name. + */ + public static String toString(JSONObject jo) throws JSONException { + StringBuilder sb = new StringBuilder(); + + String name = null; + Object value = null; + for(String key : jo.keySet()){ + if("name".equalsIgnoreCase(key)) { + name = jo.getString(key).trim(); + } + if("value".equalsIgnoreCase(key)) { + value=jo.getString(key).trim(); + } + if(name != null && value != null) { + break; + } + } + + if(name == null || "".equals(name.trim())) { + throw new JSONException("Cookie does not have a name"); + } + if(value == null) { + value = ""; + } + + sb.append(escape(name)); + sb.append("="); + sb.append(escape((String)value)); + + for(String key : jo.keySet()){ + if("name".equalsIgnoreCase(key) + || "value".equalsIgnoreCase(key)) { + // already processed above + continue; + } + value = jo.opt(key); + if(value instanceof Boolean) { + if(Boolean.TRUE.equals(value)) { + sb.append(';').append(escape(key)); + } + // don't emit false values + } else { + sb.append(';') + .append(escape(key)) + .append('=') + .append(escape(value.toString())); + } + } + + return sb.toString(); + } + + /** + * Convert %hh sequences to single characters, and + * convert plus to space. + * @param string A string that may contain + * + (plus) and + * %hh sequences. + * @return The unescaped string. + */ + public static String unescape(String string) { + int length = string.length(); + StringBuilder sb = new StringBuilder(length); + for (int i = 0; i < length; ++i) { + char c = string.charAt(i); + if (c == '+') { + c = ' '; + } else if (c == '%' && i + 2 < length) { + int d = JSONTokener.dehexchar(string.charAt(i + 1)); + int e = JSONTokener.dehexchar(string.charAt(i + 2)); + if (d >= 0 && e >= 0) { + c = (char)(d * 16 + e); + i += 2; + } + } + sb.append(c); + } + return sb.toString(); + } +} diff --git a/src/main/java/org/json/CookieList.java b/src/main/java/org/json/CookieList.java new file mode 100644 index 0000000..83b2630 --- /dev/null +++ b/src/main/java/org/json/CookieList.java @@ -0,0 +1,86 @@ +package org.json; + +/* +Copyright (c) 2002 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ + +/** + * Convert a web browser cookie list string to a JSONObject and back. + * @author JSON.org + * @version 2015-12-09 + */ +public class CookieList { + + /** + * Convert a cookie list into a JSONObject. A cookie list is a sequence + * of name/value pairs. The names are separated from the values by '='. + * The pairs are separated by ';'. The names and the values + * will be unescaped, possibly converting '+' and '%' sequences. + * + * To add a cookie to a cookie list, + * cookielistJSONObject.put(cookieJSONObject.getString("name"), + * cookieJSONObject.getString("value")); + * @param string A cookie list string + * @return A JSONObject + * @throws JSONException if a called function fails + */ + public static JSONObject toJSONObject(String string) throws JSONException { + JSONObject jo = new JSONObject(); + JSONTokener x = new JSONTokener(string); + while (x.more()) { + String name = Cookie.unescape(x.nextTo('=')); + x.next('='); + jo.put(name, Cookie.unescape(x.nextTo(';'))); + x.next(); + } + return jo; + } + + /** + * Convert a JSONObject into a cookie list. A cookie list is a sequence + * of name/value pairs. The names are separated from the values by '='. + * The pairs are separated by ';'. The characters '%', '+', '=', and ';' + * in the names and values are replaced by "%hh". + * @param jo A JSONObject + * @return A cookie list string + * @throws JSONException if a called function fails + */ + public static String toString(JSONObject jo) throws JSONException { + boolean b = false; + final StringBuilder sb = new StringBuilder(); + // Don't use the new entrySet API to maintain Android support + for (final String key : jo.keySet()) { + final Object value = jo.opt(key); + if (!JSONObject.NULL.equals(value)) { + if (b) { + sb.append(';'); + } + sb.append(Cookie.escape(key)); + sb.append("="); + sb.append(Cookie.escape(value.toString())); + b = true; + } + } + return sb.toString(); + } +} diff --git a/src/main/java/org/json/HTTP.java b/src/main/java/org/json/HTTP.java new file mode 100644 index 0000000..cc01167 --- /dev/null +++ b/src/main/java/org/json/HTTP.java @@ -0,0 +1,162 @@ +package org.json; + +/* +Copyright (c) 2002 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +import java.util.Locale; + +/** + * Convert an HTTP header to a JSONObject and back. + * @author JSON.org + * @version 2015-12-09 + */ +public class HTTP { + + /** Carriage return/line feed. */ + public static final String CRLF = "\r\n"; + + /** + * Convert an HTTP header string into a JSONObject. It can be a request + * header or a response header. A request header will contain + *

{
+     *    Method: "POST" (for example),
+     *    "Request-URI": "/" (for example),
+     *    "HTTP-Version": "HTTP/1.1" (for example)
+     * }
+ * A response header will contain + *
{
+     *    "HTTP-Version": "HTTP/1.1" (for example),
+     *    "Status-Code": "200" (for example),
+     *    "Reason-Phrase": "OK" (for example)
+     * }
+ * In addition, the other parameters in the header will be captured, using + * the HTTP field names as JSON names, so that
{@code
+     *    Date: Sun, 26 May 2002 18:06:04 GMT
+     *    Cookie: Q=q2=PPEAsg--; B=677gi6ouf29bn&b=2&f=s
+     *    Cache-Control: no-cache}
+ * become + *
{@code
+     *    Date: "Sun, 26 May 2002 18:06:04 GMT",
+     *    Cookie: "Q=q2=PPEAsg--; B=677gi6ouf29bn&b=2&f=s",
+     *    "Cache-Control": "no-cache",
+     * ...}
+ * It does no further checking or conversion. It does not parse dates. + * It does not do '%' transforms on URLs. + * @param string An HTTP header string. + * @return A JSONObject containing the elements and attributes + * of the XML string. + * @throws JSONException if a called function fails + */ + public static JSONObject toJSONObject(String string) throws JSONException { + JSONObject jo = new JSONObject(); + HTTPTokener x = new HTTPTokener(string); + String token; + + token = x.nextToken(); + if (token.toUpperCase(Locale.ROOT).startsWith("HTTP")) { + +// Response + + jo.put("HTTP-Version", token); + jo.put("Status-Code", x.nextToken()); + jo.put("Reason-Phrase", x.nextTo('\0')); + x.next(); + + } else { + +// Request + + jo.put("Method", token); + jo.put("Request-URI", x.nextToken()); + jo.put("HTTP-Version", x.nextToken()); + } + +// Fields + + while (x.more()) { + String name = x.nextTo(':'); + x.next(':'); + jo.put(name, x.nextTo('\0')); + x.next(); + } + return jo; + } + + + /** + * Convert a JSONObject into an HTTP header. A request header must contain + *
{
+     *    Method: "POST" (for example),
+     *    "Request-URI": "/" (for example),
+     *    "HTTP-Version": "HTTP/1.1" (for example)
+     * }
+ * A response header must contain + *
{
+     *    "HTTP-Version": "HTTP/1.1" (for example),
+     *    "Status-Code": "200" (for example),
+     *    "Reason-Phrase": "OK" (for example)
+     * }
+ * Any other members of the JSONObject will be output as HTTP fields. + * The result will end with two CRLF pairs. + * @param jo A JSONObject + * @return An HTTP header string. + * @throws JSONException if the object does not contain enough + * information. + */ + public static String toString(JSONObject jo) throws JSONException { + StringBuilder sb = new StringBuilder(); + if (jo.has("Status-Code") && jo.has("Reason-Phrase")) { + sb.append(jo.getString("HTTP-Version")); + sb.append(' '); + sb.append(jo.getString("Status-Code")); + sb.append(' '); + sb.append(jo.getString("Reason-Phrase")); + } else if (jo.has("Method") && jo.has("Request-URI")) { + sb.append(jo.getString("Method")); + sb.append(' '); + sb.append('"'); + sb.append(jo.getString("Request-URI")); + sb.append('"'); + sb.append(' '); + sb.append(jo.getString("HTTP-Version")); + } else { + throw new JSONException("Not enough material for an HTTP header."); + } + sb.append(CRLF); + // Don't use the new entrySet API to maintain Android support + for (final String key : jo.keySet()) { + String value = jo.optString(key); + if (!"HTTP-Version".equals(key) && !"Status-Code".equals(key) && + !"Reason-Phrase".equals(key) && !"Method".equals(key) && + !"Request-URI".equals(key) && !JSONObject.NULL.equals(value)) { + sb.append(key); + sb.append(": "); + sb.append(jo.optString(key)); + sb.append(CRLF); + } + } + sb.append(CRLF); + return sb.toString(); + } +} diff --git a/src/main/java/org/json/HTTPTokener.java b/src/main/java/org/json/HTTPTokener.java new file mode 100644 index 0000000..16c7081 --- /dev/null +++ b/src/main/java/org/json/HTTPTokener.java @@ -0,0 +1,77 @@ +package org.json; + +/* +Copyright (c) 2002 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +/** + * The HTTPTokener extends the JSONTokener to provide additional methods + * for the parsing of HTTP headers. + * @author JSON.org + * @version 2015-12-09 + */ +public class HTTPTokener extends JSONTokener { + + /** + * Construct an HTTPTokener from a string. + * @param string A source string. + */ + public HTTPTokener(String string) { + super(string); + } + + + /** + * Get the next token or string. This is used in parsing HTTP headers. + * @return A String. + * @throws JSONException if a syntax error occurs + */ + public String nextToken() throws JSONException { + char c; + char q; + StringBuilder sb = new StringBuilder(); + do { + c = next(); + } while (Character.isWhitespace(c)); + if (c == '"' || c == '\'') { + q = c; + for (;;) { + c = next(); + if (c < ' ') { + throw syntaxError("Unterminated string."); + } + if (c == q) { + return sb.toString(); + } + sb.append(c); + } + } + for (;;) { + if (c == 0 || Character.isWhitespace(c)) { + return sb.toString(); + } + sb.append(c); + c = next(); + } + } +} diff --git a/src/main/java/org/json/JSONArray.java b/src/main/java/org/json/JSONArray.java new file mode 100644 index 0000000..7e95a96 --- /dev/null +++ b/src/main/java/org/json/JSONArray.java @@ -0,0 +1,1716 @@ +package org.json; + +/* + Copyright (c) 2002 JSON.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + The Software shall be used for Good, not Evil. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + */ + +import java.io.IOException; +import java.io.StringWriter; +import java.io.Writer; +import java.lang.reflect.Array; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + + +/** + * A JSONArray is an ordered sequence of values. Its external text form is a + * string wrapped in square brackets with commas separating the values. The + * internal form is an object having get and opt + * methods for accessing the values by index, and put methods for + * adding or replacing values. The values can be any of these types: + * Boolean, JSONArray, JSONObject, + * Number, String, or the + * JSONObject.NULL object. + *

+ * The constructor can convert a JSON text into a Java object. The + * toString method converts to JSON text. + *

+ * A get method returns a value if one can be found, and throws an + * exception if one cannot be found. An opt method returns a + * default value instead of throwing an exception, and so is useful for + * obtaining optional values. + *

+ * The generic get() and opt() methods return an + * object which you can cast or query for type. There are also typed + * get and opt methods that do type checking and type + * coercion for you. + *

+ * The texts produced by the toString methods strictly conform to + * JSON syntax rules. The constructors are more forgiving in the texts they will + * accept: + *

    + *
  • An extra , (comma) may appear just + * before the closing bracket.
  • + *
  • The null value will be inserted when there is , + *  (comma) elision.
  • + *
  • Strings may be quoted with ' (single + * quote).
  • + *
  • Strings do not need to be quoted at all if they do not begin with a quote + * or single quote, and if they do not contain leading or trailing spaces, and + * if they do not contain any of these characters: + * { } [ ] / \ : , # and if they do not look like numbers and + * if they are not the reserved words true, false, or + * null.
  • + *
+ * + * @author JSON.org + * @version 2016-08/15 + */ +public class JSONArray implements Iterable { + + /** + * The arrayList where the JSONArray's properties are kept. + */ + private final ArrayList myArrayList; + + /** + * Construct an empty JSONArray. + */ + public JSONArray() { + this.myArrayList = new ArrayList(); + } + + /** + * Construct a JSONArray from a JSONTokener. + * + * @param x + * A JSONTokener + * @throws JSONException + * If there is a syntax error. + */ + public JSONArray(JSONTokener x) throws JSONException { + this(); + if (x.nextClean() != '[') { + throw x.syntaxError("A JSONArray text must start with '['"); + } + + char nextChar = x.nextClean(); + if (nextChar == 0) { + // array is unclosed. No ']' found, instead EOF + throw x.syntaxError("Expected a ',' or ']'"); + } + if (nextChar != ']') { + x.back(); + for (;;) { + if (x.nextClean() == ',') { + x.back(); + this.myArrayList.add(JSONObject.NULL); + } else { + x.back(); + this.myArrayList.add(x.nextValue()); + } + switch (x.nextClean()) { + case 0: + // array is unclosed. No ']' found, instead EOF + throw x.syntaxError("Expected a ',' or ']'"); + case ',': + nextChar = x.nextClean(); + if (nextChar == 0) { + // array is unclosed. No ']' found, instead EOF + throw x.syntaxError("Expected a ',' or ']'"); + } + if (nextChar == ']') { + return; + } + x.back(); + break; + case ']': + return; + default: + throw x.syntaxError("Expected a ',' or ']'"); + } + } + } + } + + /** + * Construct a JSONArray from a source JSON text. + * + * @param source + * A string that begins with [ (left + * bracket) and ends with ] + *  (right bracket). + * @throws JSONException + * If there is a syntax error. + */ + public JSONArray(String source) throws JSONException { + this(new JSONTokener(source)); + } + + /** + * Construct a JSONArray from a Collection. + * + * @param collection + * A Collection. + */ + public JSONArray(Collection collection) { + if (collection == null) { + this.myArrayList = new ArrayList(); + } else { + this.myArrayList = new ArrayList(collection.size()); + this.addAll(collection, true); + } + } + + /** + * Construct a JSONArray from an Iterable. This is a shallow copy. + * + * @param iter + * A Iterable collection. + */ + public JSONArray(Iterable iter) { + this(); + if (iter == null) { + return; + } + this.addAll(iter, true); + } + + /** + * Construct a JSONArray from another JSONArray. This is a shallow copy. + * + * @param array + * A array. + */ + public JSONArray(JSONArray array) { + if (array == null) { + this.myArrayList = new ArrayList(); + } else { + // shallow copy directly the internal array lists as any wrapping + // should have been done already in the original JSONArray + this.myArrayList = new ArrayList(array.myArrayList); + } + } + + /** + * Construct a JSONArray from an array. + * + * @param array + * Array. If the parameter passed is null, or not an array, an + * exception will be thrown. + * + * @throws JSONException + * If not an array or if an array value is non-finite number. + * @throws NullPointerException + * Thrown if the array parameter is null. + */ + public JSONArray(Object array) throws JSONException { + this(); + if (!array.getClass().isArray()) { + throw new JSONException( + "JSONArray initial value should be a string or collection or array."); + } + this.addAll(array, true); + } + + /** + * Construct a JSONArray with the specified initial capacity. + * + * @param initialCapacity + * the initial capacity of the JSONArray. + * @throws JSONException + * If the initial capacity is negative. + */ + public JSONArray(int initialCapacity) throws JSONException { + if (initialCapacity < 0) { + throw new JSONException( + "JSONArray initial capacity cannot be negative."); + } + this.myArrayList = new ArrayList(initialCapacity); + } + + @Override + public Iterator iterator() { + return this.myArrayList.iterator(); + } + + /** + * Get the object value associated with an index. + * + * @param index + * The index must be between 0 and length() - 1. + * @return An object value. + * @throws JSONException + * If there is no value for the index. + */ + public Object get(int index) throws JSONException { + Object object = this.opt(index); + if (object == null) { + throw new JSONException("JSONArray[" + index + "] not found."); + } + return object; + } + + /** + * Get the boolean value associated with an index. The string values "true" + * and "false" are converted to boolean. + * + * @param index + * The index must be between 0 and length() - 1. + * @return The truth. + * @throws JSONException + * If there is no value for the index or if the value is not + * convertible to boolean. + */ + public boolean getBoolean(int index) throws JSONException { + Object object = this.get(index); + if (object.equals(Boolean.FALSE) + || (object instanceof String && ((String) object) + .equalsIgnoreCase("false"))) { + return false; + } else if (object.equals(Boolean.TRUE) + || (object instanceof String && ((String) object) + .equalsIgnoreCase("true"))) { + return true; + } + throw wrongValueFormatException(index, "boolean", null); + } + + /** + * Get the double value associated with an index. + * + * @param index + * The index must be between 0 and length() - 1. + * @return The value. + * @throws JSONException + * If the key is not found or if the value cannot be converted + * to a number. + */ + public double getDouble(int index) throws JSONException { + final Object object = this.get(index); + if(object instanceof Number) { + return ((Number)object).doubleValue(); + } + try { + return Double.parseDouble(object.toString()); + } catch (Exception e) { + throw wrongValueFormatException(index, "double", e); + } + } + + /** + * Get the float value associated with a key. + * + * @param index + * The index must be between 0 and length() - 1. + * @return The numeric value. + * @throws JSONException + * if the key is not found or if the value is not a Number + * object and cannot be converted to a number. + */ + public float getFloat(int index) throws JSONException { + final Object object = this.get(index); + if(object instanceof Number) { + return ((Number)object).floatValue(); + } + try { + return Float.parseFloat(object.toString()); + } catch (Exception e) { + throw wrongValueFormatException(index, "float", e); + } + } + + /** + * Get the Number value associated with a key. + * + * @param index + * The index must be between 0 and length() - 1. + * @return The numeric value. + * @throws JSONException + * if the key is not found or if the value is not a Number + * object and cannot be converted to a number. + */ + public Number getNumber(int index) throws JSONException { + Object object = this.get(index); + try { + if (object instanceof Number) { + return (Number)object; + } + return JSONObject.stringToNumber(object.toString()); + } catch (Exception e) { + throw wrongValueFormatException(index, "number", e); + } + } + + /** + * Get the enum value associated with an index. + * + * @param + * Enum Type + * @param clazz + * The type of enum to retrieve. + * @param index + * The index must be between 0 and length() - 1. + * @return The enum value at the index location + * @throws JSONException + * if the key is not found or if the value cannot be converted + * to an enum. + */ + public > E getEnum(Class clazz, int index) throws JSONException { + E val = optEnum(clazz, index); + if(val==null) { + // JSONException should really take a throwable argument. + // If it did, I would re-implement this with the Enum.valueOf + // method and place any thrown exception in the JSONException + throw wrongValueFormatException(index, "enum of type " + + JSONObject.quote(clazz.getSimpleName()), null); + } + return val; + } + + /** + * Get the BigDecimal value associated with an index. If the value is float + * or double, the {@link BigDecimal#BigDecimal(double)} constructor + * will be used. See notes on the constructor for conversion issues that + * may arise. + * + * @param index + * The index must be between 0 and length() - 1. + * @return The value. + * @throws JSONException + * If the key is not found or if the value cannot be converted + * to a BigDecimal. + */ + public BigDecimal getBigDecimal (int index) throws JSONException { + Object object = this.get(index); + BigDecimal val = JSONObject.objectToBigDecimal(object, null); + if(val == null) { + throw wrongValueFormatException(index, "BigDecimal", object, null); + } + return val; + } + + /** + * Get the BigInteger value associated with an index. + * + * @param index + * The index must be between 0 and length() - 1. + * @return The value. + * @throws JSONException + * If the key is not found or if the value cannot be converted + * to a BigInteger. + */ + public BigInteger getBigInteger (int index) throws JSONException { + Object object = this.get(index); + BigInteger val = JSONObject.objectToBigInteger(object, null); + if(val == null) { + throw wrongValueFormatException(index, "BigInteger", object, null); + } + return val; + } + + /** + * Get the int value associated with an index. + * + * @param index + * The index must be between 0 and length() - 1. + * @return The value. + * @throws JSONException + * If the key is not found or if the value is not a number. + */ + public int getInt(int index) throws JSONException { + final Object object = this.get(index); + if(object instanceof Number) { + return ((Number)object).intValue(); + } + try { + return Integer.parseInt(object.toString()); + } catch (Exception e) { + throw wrongValueFormatException(index, "int", e); + } + } + + /** + * Get the JSONArray associated with an index. + * + * @param index + * The index must be between 0 and length() - 1. + * @return A JSONArray value. + * @throws JSONException + * If there is no value for the index. or if the value is not a + * JSONArray + */ + public JSONArray getJSONArray(int index) throws JSONException { + Object object = this.get(index); + if (object instanceof JSONArray) { + return (JSONArray) object; + } + throw wrongValueFormatException(index, "JSONArray", null); + } + + /** + * Get the JSONObject associated with an index. + * + * @param index + * subscript + * @return A JSONObject value. + * @throws JSONException + * If there is no value for the index or if the value is not a + * JSONObject + */ + public JSONObject getJSONObject(int index) throws JSONException { + Object object = this.get(index); + if (object instanceof JSONObject) { + return (JSONObject) object; + } + throw wrongValueFormatException(index, "JSONObject", null); + } + + /** + * Get the long value associated with an index. + * + * @param index + * The index must be between 0 and length() - 1. + * @return The value. + * @throws JSONException + * If the key is not found or if the value cannot be converted + * to a number. + */ + public long getLong(int index) throws JSONException { + final Object object = this.get(index); + if(object instanceof Number) { + return ((Number)object).longValue(); + } + try { + return Long.parseLong(object.toString()); + } catch (Exception e) { + throw wrongValueFormatException(index, "long", e); + } + } + + /** + * Get the string associated with an index. + * + * @param index + * The index must be between 0 and length() - 1. + * @return A string value. + * @throws JSONException + * If there is no string value for the index. + */ + public String getString(int index) throws JSONException { + Object object = this.get(index); + if (object instanceof String) { + return (String) object; + } + throw wrongValueFormatException(index, "String", null); + } + + /** + * Determine if the value is null. + * + * @param index + * The index must be between 0 and length() - 1. + * @return true if the value at the index is null, or if there is no value. + */ + public boolean isNull(int index) { + return JSONObject.NULL.equals(this.opt(index)); + } + + /** + * Make a string from the contents of this JSONArray. The + * separator string is inserted between each element. Warning: + * This method assumes that the data structure is acyclical. + * + * @param separator + * A string that will be inserted between the elements. + * @return a string. + * @throws JSONException + * If the array contains an invalid number. + */ + public String join(String separator) throws JSONException { + int len = this.length(); + if (len == 0) { + return ""; + } + + StringBuilder sb = new StringBuilder( + JSONObject.valueToString(this.myArrayList.get(0))); + + for (int i = 1; i < len; i++) { + sb.append(separator) + .append(JSONObject.valueToString(this.myArrayList.get(i))); + } + return sb.toString(); + } + + /** + * Get the number of elements in the JSONArray, included nulls. + * + * @return The length (or size). + */ + public int length() { + return this.myArrayList.size(); + } + + /** + * Removes all of the elements from this JSONArray. + * The JSONArray will be empty after this call returns. + */ + public void clear() { + this.myArrayList.clear(); + } + + /** + * Get the optional object value associated with an index. + * + * @param index + * The index must be between 0 and length() - 1. If not, null is returned. + * @return An object value, or null if there is no object at that index. + */ + public Object opt(int index) { + return (index < 0 || index >= this.length()) ? null : this.myArrayList + .get(index); + } + + /** + * Get the optional boolean value associated with an index. It returns false + * if there is no value at that index, or if the value is not Boolean.TRUE + * or the String "true". + * + * @param index + * The index must be between 0 and length() - 1. + * @return The truth. + */ + public boolean optBoolean(int index) { + return this.optBoolean(index, false); + } + + /** + * Get the optional boolean value associated with an index. It returns the + * defaultValue if there is no value at that index or if it is not a Boolean + * or the String "true" or "false" (case insensitive). + * + * @param index + * The index must be between 0 and length() - 1. + * @param defaultValue + * A boolean default. + * @return The truth. + */ + public boolean optBoolean(int index, boolean defaultValue) { + try { + return this.getBoolean(index); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * Get the optional double value associated with an index. NaN is returned + * if there is no value for the index, or if the value is not a number and + * cannot be converted to a number. + * + * @param index + * The index must be between 0 and length() - 1. + * @return The value. + */ + public double optDouble(int index) { + return this.optDouble(index, Double.NaN); + } + + /** + * Get the optional double value associated with an index. The defaultValue + * is returned if there is no value for the index, or if the value is not a + * number and cannot be converted to a number. + * + * @param index + * subscript + * @param defaultValue + * The default value. + * @return The value. + */ + public double optDouble(int index, double defaultValue) { + final Number val = this.optNumber(index, null); + if (val == null) { + return defaultValue; + } + final double doubleValue = val.doubleValue(); + // if (Double.isNaN(doubleValue) || Double.isInfinite(doubleValue)) { + // return defaultValue; + // } + return doubleValue; + } + + /** + * Get the optional float value associated with an index. NaN is returned + * if there is no value for the index, or if the value is not a number and + * cannot be converted to a number. + * + * @param index + * The index must be between 0 and length() - 1. + * @return The value. + */ + public float optFloat(int index) { + return this.optFloat(index, Float.NaN); + } + + /** + * Get the optional float value associated with an index. The defaultValue + * is returned if there is no value for the index, or if the value is not a + * number and cannot be converted to a number. + * + * @param index + * subscript + * @param defaultValue + * The default value. + * @return The value. + */ + public float optFloat(int index, float defaultValue) { + final Number val = this.optNumber(index, null); + if (val == null) { + return defaultValue; + } + final float floatValue = val.floatValue(); + // if (Float.isNaN(floatValue) || Float.isInfinite(floatValue)) { + // return floatValue; + // } + return floatValue; + } + + /** + * Get the optional int value associated with an index. Zero is returned if + * there is no value for the index, or if the value is not a number and + * cannot be converted to a number. + * + * @param index + * The index must be between 0 and length() - 1. + * @return The value. + */ + public int optInt(int index) { + return this.optInt(index, 0); + } + + /** + * Get the optional int value associated with an index. The defaultValue is + * returned if there is no value for the index, or if the value is not a + * number and cannot be converted to a number. + * + * @param index + * The index must be between 0 and length() - 1. + * @param defaultValue + * The default value. + * @return The value. + */ + public int optInt(int index, int defaultValue) { + final Number val = this.optNumber(index, null); + if (val == null) { + return defaultValue; + } + return val.intValue(); + } + + /** + * Get the enum value associated with a key. + * + * @param + * Enum Type + * @param clazz + * The type of enum to retrieve. + * @param index + * The index must be between 0 and length() - 1. + * @return The enum value at the index location or null if not found + */ + public > E optEnum(Class clazz, int index) { + return this.optEnum(clazz, index, null); + } + + /** + * Get the enum value associated with a key. + * + * @param + * Enum Type + * @param clazz + * The type of enum to retrieve. + * @param index + * The index must be between 0 and length() - 1. + * @param defaultValue + * The default in case the value is not found + * @return The enum value at the index location or defaultValue if + * the value is not found or cannot be assigned to clazz + */ + public > E optEnum(Class clazz, int index, E defaultValue) { + try { + Object val = this.opt(index); + if (JSONObject.NULL.equals(val)) { + return defaultValue; + } + if (clazz.isAssignableFrom(val.getClass())) { + // we just checked it! + @SuppressWarnings("unchecked") + E myE = (E) val; + return myE; + } + return Enum.valueOf(clazz, val.toString()); + } catch (IllegalArgumentException e) { + return defaultValue; + } catch (NullPointerException e) { + return defaultValue; + } + } + + /** + * Get the optional BigInteger value associated with an index. The + * defaultValue is returned if there is no value for the index, or if the + * value is not a number and cannot be converted to a number. + * + * @param index + * The index must be between 0 and length() - 1. + * @param defaultValue + * The default value. + * @return The value. + */ + public BigInteger optBigInteger(int index, BigInteger defaultValue) { + Object val = this.opt(index); + return JSONObject.objectToBigInteger(val, defaultValue); + } + + /** + * Get the optional BigDecimal value associated with an index. The + * defaultValue is returned if there is no value for the index, or if the + * value is not a number and cannot be converted to a number. If the value + * is float or double, the {@link BigDecimal#BigDecimal(double)} + * constructor will be used. See notes on the constructor for conversion + * issues that may arise. + * + * @param index + * The index must be between 0 and length() - 1. + * @param defaultValue + * The default value. + * @return The value. + */ + public BigDecimal optBigDecimal(int index, BigDecimal defaultValue) { + Object val = this.opt(index); + return JSONObject.objectToBigDecimal(val, defaultValue); + } + + /** + * Get the optional JSONArray associated with an index. + * + * @param index + * subscript + * @return A JSONArray value, or null if the index has no value, or if the + * value is not a JSONArray. + */ + public JSONArray optJSONArray(int index) { + Object o = this.opt(index); + return o instanceof JSONArray ? (JSONArray) o : null; + } + + /** + * Get the optional JSONObject associated with an index. Null is returned if + * the key is not found, or null if the index has no value, or if the value + * is not a JSONObject. + * + * @param index + * The index must be between 0 and length() - 1. + * @return A JSONObject value. + */ + public JSONObject optJSONObject(int index) { + Object o = this.opt(index); + return o instanceof JSONObject ? (JSONObject) o : null; + } + + /** + * Get the optional long value associated with an index. Zero is returned if + * there is no value for the index, or if the value is not a number and + * cannot be converted to a number. + * + * @param index + * The index must be between 0 and length() - 1. + * @return The value. + */ + public long optLong(int index) { + return this.optLong(index, 0); + } + + /** + * Get the optional long value associated with an index. The defaultValue is + * returned if there is no value for the index, or if the value is not a + * number and cannot be converted to a number. + * + * @param index + * The index must be between 0 and length() - 1. + * @param defaultValue + * The default value. + * @return The value. + */ + public long optLong(int index, long defaultValue) { + final Number val = this.optNumber(index, null); + if (val == null) { + return defaultValue; + } + return val.longValue(); + } + + /** + * Get an optional {@link Number} value associated with a key, or null + * if there is no such key or if the value is not a number. If the value is a string, + * an attempt will be made to evaluate it as a number ({@link BigDecimal}). This method + * would be used in cases where type coercion of the number value is unwanted. + * + * @param index + * The index must be between 0 and length() - 1. + * @return An object which is the value. + */ + public Number optNumber(int index) { + return this.optNumber(index, null); + } + + /** + * Get an optional {@link Number} value associated with a key, or the default if there + * is no such key or if the value is not a number. If the value is a string, + * an attempt will be made to evaluate it as a number ({@link BigDecimal}). This method + * would be used in cases where type coercion of the number value is unwanted. + * + * @param index + * The index must be between 0 and length() - 1. + * @param defaultValue + * The default. + * @return An object which is the value. + */ + public Number optNumber(int index, Number defaultValue) { + Object val = this.opt(index); + if (JSONObject.NULL.equals(val)) { + return defaultValue; + } + if (val instanceof Number){ + return (Number) val; + } + + if (val instanceof String) { + try { + return JSONObject.stringToNumber((String) val); + } catch (Exception e) { + return defaultValue; + } + } + return defaultValue; + } + + /** + * Get the optional string value associated with an index. It returns an + * empty string if there is no value at that index. If the value is not a + * string and is not null, then it is converted to a string. + * + * @param index + * The index must be between 0 and length() - 1. + * @return A String value. + */ + public String optString(int index) { + return this.optString(index, ""); + } + + /** + * Get the optional string associated with an index. The defaultValue is + * returned if the key is not found. + * + * @param index + * The index must be between 0 and length() - 1. + * @param defaultValue + * The default value. + * @return A String value. + */ + public String optString(int index, String defaultValue) { + Object object = this.opt(index); + return JSONObject.NULL.equals(object) ? defaultValue : object + .toString(); + } + + /** + * Append a boolean value. This increases the array's length by one. + * + * @param value + * A boolean value. + * @return this. + */ + public JSONArray put(boolean value) { + return this.put(value ? Boolean.TRUE : Boolean.FALSE); + } + + /** + * Put a value in the JSONArray, where the value will be a JSONArray which + * is produced from a Collection. + * + * @param value + * A Collection value. + * @return this. + * @throws JSONException + * If the value is non-finite number. + */ + public JSONArray put(Collection value) { + return this.put(new JSONArray(value)); + } + + /** + * Append a double value. This increases the array's length by one. + * + * @param value + * A double value. + * @return this. + * @throws JSONException + * if the value is not finite. + */ + public JSONArray put(double value) throws JSONException { + return this.put(Double.valueOf(value)); + } + + /** + * Append a float value. This increases the array's length by one. + * + * @param value + * A float value. + * @return this. + * @throws JSONException + * if the value is not finite. + */ + public JSONArray put(float value) throws JSONException { + return this.put(Float.valueOf(value)); + } + + /** + * Append an int value. This increases the array's length by one. + * + * @param value + * An int value. + * @return this. + */ + public JSONArray put(int value) { + return this.put(Integer.valueOf(value)); + } + + /** + * Append an long value. This increases the array's length by one. + * + * @param value + * A long value. + * @return this. + */ + public JSONArray put(long value) { + return this.put(Long.valueOf(value)); + } + + /** + * Put a value in the JSONArray, where the value will be a JSONObject which + * is produced from a Map. + * + * @param value + * A Map value. + * @return this. + * @throws JSONException + * If a value in the map is non-finite number. + * @throws NullPointerException + * If a key in the map is null + */ + public JSONArray put(Map value) { + return this.put(new JSONObject(value)); + } + + /** + * Append an object value. This increases the array's length by one. + * + * @param value + * An object value. The value should be a Boolean, Double, + * Integer, JSONArray, JSONObject, Long, or String, or the + * JSONObject.NULL object. + * @return this. + * @throws JSONException + * If the value is non-finite number. + */ + public JSONArray put(Object value) { + JSONObject.testValidity(value); + this.myArrayList.add(value); + return this; + } + + /** + * Put or replace a boolean value in the JSONArray. If the index is greater + * than the length of the JSONArray, then null elements will be added as + * necessary to pad it out. + * + * @param index + * The subscript. + * @param value + * A boolean value. + * @return this. + * @throws JSONException + * If the index is negative. + */ + public JSONArray put(int index, boolean value) throws JSONException { + return this.put(index, value ? Boolean.TRUE : Boolean.FALSE); + } + + /** + * Put a value in the JSONArray, where the value will be a JSONArray which + * is produced from a Collection. + * + * @param index + * The subscript. + * @param value + * A Collection value. + * @return this. + * @throws JSONException + * If the index is negative or if the value is non-finite. + */ + public JSONArray put(int index, Collection value) throws JSONException { + return this.put(index, new JSONArray(value)); + } + + /** + * Put or replace a double value. If the index is greater than the length of + * the JSONArray, then null elements will be added as necessary to pad it + * out. + * + * @param index + * The subscript. + * @param value + * A double value. + * @return this. + * @throws JSONException + * If the index is negative or if the value is non-finite. + */ + public JSONArray put(int index, double value) throws JSONException { + return this.put(index, Double.valueOf(value)); + } + + /** + * Put or replace a float value. If the index is greater than the length of + * the JSONArray, then null elements will be added as necessary to pad it + * out. + * + * @param index + * The subscript. + * @param value + * A float value. + * @return this. + * @throws JSONException + * If the index is negative or if the value is non-finite. + */ + public JSONArray put(int index, float value) throws JSONException { + return this.put(index, Float.valueOf(value)); + } + + /** + * Put or replace an int value. If the index is greater than the length of + * the JSONArray, then null elements will be added as necessary to pad it + * out. + * + * @param index + * The subscript. + * @param value + * An int value. + * @return this. + * @throws JSONException + * If the index is negative. + */ + public JSONArray put(int index, int value) throws JSONException { + return this.put(index, Integer.valueOf(value)); + } + + /** + * Put or replace a long value. If the index is greater than the length of + * the JSONArray, then null elements will be added as necessary to pad it + * out. + * + * @param index + * The subscript. + * @param value + * A long value. + * @return this. + * @throws JSONException + * If the index is negative. + */ + public JSONArray put(int index, long value) throws JSONException { + return this.put(index, Long.valueOf(value)); + } + + /** + * Put a value in the JSONArray, where the value will be a JSONObject that + * is produced from a Map. + * + * @param index + * The subscript. + * @param value + * The Map value. + * @return this. + * @throws JSONException + * If the index is negative or if the value is an invalid + * number. + * @throws NullPointerException + * If a key in the map is null + */ + public JSONArray put(int index, Map value) throws JSONException { + this.put(index, new JSONObject(value)); + return this; + } + + /** + * Put or replace an object value in the JSONArray. If the index is greater + * than the length of the JSONArray, then null elements will be added as + * necessary to pad it out. + * + * @param index + * The subscript. + * @param value + * The value to put into the array. The value should be a + * Boolean, Double, Integer, JSONArray, JSONObject, Long, or + * String, or the JSONObject.NULL object. + * @return this. + * @throws JSONException + * If the index is negative or if the value is an invalid + * number. + */ + public JSONArray put(int index, Object value) throws JSONException { + if (index < 0) { + throw new JSONException("JSONArray[" + index + "] not found."); + } + if (index < this.length()) { + JSONObject.testValidity(value); + this.myArrayList.set(index, value); + return this; + } + if(index == this.length()){ + // simple append + return this.put(value); + } + // if we are inserting past the length, we want to grow the array all at once + // instead of incrementally. + this.myArrayList.ensureCapacity(index + 1); + while (index != this.length()) { + // we don't need to test validity of NULL objects + this.myArrayList.add(JSONObject.NULL); + } + return this.put(value); + } + + /** + * Put a collection's elements in to the JSONArray. + * + * @param collection + * A Collection. + * @return this. + */ + public JSONArray putAll(Collection collection) { + this.addAll(collection, false); + return this; + } + + /** + * Put an Iterable's elements in to the JSONArray. + * + * @param iter + * An Iterable. + * @return this. + */ + public JSONArray putAll(Iterable iter) { + this.addAll(iter, false); + return this; + } + + /** + * Put a JSONArray's elements in to the JSONArray. + * + * @param array + * A JSONArray. + * @return this. + */ + public JSONArray putAll(JSONArray array) { + // directly copy the elements from the source array to this one + // as all wrapping should have been done already in the source. + this.myArrayList.addAll(array.myArrayList); + return this; + } + + /** + * Put an array's elements in to the JSONArray. + * + * @param array + * Array. If the parameter passed is null, or not an array or Iterable, an + * exception will be thrown. + * @return this. + * + * @throws JSONException + * If not an array, JSONArray, Iterable or if an value is non-finite number. + * @throws NullPointerException + * Thrown if the array parameter is null. + */ + public JSONArray putAll(Object array) throws JSONException { + this.addAll(array, false); + return this; + } + + /** + * Creates a JSONPointer using an initialization string and tries to + * match it to an item within this JSONArray. For example, given a + * JSONArray initialized with this document: + *
+     * [
+     *     {"b":"c"}
+     * ]
+     * 
+ * and this JSONPointer string: + *
+     * "/0/b"
+     * 
+ * Then this method will return the String "c" + * A JSONPointerException may be thrown from code called by this method. + * + * @param jsonPointer string that can be used to create a JSONPointer + * @return the item matched by the JSONPointer, otherwise null + */ + public Object query(String jsonPointer) { + return query(new JSONPointer(jsonPointer)); + } + + /** + * Uses a user initialized JSONPointer and tries to + * match it to an item within this JSONArray. For example, given a + * JSONArray initialized with this document: + *
+     * [
+     *     {"b":"c"}
+     * ]
+     * 
+ * and this JSONPointer: + *
+     * "/0/b"
+     * 
+ * Then this method will return the String "c" + * A JSONPointerException may be thrown from code called by this method. + * + * @param jsonPointer string that can be used to create a JSONPointer + * @return the item matched by the JSONPointer, otherwise null + */ + public Object query(JSONPointer jsonPointer) { + return jsonPointer.queryFrom(this); + } + + /** + * Queries and returns a value from this object using {@code jsonPointer}, or + * returns null if the query fails due to a missing key. + * + * @param jsonPointer the string representation of the JSON pointer + * @return the queried value or {@code null} + * @throws IllegalArgumentException if {@code jsonPointer} has invalid syntax + */ + public Object optQuery(String jsonPointer) { + return optQuery(new JSONPointer(jsonPointer)); + } + + /** + * Queries and returns a value from this object using {@code jsonPointer}, or + * returns null if the query fails due to a missing key. + * + * @param jsonPointer The JSON pointer + * @return the queried value or {@code null} + * @throws IllegalArgumentException if {@code jsonPointer} has invalid syntax + */ + public Object optQuery(JSONPointer jsonPointer) { + try { + return jsonPointer.queryFrom(this); + } catch (JSONPointerException e) { + return null; + } + } + + /** + * Remove an index and close the hole. + * + * @param index + * The index of the element to be removed. + * @return The value that was associated with the index, or null if there + * was no value. + */ + public Object remove(int index) { + return index >= 0 && index < this.length() + ? this.myArrayList.remove(index) + : null; + } + + /** + * Determine if two JSONArrays are similar. + * They must contain similar sequences. + * + * @param other The other JSONArray + * @return true if they are equal + */ + public boolean similar(Object other) { + if (!(other instanceof JSONArray)) { + return false; + } + int len = this.length(); + if (len != ((JSONArray)other).length()) { + return false; + } + for (int i = 0; i < len; i += 1) { + Object valueThis = this.myArrayList.get(i); + Object valueOther = ((JSONArray)other).myArrayList.get(i); + if(valueThis == valueOther) { + continue; + } + if(valueThis == null) { + return false; + } + if (valueThis instanceof JSONObject) { + if (!((JSONObject)valueThis).similar(valueOther)) { + return false; + } + } else if (valueThis instanceof JSONArray) { + if (!((JSONArray)valueThis).similar(valueOther)) { + return false; + } + } else if (valueThis instanceof Number && valueOther instanceof Number) { + if (!JSONObject.isNumberSimilar((Number)valueThis, (Number)valueOther)) { + return false; + } + } else if (!valueThis.equals(valueOther)) { + return false; + } + } + return true; + } + + /** + * Produce a JSONObject by combining a JSONArray of names with the values of + * this JSONArray. + * + * @param names + * A JSONArray containing a list of key strings. These will be + * paired with the values. + * @return A JSONObject, or null if there are no names or if this JSONArray + * has no values. + * @throws JSONException + * If any of the names are null. + */ + public JSONObject toJSONObject(JSONArray names) throws JSONException { + if (names == null || names.isEmpty() || this.isEmpty()) { + return null; + } + JSONObject jo = new JSONObject(names.length()); + for (int i = 0; i < names.length(); i += 1) { + jo.put(names.getString(i), this.opt(i)); + } + return jo; + } + + /** + * Make a JSON text of this JSONArray. For compactness, no unnecessary + * whitespace is added. If it is not possible to produce a syntactically + * correct JSON text then null will be returned instead. This could occur if + * the array contains an invalid number. + *

+ * Warning: This method assumes that the data structure is acyclical. + * + * + * @return a printable, displayable, transmittable representation of the + * array. + */ + @Override + public String toString() { + try { + return this.toString(0); + } catch (Exception e) { + return null; + } + } + + /** + * Make a pretty-printed JSON text of this JSONArray. + * + *

If

 {@code indentFactor > 0}
and the {@link JSONArray} has only + * one element, then the array will be output on a single line: + *
{@code [1]}
+ * + *

If an array has 2 or more elements, then it will be output across + * multiple lines:

{@code
+     * [
+     * 1,
+     * "value 2",
+     * 3
+     * ]
+     * }
+ *

+ * Warning: This method assumes that the data structure is acyclical. + * + * + * @param indentFactor + * The number of spaces to add to each level of indentation. + * @return a printable, displayable, transmittable representation of the + * object, beginning with [ (left + * bracket) and ending with ] + *  (right bracket). + * @throws JSONException if a called function fails + */ + public String toString(int indentFactor) throws JSONException { + StringWriter sw = new StringWriter(); + synchronized (sw.getBuffer()) { + return this.write(sw, indentFactor, 0).toString(); + } + } + + /** + * Write the contents of the JSONArray as JSON text to a writer. For + * compactness, no whitespace is added. + *

+ * Warning: This method assumes that the data structure is acyclical. + * + * @param writer the writer object + * @return The writer. + * @throws JSONException if a called function fails + */ + public Writer write(Writer writer) throws JSONException { + return this.write(writer, 0, 0); + } + + /** + * Write the contents of the JSONArray as JSON text to a writer. + * + *

If

{@code indentFactor > 0}
and the {@link JSONArray} has only + * one element, then the array will be output on a single line: + *
{@code [1]}
+ * + *

If an array has 2 or more elements, then it will be output across + * multiple lines:

{@code
+     * [
+     * 1,
+     * "value 2",
+     * 3
+     * ]
+     * }
+ *

+ * Warning: This method assumes that the data structure is acyclical. + * + * + * @param writer + * Writes the serialized JSON + * @param indentFactor + * The number of spaces to add to each level of indentation. + * @param indent + * The indentation of the top level. + * @return The writer. + * @throws JSONException if a called function fails or unable to write + */ + public Writer write(Writer writer, int indentFactor, int indent) + throws JSONException { + try { + boolean needsComma = false; + int length = this.length(); + writer.write('['); + + if (length == 1) { + try { + JSONObject.writeValue(writer, this.myArrayList.get(0), + indentFactor, indent); + } catch (Exception e) { + throw new JSONException("Unable to write JSONArray value at index: 0", e); + } + } else if (length != 0) { + final int newIndent = indent + indentFactor; + + for (int i = 0; i < length; i += 1) { + if (needsComma) { + writer.write(','); + } + if (indentFactor > 0) { + writer.write('\n'); + } + JSONObject.indent(writer, newIndent); + try { + JSONObject.writeValue(writer, this.myArrayList.get(i), + indentFactor, newIndent); + } catch (Exception e) { + throw new JSONException("Unable to write JSONArray value at index: " + i, e); + } + needsComma = true; + } + if (indentFactor > 0) { + writer.write('\n'); + } + JSONObject.indent(writer, indent); + } + writer.write(']'); + return writer; + } catch (IOException e) { + throw new JSONException(e); + } + } + + /** + * Returns a java.util.List containing all of the elements in this array. + * If an element in the array is a JSONArray or JSONObject it will also + * be converted to a List and a Map respectively. + *

+ * Warning: This method assumes that the data structure is acyclical. + * + * @return a java.util.List containing the elements of this array + */ + public List toList() { + List results = new ArrayList(this.myArrayList.size()); + for (Object element : this.myArrayList) { + if (element == null || JSONObject.NULL.equals(element)) { + results.add(null); + } else if (element instanceof JSONArray) { + results.add(((JSONArray) element).toList()); + } else if (element instanceof JSONObject) { + results.add(((JSONObject) element).toMap()); + } else { + results.add(element); + } + } + return results; + } + + /** + * Check if JSONArray is empty. + * + * @return true if JSONArray is empty, otherwise false. + */ + public boolean isEmpty() { + return this.myArrayList.isEmpty(); + } + + /** + * Add a collection's elements to the JSONArray. + * + * @param collection + * A Collection. + * @param wrap + * {@code true} to call {@link JSONObject#wrap(Object)} for each item, + * {@code false} to add the items directly + * + */ + private void addAll(Collection collection, boolean wrap) { + this.myArrayList.ensureCapacity(this.myArrayList.size() + collection.size()); + if (wrap) { + for (Object o: collection){ + this.put(JSONObject.wrap(o)); + } + } else { + for (Object o: collection){ + this.put(o); + } + } + } + + /** + * Add an Iterable's elements to the JSONArray. + * + * @param iter + * An Iterable. + * @param wrap + * {@code true} to call {@link JSONObject#wrap(Object)} for each item, + * {@code false} to add the items directly + */ + private void addAll(Iterable iter, boolean wrap) { + if (wrap) { + for (Object o: iter){ + this.put(JSONObject.wrap(o)); + } + } else { + for (Object o: iter){ + this.put(o); + } + } + } + + /** + * Add an array's elements to the JSONArray. + * + * @param array + * Array. If the parameter passed is null, or not an array, + * JSONArray, Collection, or Iterable, an exception will be + * thrown. + * @param wrap + * {@code true} to call {@link JSONObject#wrap(Object)} for each item, + * {@code false} to add the items directly + * + * @throws JSONException + * If not an array or if an array value is non-finite number. + * @throws NullPointerException + * Thrown if the array parameter is null. + */ + private void addAll(Object array, boolean wrap) throws JSONException { + if (array.getClass().isArray()) { + int length = Array.getLength(array); + this.myArrayList.ensureCapacity(this.myArrayList.size() + length); + if (wrap) { + for (int i = 0; i < length; i += 1) { + this.put(JSONObject.wrap(Array.get(array, i))); + } + } else { + for (int i = 0; i < length; i += 1) { + this.put(Array.get(array, i)); + } + } + } else if (array instanceof JSONArray) { + // use the built in array list `addAll` as all object + // wrapping should have been completed in the original + // JSONArray + this.myArrayList.addAll(((JSONArray)array).myArrayList); + } else if (array instanceof Collection) { + this.addAll((Collection)array, wrap); + } else if (array instanceof Iterable) { + this.addAll((Iterable)array, wrap); + } else { + throw new JSONException( + "JSONArray initial value should be a string or collection or array."); + } + } + + /** + * Create a new JSONException in a common format for incorrect conversions. + * @param idx index of the item + * @param valueType the type of value being coerced to + * @param cause optional cause of the coercion failure + * @return JSONException that can be thrown. + */ + private static JSONException wrongValueFormatException( + int idx, + String valueType, + Throwable cause) { + return new JSONException( + "JSONArray[" + idx + "] is not a " + valueType + "." + , cause); + } + + /** + * Create a new JSONException in a common format for incorrect conversions. + * @param idx index of the item + * @param valueType the type of value being coerced to + * @param cause optional cause of the coercion failure + * @return JSONException that can be thrown. + */ + private static JSONException wrongValueFormatException( + int idx, + String valueType, + Object value, + Throwable cause) { + return new JSONException( + "JSONArray[" + idx + "] is not a " + valueType + " (" + value + ")." + , cause); + } + +} diff --git a/src/main/java/org/json/JSONException.java b/src/main/java/org/json/JSONException.java new file mode 100644 index 0000000..ab7ff77 --- /dev/null +++ b/src/main/java/org/json/JSONException.java @@ -0,0 +1,69 @@ +package org.json; + +/* +Copyright (c) 2002 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ + +/** + * The JSONException is thrown by the JSON.org classes when things are amiss. + * + * @author JSON.org + * @version 2015-12-09 + */ +public class JSONException extends RuntimeException { + /** Serialization ID */ + private static final long serialVersionUID = 0; + + /** + * Constructs a JSONException with an explanatory message. + * + * @param message + * Detail about the reason for the exception. + */ + public JSONException(final String message) { + super(message); + } + + /** + * Constructs a JSONException with an explanatory message and cause. + * + * @param message + * Detail about the reason for the exception. + * @param cause + * The cause. + */ + public JSONException(final String message, final Throwable cause) { + super(message, cause); + } + + /** + * Constructs a new JSONException with the specified cause. + * + * @param cause + * The cause. + */ + public JSONException(final Throwable cause) { + super(cause.getMessage(), cause); + } + +} diff --git a/src/main/java/org/json/JSONML.java b/src/main/java/org/json/JSONML.java new file mode 100644 index 0000000..aafdf72 --- /dev/null +++ b/src/main/java/org/json/JSONML.java @@ -0,0 +1,542 @@ +package org.json; + +/* +Copyright (c) 2008 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +/** + * This provides static methods to convert an XML text into a JSONArray or + * JSONObject, and to covert a JSONArray or JSONObject into an XML text using + * the JsonML transform. + * + * @author JSON.org + * @version 2016-01-30 + */ +public class JSONML { + /** + * Parse XML values and store them in a JSONArray. + * @param x The XMLTokener containing the source string. + * @param arrayForm true if array form, false if object form. + * @param ja The JSONArray that is containing the current tag or null + * if we are at the outermost level. + * @param keepStrings Don't type-convert text nodes and attribute values + * @return A JSONArray if the value is the outermost tag, otherwise null. + * @throws JSONException if a parsing error occurs + */ + private static Object parse( + XMLTokener x, + boolean arrayForm, + JSONArray ja, + boolean keepStrings + ) throws JSONException { + String attribute; + char c; + String closeTag = null; + int i; + JSONArray newja = null; + JSONObject newjo = null; + Object token; + String tagName = null; + +// Test for and skip past these forms: +// +// +// +// + + while (true) { + if (!x.more()) { + throw x.syntaxError("Bad XML"); + } + token = x.nextContent(); + if (token == XML.LT) { + token = x.nextToken(); + if (token instanceof Character) { + if (token == XML.SLASH) { + +// Close tag "); + } else { + x.back(); + } + } else if (c == '[') { + token = x.nextToken(); + if (token.equals("CDATA") && x.next() == '[') { + if (ja != null) { + ja.put(x.nextCDATA()); + } + } else { + throw x.syntaxError("Expected 'CDATA['"); + } + } else { + i = 1; + do { + token = x.nextMeta(); + if (token == null) { + throw x.syntaxError("Missing '>' after ' 0); + } + } else if (token == XML.QUEST) { + +// "); + } else { + throw x.syntaxError("Misshaped tag"); + } + +// Open tag < + + } else { + if (!(token instanceof String)) { + throw x.syntaxError("Bad tagName '" + token + "'."); + } + tagName = (String)token; + newja = new JSONArray(); + newjo = new JSONObject(); + if (arrayForm) { + newja.put(tagName); + if (ja != null) { + ja.put(newja); + } + } else { + newjo.put("tagName", tagName); + if (ja != null) { + ja.put(newjo); + } + } + token = null; + for (;;) { + if (token == null) { + token = x.nextToken(); + } + if (token == null) { + throw x.syntaxError("Misshaped tag"); + } + if (!(token instanceof String)) { + break; + } + +// attribute = value + + attribute = (String)token; + if (!arrayForm && ("tagName".equals(attribute) || "childNode".equals(attribute))) { + throw x.syntaxError("Reserved attribute."); + } + token = x.nextToken(); + if (token == XML.EQ) { + token = x.nextToken(); + if (!(token instanceof String)) { + throw x.syntaxError("Missing value"); + } + newjo.accumulate(attribute, keepStrings ? ((String)token) :XML.stringToValue((String)token)); + token = null; + } else { + newjo.accumulate(attribute, ""); + } + } + if (arrayForm && newjo.length() > 0) { + newja.put(newjo); + } + +// Empty tag <.../> + + if (token == XML.SLASH) { + if (x.nextToken() != XML.GT) { + throw x.syntaxError("Misshaped tag"); + } + if (ja == null) { + if (arrayForm) { + return newja; + } + return newjo; + } + +// Content, between <...> and + + } else { + if (token != XML.GT) { + throw x.syntaxError("Misshaped tag"); + } + closeTag = (String)parse(x, arrayForm, newja, keepStrings); + if (closeTag != null) { + if (!closeTag.equals(tagName)) { + throw x.syntaxError("Mismatched '" + tagName + + "' and '" + closeTag + "'"); + } + tagName = null; + if (!arrayForm && newja.length() > 0) { + newjo.put("childNodes", newja); + } + if (ja == null) { + if (arrayForm) { + return newja; + } + return newjo; + } + } + } + } + } else { + if (ja != null) { + ja.put(token instanceof String + ? keepStrings ? XML.unescape((String)token) :XML.stringToValue((String)token) + : token); + } + } + } + } + + + /** + * Convert a well-formed (but not necessarily valid) XML string into a + * JSONArray using the JsonML transform. Each XML tag is represented as + * a JSONArray in which the first element is the tag name. If the tag has + * attributes, then the second element will be JSONObject containing the + * name/value pairs. If the tag contains children, then strings and + * JSONArrays will represent the child tags. + * Comments, prologs, DTDs, and
{@code <[ [ ]]>}
are ignored. + * @param string The source string. + * @return A JSONArray containing the structured data from the XML string. + * @throws JSONException Thrown on error converting to a JSONArray + */ + public static JSONArray toJSONArray(String string) throws JSONException { + return (JSONArray)parse(new XMLTokener(string), true, null, false); + } + + + /** + * Convert a well-formed (but not necessarily valid) XML string into a + * JSONArray using the JsonML transform. Each XML tag is represented as + * a JSONArray in which the first element is the tag name. If the tag has + * attributes, then the second element will be JSONObject containing the + * name/value pairs. If the tag contains children, then strings and + * JSONArrays will represent the child tags. + * As opposed to toJSONArray this method does not attempt to convert + * any text node or attribute value to any type + * but just leaves it as a string. + * Comments, prologs, DTDs, and
{@code <[ [ ]]>}
are ignored. + * @param string The source string. + * @param keepStrings If true, then values will not be coerced into boolean + * or numeric values and will instead be left as strings + * @return A JSONArray containing the structured data from the XML string. + * @throws JSONException Thrown on error converting to a JSONArray + */ + public static JSONArray toJSONArray(String string, boolean keepStrings) throws JSONException { + return (JSONArray)parse(new XMLTokener(string), true, null, keepStrings); + } + + + /** + * Convert a well-formed (but not necessarily valid) XML string into a + * JSONArray using the JsonML transform. Each XML tag is represented as + * a JSONArray in which the first element is the tag name. If the tag has + * attributes, then the second element will be JSONObject containing the + * name/value pairs. If the tag contains children, then strings and + * JSONArrays will represent the child content and tags. + * As opposed to toJSONArray this method does not attempt to convert + * any text node or attribute value to any type + * but just leaves it as a string. + * Comments, prologs, DTDs, and
{@code <[ [ ]]>}
are ignored. + * @param x An XMLTokener. + * @param keepStrings If true, then values will not be coerced into boolean + * or numeric values and will instead be left as strings + * @return A JSONArray containing the structured data from the XML string. + * @throws JSONException Thrown on error converting to a JSONArray + */ + public static JSONArray toJSONArray(XMLTokener x, boolean keepStrings) throws JSONException { + return (JSONArray)parse(x, true, null, keepStrings); + } + + + /** + * Convert a well-formed (but not necessarily valid) XML string into a + * JSONArray using the JsonML transform. Each XML tag is represented as + * a JSONArray in which the first element is the tag name. If the tag has + * attributes, then the second element will be JSONObject containing the + * name/value pairs. If the tag contains children, then strings and + * JSONArrays will represent the child content and tags. + * Comments, prologs, DTDs, and
{@code <[ [ ]]>}
are ignored. + * @param x An XMLTokener. + * @return A JSONArray containing the structured data from the XML string. + * @throws JSONException Thrown on error converting to a JSONArray + */ + public static JSONArray toJSONArray(XMLTokener x) throws JSONException { + return (JSONArray)parse(x, true, null, false); + } + + + /** + * Convert a well-formed (but not necessarily valid) XML string into a + * JSONObject using the JsonML transform. Each XML tag is represented as + * a JSONObject with a "tagName" property. If the tag has attributes, then + * the attributes will be in the JSONObject as properties. If the tag + * contains children, the object will have a "childNodes" property which + * will be an array of strings and JsonML JSONObjects. + + * Comments, prologs, DTDs, and
{@code <[ [ ]]>}
are ignored. + * @param string The XML source text. + * @return A JSONObject containing the structured data from the XML string. + * @throws JSONException Thrown on error converting to a JSONObject + */ + public static JSONObject toJSONObject(String string) throws JSONException { + return (JSONObject)parse(new XMLTokener(string), false, null, false); + } + + + /** + * Convert a well-formed (but not necessarily valid) XML string into a + * JSONObject using the JsonML transform. Each XML tag is represented as + * a JSONObject with a "tagName" property. If the tag has attributes, then + * the attributes will be in the JSONObject as properties. If the tag + * contains children, the object will have a "childNodes" property which + * will be an array of strings and JsonML JSONObjects. + + * Comments, prologs, DTDs, and
{@code <[ [ ]]>}
are ignored. + * @param string The XML source text. + * @param keepStrings If true, then values will not be coerced into boolean + * or numeric values and will instead be left as strings + * @return A JSONObject containing the structured data from the XML string. + * @throws JSONException Thrown on error converting to a JSONObject + */ + public static JSONObject toJSONObject(String string, boolean keepStrings) throws JSONException { + return (JSONObject)parse(new XMLTokener(string), false, null, keepStrings); + } + + + /** + * Convert a well-formed (but not necessarily valid) XML string into a + * JSONObject using the JsonML transform. Each XML tag is represented as + * a JSONObject with a "tagName" property. If the tag has attributes, then + * the attributes will be in the JSONObject as properties. If the tag + * contains children, the object will have a "childNodes" property which + * will be an array of strings and JsonML JSONObjects. + + * Comments, prologs, DTDs, and
{@code <[ [ ]]>}
are ignored. + * @param x An XMLTokener of the XML source text. + * @return A JSONObject containing the structured data from the XML string. + * @throws JSONException Thrown on error converting to a JSONObject + */ + public static JSONObject toJSONObject(XMLTokener x) throws JSONException { + return (JSONObject)parse(x, false, null, false); + } + + + /** + * Convert a well-formed (but not necessarily valid) XML string into a + * JSONObject using the JsonML transform. Each XML tag is represented as + * a JSONObject with a "tagName" property. If the tag has attributes, then + * the attributes will be in the JSONObject as properties. If the tag + * contains children, the object will have a "childNodes" property which + * will be an array of strings and JsonML JSONObjects. + + * Comments, prologs, DTDs, and
{@code <[ [ ]]>}
are ignored. + * @param x An XMLTokener of the XML source text. + * @param keepStrings If true, then values will not be coerced into boolean + * or numeric values and will instead be left as strings + * @return A JSONObject containing the structured data from the XML string. + * @throws JSONException Thrown on error converting to a JSONObject + */ + public static JSONObject toJSONObject(XMLTokener x, boolean keepStrings) throws JSONException { + return (JSONObject)parse(x, false, null, keepStrings); + } + + + /** + * Reverse the JSONML transformation, making an XML text from a JSONArray. + * @param ja A JSONArray. + * @return An XML string. + * @throws JSONException Thrown on error converting to a string + */ + public static String toString(JSONArray ja) throws JSONException { + int i; + JSONObject jo; + int length; + Object object; + StringBuilder sb = new StringBuilder(); + String tagName; + +// Emit = length) { + sb.append('/'); + sb.append('>'); + } else { + sb.append('>'); + do { + object = ja.get(i); + i += 1; + if (object != null) { + if (object instanceof String) { + sb.append(XML.escape(object.toString())); + } else if (object instanceof JSONObject) { + sb.append(toString((JSONObject)object)); + } else if (object instanceof JSONArray) { + sb.append(toString((JSONArray)object)); + } else { + sb.append(object.toString()); + } + } + } while (i < length); + sb.append('<'); + sb.append('/'); + sb.append(tagName); + sb.append('>'); + } + return sb.toString(); + } + + /** + * Reverse the JSONML transformation, making an XML text from a JSONObject. + * The JSONObject must contain a "tagName" property. If it has children, + * then it must have a "childNodes" property containing an array of objects. + * The other properties are attributes with string values. + * @param jo A JSONObject. + * @return An XML string. + * @throws JSONException Thrown on error converting to a string + */ + public static String toString(JSONObject jo) throws JSONException { + StringBuilder sb = new StringBuilder(); + int i; + JSONArray ja; + int length; + Object object; + String tagName; + Object value; + +//Emit '); + } else { + sb.append('>'); + length = ja.length(); + for (i = 0; i < length; i += 1) { + object = ja.get(i); + if (object != null) { + if (object instanceof String) { + sb.append(XML.escape(object.toString())); + } else if (object instanceof JSONObject) { + sb.append(toString((JSONObject)object)); + } else if (object instanceof JSONArray) { + sb.append(toString((JSONArray)object)); + } else { + sb.append(object.toString()); + } + } + } + sb.append('<'); + sb.append('/'); + sb.append(tagName); + sb.append('>'); + } + return sb.toString(); + } +} diff --git a/src/main/java/org/json/JSONObject.java b/src/main/java/org/json/JSONObject.java new file mode 100644 index 0000000..5c37249 --- /dev/null +++ b/src/main/java/org/json/JSONObject.java @@ -0,0 +1,2732 @@ +package org.json; + +import java.io.Closeable; + +/* + Copyright (c) 2002 JSON.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + The Software shall be used for Good, not Evil. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + */ + +import java.io.IOException; +import java.io.StringWriter; +import java.io.Writer; +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.Collection; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.IdentityHashMap; +import java.util.Iterator; +import java.util.Locale; +import java.util.Map; +import java.util.Map.Entry; +import java.util.ResourceBundle; +import java.util.Set; +import java.util.regex.Pattern; + +/** + * A JSONObject is an unordered collection of name/value pairs. Its external + * form is a string wrapped in curly braces with colons between the names and + * values, and commas between the values and names. The internal form is an + * object having get and opt methods for accessing + * the values by name, and put methods for adding or replacing + * values by name. The values can be any of these types: Boolean, + * JSONArray, JSONObject, Number, + * String, or the JSONObject.NULL object. A + * JSONObject constructor can be used to convert an external form JSON text + * into an internal form whose values can be retrieved with the + * get and opt methods, or to convert values into a + * JSON text using the put and toString methods. A + * get method returns a value if one can be found, and throws an + * exception if one cannot be found. An opt method returns a + * default value instead of throwing an exception, and so is useful for + * obtaining optional values. + *

+ * The generic get() and opt() methods return an + * object, which you can cast or query for type. There are also typed + * get and opt methods that do type checking and type + * coercion for you. The opt methods differ from the get methods in that they + * do not throw. Instead, they return a specified value, such as null. + *

+ * The put methods add or replace values in an object. For + * example, + * + *

+ * myString = new JSONObject()
+ *         .put("JSON", "Hello, World!").toString();
+ * 
+ * + * produces the string {"JSON": "Hello, World"}. + *

+ * The texts produced by the toString methods strictly conform to + * the JSON syntax rules. The constructors are more forgiving in the texts they + * will accept: + *

    + *
  • An extra , (comma) may appear just + * before the closing brace.
  • + *
  • Strings may be quoted with ' (single + * quote).
  • + *
  • Strings do not need to be quoted at all if they do not begin with a + * quote or single quote, and if they do not contain leading or trailing + * spaces, and if they do not contain any of these characters: + * { } [ ] / \ : , # and if they do not look like numbers and + * if they are not the reserved words true, false, + * or null.
  • + *
+ * + * @author JSON.org + * @version 2016-08-15 + */ +public class JSONObject { + /** + * JSONObject.NULL is equivalent to the value that JavaScript calls null, + * whilst Java's null is equivalent to the value that JavaScript calls + * undefined. + */ + private static final class Null { + + /** + * There is only intended to be a single instance of the NULL object, + * so the clone method returns itself. + * + * @return NULL. + */ + @Override + protected final Object clone() { + return this; + } + + /** + * A Null object is equal to the null value and to itself. + * + * @param object + * An object to test for nullness. + * @return true if the object parameter is the JSONObject.NULL object or + * null. + */ + @Override + @SuppressWarnings("lgtm[java/unchecked-cast-in-equals]") + public boolean equals(Object object) { + return object == null || object == this; + } + /** + * A Null object is equal to the null value and to itself. + * + * @return always returns 0. + */ + @Override + public int hashCode() { + return 0; + } + + /** + * Get the "null" string value. + * + * @return The string "null". + */ + @Override + public String toString() { + return "null"; + } + } + + /** + * Regular Expression Pattern that matches JSON Numbers. This is primarily used for + * output to guarantee that we are always writing valid JSON. + */ + static final Pattern NUMBER_PATTERN = Pattern.compile("-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?"); + + /** + * The map where the JSONObject's properties are kept. + */ + private final Map map; + + /** + * It is sometimes more convenient and less ambiguous to have a + * NULL object than to use Java's null value. + * JSONObject.NULL.equals(null) returns true. + * JSONObject.NULL.toString() returns "null". + */ + public static final Object NULL = new Null(); + + /** + * Construct an empty JSONObject. + */ + public JSONObject() { + // HashMap is used on purpose to ensure that elements are unordered by + // the specification. + // JSON tends to be a portable transfer format to allows the container + // implementations to rearrange their items for a faster element + // retrieval based on associative access. + // Therefore, an implementation mustn't rely on the order of the item. + this.map = new HashMap(); + } + + /** + * Construct a JSONObject from a subset of another JSONObject. An array of + * strings is used to identify the keys that should be copied. Missing keys + * are ignored. + * + * @param jo + * A JSONObject. + * @param names + * An array of strings. + */ + public JSONObject(JSONObject jo, String ... names) { + this(names.length); + for (int i = 0; i < names.length; i += 1) { + try { + this.putOnce(names[i], jo.opt(names[i])); + } catch (Exception ignore) { + } + } + } + + /** + * Construct a JSONObject from a JSONTokener. + * + * @param x + * A JSONTokener object containing the source string. + * @throws JSONException + * If there is a syntax error in the source string or a + * duplicated key. + */ + public JSONObject(JSONTokener x) throws JSONException { + this(); + char c; + String key; + + if (x.nextClean() != '{') { + throw x.syntaxError("A JSONObject text must begin with '{'"); + } + for (;;) { + char prev = x.getPrevious(); + c = x.nextClean(); + switch (c) { + case 0: + throw x.syntaxError("A JSONObject text must end with '}'"); + case '}': + return; + case '{': + case '[': + if(prev=='{') { + throw x.syntaxError("A JSON Object can not directly nest another JSON Object or JSON Array."); + } + // fall through + default: + x.back(); + key = x.nextValue().toString(); + } + + // The key is followed by ':'. + + c = x.nextClean(); + if (c != ':') { + throw x.syntaxError("Expected a ':' after a key"); + } + + // Use syntaxError(..) to include error location + + if (key != null) { + // Check if key exists + if (this.opt(key) != null) { + // key already exists + throw x.syntaxError("Duplicate key \"" + key + "\""); + } + // Only add value if non-null + Object value = x.nextValue(); + if (value!=null) { + this.put(key, value); + } + } + + // Pairs are separated by ','. + + switch (x.nextClean()) { + case ';': + case ',': + if (x.nextClean() == '}') { + return; + } + x.back(); + break; + case '}': + return; + default: + throw x.syntaxError("Expected a ',' or '}'"); + } + } + } + + /** + * Construct a JSONObject from a Map. + * + * @param m + * A map object that can be used to initialize the contents of + * the JSONObject. + * @throws JSONException + * If a value in the map is non-finite number. + * @throws NullPointerException + * If a key in the map is null + */ + public JSONObject(Map m) { + if (m == null) { + this.map = new HashMap(); + } else { + this.map = new HashMap(m.size()); + for (final Entry e : m.entrySet()) { + if(e.getKey() == null) { + throw new NullPointerException("Null key."); + } + final Object value = e.getValue(); + if (value != null) { + this.map.put(String.valueOf(e.getKey()), wrap(value)); + } + } + } + } + + /** + * Construct a JSONObject from an Object using bean getters. It reflects on + * all of the public methods of the object. For each of the methods with no + * parameters and a name starting with "get" or + * "is" followed by an uppercase letter, the method is invoked, + * and a key and the value returned from the getter method are put into the + * new JSONObject. + *

+ * The key is formed by removing the "get" or "is" + * prefix. If the second remaining character is not upper case, then the + * first character is converted to lower case. + *

+ * Methods that are static, return void, + * have parameters, or are "bridge" methods, are ignored. + *

+ * For example, if an object has a method named "getName", and + * if the result of calling object.getName() is + * "Larry Fine", then the JSONObject will contain + * "name": "Larry Fine". + *

+ * The {@link JSONPropertyName} annotation can be used on a bean getter to + * override key name used in the JSONObject. For example, using the object + * above with the getName method, if we annotated it with: + *

+     * @JSONPropertyName("FullName")
+     * public String getName() { return this.name; }
+     * 
+ * The resulting JSON object would contain "FullName": "Larry Fine" + *

+ * Similarly, the {@link JSONPropertyName} annotation can be used on non- + * get and is methods. We can also override key + * name used in the JSONObject as seen below even though the field would normally + * be ignored: + *

+     * @JSONPropertyName("FullName")
+     * public String fullName() { return this.name; }
+     * 
+ * The resulting JSON object would contain "FullName": "Larry Fine" + *

+ * The {@link JSONPropertyIgnore} annotation can be used to force the bean property + * to not be serialized into JSON. If both {@link JSONPropertyIgnore} and + * {@link JSONPropertyName} are defined on the same method, a depth comparison is + * performed and the one closest to the concrete class being serialized is used. + * If both annotations are at the same level, then the {@link JSONPropertyIgnore} + * annotation takes precedent and the field is not serialized. + * For example, the following declaration would prevent the getName + * method from being serialized: + *

+     * @JSONPropertyName("FullName")
+     * @JSONPropertyIgnore
+     * public String getName() { return this.name; }
+     * 
+ *

+ * + * @param bean + * An object that has getter methods that should be used to make + * a JSONObject. + */ + public JSONObject(Object bean) { + this(); + this.populateMap(bean); + } + + private JSONObject(Object bean, Set objectsRecord) { + this(); + this.populateMap(bean, objectsRecord); + } + + /** + * Construct a JSONObject from an Object, using reflection to find the + * public members. The resulting JSONObject's keys will be the strings from + * the names array, and the values will be the field values associated with + * those keys in the object. If a key is not found or not visible, then it + * will not be copied into the new JSONObject. + * + * @param object + * An object that has fields that should be used to make a + * JSONObject. + * @param names + * An array of strings, the names of the fields to be obtained + * from the object. + */ + public JSONObject(Object object, String ... names) { + this(names.length); + Class c = object.getClass(); + for (int i = 0; i < names.length; i += 1) { + String name = names[i]; + try { + this.putOpt(name, c.getField(name).get(object)); + } catch (Exception ignore) { + } + } + } + + /** + * Construct a JSONObject from a source JSON text string. This is the most + * commonly used JSONObject constructor. + * + * @param source + * A string beginning with { (left + * brace) and ending with } + *  (right brace). + * @exception JSONException + * If there is a syntax error in the source string or a + * duplicated key. + */ + public JSONObject(String source) throws JSONException { + this(new JSONTokener(source)); + } + + /** + * Construct a JSONObject from a ResourceBundle. + * + * @param baseName + * The ResourceBundle base name. + * @param locale + * The Locale to load the ResourceBundle for. + * @throws JSONException + * If any JSONExceptions are detected. + */ + public JSONObject(String baseName, Locale locale) throws JSONException { + this(); + ResourceBundle bundle = ResourceBundle.getBundle(baseName, locale, + Thread.currentThread().getContextClassLoader()); + +// Iterate through the keys in the bundle. + + Enumeration keys = bundle.getKeys(); + while (keys.hasMoreElements()) { + Object key = keys.nextElement(); + if (key != null) { + +// Go through the path, ensuring that there is a nested JSONObject for each +// segment except the last. Add the value using the last segment's name into +// the deepest nested JSONObject. + + String[] path = ((String) key).split("\\."); + int last = path.length - 1; + JSONObject target = this; + for (int i = 0; i < last; i += 1) { + String segment = path[i]; + JSONObject nextTarget = target.optJSONObject(segment); + if (nextTarget == null) { + nextTarget = new JSONObject(); + target.put(segment, nextTarget); + } + target = nextTarget; + } + target.put(path[last], bundle.getString((String) key)); + } + } + } + + /** + * Constructor to specify an initial capacity of the internal map. Useful for library + * internal calls where we know, or at least can best guess, how big this JSONObject + * will be. + * + * @param initialCapacity initial capacity of the internal map. + */ + protected JSONObject(int initialCapacity){ + this.map = new HashMap(initialCapacity); + } + + /** + * Accumulate values under a key. It is similar to the put method except + * that if there is already an object stored under the key then a JSONArray + * is stored under the key to hold all of the accumulated values. If there + * is already a JSONArray, then the new value is appended to it. In + * contrast, the put method replaces the previous value. + * + * If only one value is accumulated that is not a JSONArray, then the result + * will be the same as using put. But if multiple values are accumulated, + * then the result will be like append. + * + * @param key + * A key string. + * @param value + * An object to be accumulated under the key. + * @return this. + * @throws JSONException + * If the value is non-finite number. + * @throws NullPointerException + * If the key is null. + */ + public JSONObject accumulate(String key, Object value) throws JSONException { + testValidity(value); + Object object = this.opt(key); + if (object == null) { + this.put(key, + value instanceof JSONArray ? new JSONArray().put(value) + : value); + } else if (object instanceof JSONArray) { + ((JSONArray) object).put(value); + } else { + this.put(key, new JSONArray().put(object).put(value)); + } + return this; + } + + /** + * Append values to the array under a key. If the key does not exist in the + * JSONObject, then the key is put in the JSONObject with its value being a + * JSONArray containing the value parameter. If the key was already + * associated with a JSONArray, then the value parameter is appended to it. + * + * @param key + * A key string. + * @param value + * An object to be accumulated under the key. + * @return this. + * @throws JSONException + * If the value is non-finite number or if the current value associated with + * the key is not a JSONArray. + * @throws NullPointerException + * If the key is null. + */ + public JSONObject append(String key, Object value) throws JSONException { + testValidity(value); + Object object = this.opt(key); + if (object == null) { + this.put(key, new JSONArray().put(value)); + } else if (object instanceof JSONArray) { + this.put(key, ((JSONArray) object).put(value)); + } else { + throw wrongValueFormatException(key, "JSONArray", null, null); + } + return this; + } + + /** + * Produce a string from a double. The string "null" will be returned if the + * number is not finite. + * + * @param d + * A double. + * @return A String. + */ + public static String doubleToString(double d) { + if (Double.isInfinite(d) || Double.isNaN(d)) { + return "null"; + } + +// Shave off trailing zeros and decimal point, if possible. + + String string = Double.toString(d); + if (string.indexOf('.') > 0 && string.indexOf('e') < 0 + && string.indexOf('E') < 0) { + while (string.endsWith("0")) { + string = string.substring(0, string.length() - 1); + } + if (string.endsWith(".")) { + string = string.substring(0, string.length() - 1); + } + } + return string; + } + + /** + * Get the value object associated with a key. + * + * @param key + * A key string. + * @return The object associated with the key. + * @throws JSONException + * if the key is not found. + */ + public Object get(String key) throws JSONException { + if (key == null) { + throw new JSONException("Null key."); + } + Object object = this.opt(key); + if (object == null) { + throw new JSONException("JSONObject[" + quote(key) + "] not found."); + } + return object; + } + + /** + * Get the enum value associated with a key. + * + * @param + * Enum Type + * @param clazz + * The type of enum to retrieve. + * @param key + * A key string. + * @return The enum value associated with the key + * @throws JSONException + * if the key is not found or if the value cannot be converted + * to an enum. + */ + public > E getEnum(Class clazz, String key) throws JSONException { + E val = optEnum(clazz, key); + if(val==null) { + // JSONException should really take a throwable argument. + // If it did, I would re-implement this with the Enum.valueOf + // method and place any thrown exception in the JSONException + throw wrongValueFormatException(key, "enum of type " + quote(clazz.getSimpleName()), null); + } + return val; + } + + /** + * Get the boolean value associated with a key. + * + * @param key + * A key string. + * @return The truth. + * @throws JSONException + * if the value is not a Boolean or the String "true" or + * "false". + */ + public boolean getBoolean(String key) throws JSONException { + Object object = this.get(key); + if (object.equals(Boolean.FALSE) + || (object instanceof String && ((String) object) + .equalsIgnoreCase("false"))) { + return false; + } else if (object.equals(Boolean.TRUE) + || (object instanceof String && ((String) object) + .equalsIgnoreCase("true"))) { + return true; + } + throw wrongValueFormatException(key, "Boolean", null); + } + + /** + * Get the BigInteger value associated with a key. + * + * @param key + * A key string. + * @return The numeric value. + * @throws JSONException + * if the key is not found or if the value cannot + * be converted to BigInteger. + */ + public BigInteger getBigInteger(String key) throws JSONException { + Object object = this.get(key); + BigInteger ret = objectToBigInteger(object, null); + if (ret != null) { + return ret; + } + throw wrongValueFormatException(key, "BigInteger", object, null); + } + + /** + * Get the BigDecimal value associated with a key. If the value is float or + * double, the {@link BigDecimal#BigDecimal(double)} constructor will + * be used. See notes on the constructor for conversion issues that may + * arise. + * + * @param key + * A key string. + * @return The numeric value. + * @throws JSONException + * if the key is not found or if the value + * cannot be converted to BigDecimal. + */ + public BigDecimal getBigDecimal(String key) throws JSONException { + Object object = this.get(key); + BigDecimal ret = objectToBigDecimal(object, null); + if (ret != null) { + return ret; + } + throw wrongValueFormatException(key, "BigDecimal", object, null); + } + + /** + * Get the double value associated with a key. + * + * @param key + * A key string. + * @return The numeric value. + * @throws JSONException + * if the key is not found or if the value is not a Number + * object and cannot be converted to a number. + */ + public double getDouble(String key) throws JSONException { + final Object object = this.get(key); + if(object instanceof Number) { + return ((Number)object).doubleValue(); + } + try { + return Double.parseDouble(object.toString()); + } catch (Exception e) { + throw wrongValueFormatException(key, "double", e); + } + } + + /** + * Get the float value associated with a key. + * + * @param key + * A key string. + * @return The numeric value. + * @throws JSONException + * if the key is not found or if the value is not a Number + * object and cannot be converted to a number. + */ + public float getFloat(String key) throws JSONException { + final Object object = this.get(key); + if(object instanceof Number) { + return ((Number)object).floatValue(); + } + try { + return Float.parseFloat(object.toString()); + } catch (Exception e) { + throw wrongValueFormatException(key, "float", e); + } + } + + /** + * Get the Number value associated with a key. + * + * @param key + * A key string. + * @return The numeric value. + * @throws JSONException + * if the key is not found or if the value is not a Number + * object and cannot be converted to a number. + */ + public Number getNumber(String key) throws JSONException { + Object object = this.get(key); + try { + if (object instanceof Number) { + return (Number)object; + } + return stringToNumber(object.toString()); + } catch (Exception e) { + throw wrongValueFormatException(key, "number", e); + } + } + + /** + * Get the int value associated with a key. + * + * @param key + * A key string. + * @return The integer value. + * @throws JSONException + * if the key is not found or if the value cannot be converted + * to an integer. + */ + public int getInt(String key) throws JSONException { + final Object object = this.get(key); + if(object instanceof Number) { + return ((Number)object).intValue(); + } + try { + return Integer.parseInt(object.toString()); + } catch (Exception e) { + throw wrongValueFormatException(key, "int", e); + } + } + + /** + * Get the JSONArray value associated with a key. + * + * @param key + * A key string. + * @return A JSONArray which is the value. + * @throws JSONException + * if the key is not found or if the value is not a JSONArray. + */ + public JSONArray getJSONArray(String key) throws JSONException { + Object object = this.get(key); + if (object instanceof JSONArray) { + return (JSONArray) object; + } + throw wrongValueFormatException(key, "JSONArray", null); + } + + /** + * Get the JSONObject value associated with a key. + * + * @param key + * A key string. + * @return A JSONObject which is the value. + * @throws JSONException + * if the key is not found or if the value is not a JSONObject. + */ + public JSONObject getJSONObject(String key) throws JSONException { + Object object = this.get(key); + if (object instanceof JSONObject) { + return (JSONObject) object; + } + throw wrongValueFormatException(key, "JSONObject", null); + } + + /** + * Get the long value associated with a key. + * + * @param key + * A key string. + * @return The long value. + * @throws JSONException + * if the key is not found or if the value cannot be converted + * to a long. + */ + public long getLong(String key) throws JSONException { + final Object object = this.get(key); + if(object instanceof Number) { + return ((Number)object).longValue(); + } + try { + return Long.parseLong(object.toString()); + } catch (Exception e) { + throw wrongValueFormatException(key, "long", e); + } + } + + /** + * Get an array of field names from a JSONObject. + * + * @param jo + * JSON object + * @return An array of field names, or null if there are no names. + */ + public static String[] getNames(JSONObject jo) { + if (jo.isEmpty()) { + return null; + } + return jo.keySet().toArray(new String[jo.length()]); + } + + /** + * Get an array of public field names from an Object. + * + * @param object + * object to read + * @return An array of field names, or null if there are no names. + */ + public static String[] getNames(Object object) { + if (object == null) { + return null; + } + Class klass = object.getClass(); + Field[] fields = klass.getFields(); + int length = fields.length; + if (length == 0) { + return null; + } + String[] names = new String[length]; + for (int i = 0; i < length; i += 1) { + names[i] = fields[i].getName(); + } + return names; + } + + /** + * Get the string associated with a key. + * + * @param key + * A key string. + * @return A string which is the value. + * @throws JSONException + * if there is no string value for the key. + */ + public String getString(String key) throws JSONException { + Object object = this.get(key); + if (object instanceof String) { + return (String) object; + } + throw wrongValueFormatException(key, "string", null); + } + + /** + * Determine if the JSONObject contains a specific key. + * + * @param key + * A key string. + * @return true if the key exists in the JSONObject. + */ + public boolean has(String key) { + return this.map.containsKey(key); + } + + /** + * Increment a property of a JSONObject. If there is no such property, + * create one with a value of 1 (Integer). If there is such a property, and if it is + * an Integer, Long, Double, Float, BigInteger, or BigDecimal then add one to it. + * No overflow bounds checking is performed, so callers should initialize the key + * prior to this call with an appropriate type that can handle the maximum expected + * value. + * + * @param key + * A key string. + * @return this. + * @throws JSONException + * If there is already a property with this name that is not an + * Integer, Long, Double, or Float. + */ + public JSONObject increment(String key) throws JSONException { + Object value = this.opt(key); + if (value == null) { + this.put(key, 1); + } else if (value instanceof Integer) { + this.put(key, ((Integer) value).intValue() + 1); + } else if (value instanceof Long) { + this.put(key, ((Long) value).longValue() + 1L); + } else if (value instanceof BigInteger) { + this.put(key, ((BigInteger)value).add(BigInteger.ONE)); + } else if (value instanceof Float) { + this.put(key, ((Float) value).floatValue() + 1.0f); + } else if (value instanceof Double) { + this.put(key, ((Double) value).doubleValue() + 1.0d); + } else if (value instanceof BigDecimal) { + this.put(key, ((BigDecimal)value).add(BigDecimal.ONE)); + } else { + throw new JSONException("Unable to increment [" + quote(key) + "]."); + } + return this; + } + + /** + * Determine if the value associated with the key is null or if there is no + * value. + * + * @param key + * A key string. + * @return true if there is no value associated with the key or if the value + * is the JSONObject.NULL object. + */ + public boolean isNull(String key) { + return JSONObject.NULL.equals(this.opt(key)); + } + + /** + * Get an enumeration of the keys of the JSONObject. Modifying this key Set will also + * modify the JSONObject. Use with caution. + * + * @see Set#iterator() + * + * @return An iterator of the keys. + */ + public Iterator keys() { + return this.keySet().iterator(); + } + + /** + * Get a set of keys of the JSONObject. Modifying this key Set will also modify the + * JSONObject. Use with caution. + * + * @see Map#keySet() + * + * @return A keySet. + */ + public Set keySet() { + return this.map.keySet(); + } + + /** + * Get a set of entries of the JSONObject. These are raw values and may not + * match what is returned by the JSONObject get* and opt* functions. Modifying + * the returned EntrySet or the Entry objects contained therein will modify the + * backing JSONObject. This does not return a clone or a read-only view. + * + * Use with caution. + * + * @see Map#entrySet() + * + * @return An Entry Set + */ + protected Set> entrySet() { + return this.map.entrySet(); + } + + /** + * Get the number of keys stored in the JSONObject. + * + * @return The number of keys in the JSONObject. + */ + public int length() { + return this.map.size(); + } + + /** + * Removes all of the elements from this JSONObject. + * The JSONObject will be empty after this call returns. + */ + public void clear() { + this.map.clear(); + } + + /** + * Check if JSONObject is empty. + * + * @return true if JSONObject is empty, otherwise false. + */ + public boolean isEmpty() { + return this.map.isEmpty(); + } + + /** + * Produce a JSONArray containing the names of the elements of this + * JSONObject. + * + * @return A JSONArray containing the key strings, or null if the JSONObject + * is empty. + */ + public JSONArray names() { + if(this.map.isEmpty()) { + return null; + } + return new JSONArray(this.map.keySet()); + } + + /** + * Produce a string from a Number. + * + * @param number + * A Number + * @return A String. + * @throws JSONException + * If n is a non-finite number. + */ + public static String numberToString(Number number) throws JSONException { + if (number == null) { + throw new JSONException("Null pointer"); + } + testValidity(number); + + // Shave off trailing zeros and decimal point, if possible. + + String string = number.toString(); + if (string.indexOf('.') > 0 && string.indexOf('e') < 0 + && string.indexOf('E') < 0) { + while (string.endsWith("0")) { + string = string.substring(0, string.length() - 1); + } + if (string.endsWith(".")) { + string = string.substring(0, string.length() - 1); + } + } + return string; + } + + /** + * Get an optional value associated with a key. + * + * @param key + * A key string. + * @return An object which is the value, or null if there is no value. + */ + public Object opt(String key) { + return key == null ? null : this.map.get(key); + } + + /** + * Get the enum value associated with a key. + * + * @param + * Enum Type + * @param clazz + * The type of enum to retrieve. + * @param key + * A key string. + * @return The enum value associated with the key or null if not found + */ + public > E optEnum(Class clazz, String key) { + return this.optEnum(clazz, key, null); + } + + /** + * Get the enum value associated with a key. + * + * @param + * Enum Type + * @param clazz + * The type of enum to retrieve. + * @param key + * A key string. + * @param defaultValue + * The default in case the value is not found + * @return The enum value associated with the key or defaultValue + * if the value is not found or cannot be assigned to clazz + */ + public > E optEnum(Class clazz, String key, E defaultValue) { + try { + Object val = this.opt(key); + if (NULL.equals(val)) { + return defaultValue; + } + if (clazz.isAssignableFrom(val.getClass())) { + // we just checked it! + @SuppressWarnings("unchecked") + E myE = (E) val; + return myE; + } + return Enum.valueOf(clazz, val.toString()); + } catch (IllegalArgumentException e) { + return defaultValue; + } catch (NullPointerException e) { + return defaultValue; + } + } + + /** + * Get an optional boolean associated with a key. It returns false if there + * is no such key, or if the value is not Boolean.TRUE or the String "true". + * + * @param key + * A key string. + * @return The truth. + */ + public boolean optBoolean(String key) { + return this.optBoolean(key, false); + } + + /** + * Get an optional boolean associated with a key. It returns the + * defaultValue if there is no such key, or if it is not a Boolean or the + * String "true" or "false" (case insensitive). + * + * @param key + * A key string. + * @param defaultValue + * The default. + * @return The truth. + */ + public boolean optBoolean(String key, boolean defaultValue) { + Object val = this.opt(key); + if (NULL.equals(val)) { + return defaultValue; + } + if (val instanceof Boolean){ + return ((Boolean) val).booleanValue(); + } + try { + // we'll use the get anyway because it does string conversion. + return this.getBoolean(key); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * Get an optional BigDecimal associated with a key, or the defaultValue if + * there is no such key or if its value is not a number. If the value is a + * string, an attempt will be made to evaluate it as a number. If the value + * is float or double, then the {@link BigDecimal#BigDecimal(double)} + * constructor will be used. See notes on the constructor for conversion + * issues that may arise. + * + * @param key + * A key string. + * @param defaultValue + * The default. + * @return An object which is the value. + */ + public BigDecimal optBigDecimal(String key, BigDecimal defaultValue) { + Object val = this.opt(key); + return objectToBigDecimal(val, defaultValue); + } + + /** + * @param val value to convert + * @param defaultValue default value to return is the conversion doesn't work or is null. + * @return BigDecimal conversion of the original value, or the defaultValue if unable + * to convert. + */ + static BigDecimal objectToBigDecimal(Object val, BigDecimal defaultValue) { + return objectToBigDecimal(val, defaultValue, true); + } + + /** + * @param val value to convert + * @param defaultValue default value to return is the conversion doesn't work or is null. + * @param exact When true, then {@link Double} and {@link Float} values will be converted exactly. + * When false, they will be converted to {@link String} values before converting to {@link BigDecimal}. + * @return BigDecimal conversion of the original value, or the defaultValue if unable + * to convert. + */ + static BigDecimal objectToBigDecimal(Object val, BigDecimal defaultValue, boolean exact) { + if (NULL.equals(val)) { + return defaultValue; + } + if (val instanceof BigDecimal){ + return (BigDecimal) val; + } + if (val instanceof BigInteger){ + return new BigDecimal((BigInteger) val); + } + if (val instanceof Double || val instanceof Float){ + if (!numberIsFinite((Number)val)) { + return defaultValue; + } + if (exact) { + return new BigDecimal(((Number)val).doubleValue()); + }else { + // use the string constructor so that we maintain "nice" values for doubles and floats + // the double constructor will translate doubles to "exact" values instead of the likely + // intended representation + return new BigDecimal(val.toString()); + } + } + if (val instanceof Long || val instanceof Integer + || val instanceof Short || val instanceof Byte){ + return new BigDecimal(((Number) val).longValue()); + } + // don't check if it's a string in case of unchecked Number subclasses + try { + return new BigDecimal(val.toString()); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * Get an optional BigInteger associated with a key, or the defaultValue if + * there is no such key or if its value is not a number. If the value is a + * string, an attempt will be made to evaluate it as a number. + * + * @param key + * A key string. + * @param defaultValue + * The default. + * @return An object which is the value. + */ + public BigInteger optBigInteger(String key, BigInteger defaultValue) { + Object val = this.opt(key); + return objectToBigInteger(val, defaultValue); + } + + /** + * @param val value to convert + * @param defaultValue default value to return is the conversion doesn't work or is null. + * @return BigInteger conversion of the original value, or the defaultValue if unable + * to convert. + */ + static BigInteger objectToBigInteger(Object val, BigInteger defaultValue) { + if (NULL.equals(val)) { + return defaultValue; + } + if (val instanceof BigInteger){ + return (BigInteger) val; + } + if (val instanceof BigDecimal){ + return ((BigDecimal) val).toBigInteger(); + } + if (val instanceof Double || val instanceof Float){ + if (!numberIsFinite((Number)val)) { + return defaultValue; + } + return new BigDecimal(((Number) val).doubleValue()).toBigInteger(); + } + if (val instanceof Long || val instanceof Integer + || val instanceof Short || val instanceof Byte){ + return BigInteger.valueOf(((Number) val).longValue()); + } + // don't check if it's a string in case of unchecked Number subclasses + try { + // the other opt functions handle implicit conversions, i.e. + // jo.put("double",1.1d); + // jo.optInt("double"); -- will return 1, not an error + // this conversion to BigDecimal then to BigInteger is to maintain + // that type cast support that may truncate the decimal. + final String valStr = val.toString(); + if(isDecimalNotation(valStr)) { + return new BigDecimal(valStr).toBigInteger(); + } + return new BigInteger(valStr); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * Get an optional double associated with a key, or NaN if there is no such + * key or if its value is not a number. If the value is a string, an attempt + * will be made to evaluate it as a number. + * + * @param key + * A string which is the key. + * @return An object which is the value. + */ + public double optDouble(String key) { + return this.optDouble(key, Double.NaN); + } + + /** + * Get an optional double associated with a key, or the defaultValue if + * there is no such key or if its value is not a number. If the value is a + * string, an attempt will be made to evaluate it as a number. + * + * @param key + * A key string. + * @param defaultValue + * The default. + * @return An object which is the value. + */ + public double optDouble(String key, double defaultValue) { + Number val = this.optNumber(key); + if (val == null) { + return defaultValue; + } + final double doubleValue = val.doubleValue(); + // if (Double.isNaN(doubleValue) || Double.isInfinite(doubleValue)) { + // return defaultValue; + // } + return doubleValue; + } + + /** + * Get the optional double value associated with an index. NaN is returned + * if there is no value for the index, or if the value is not a number and + * cannot be converted to a number. + * + * @param key + * A key string. + * @return The value. + */ + public float optFloat(String key) { + return this.optFloat(key, Float.NaN); + } + + /** + * Get the optional double value associated with an index. The defaultValue + * is returned if there is no value for the index, or if the value is not a + * number and cannot be converted to a number. + * + * @param key + * A key string. + * @param defaultValue + * The default value. + * @return The value. + */ + public float optFloat(String key, float defaultValue) { + Number val = this.optNumber(key); + if (val == null) { + return defaultValue; + } + final float floatValue = val.floatValue(); + // if (Float.isNaN(floatValue) || Float.isInfinite(floatValue)) { + // return defaultValue; + // } + return floatValue; + } + + /** + * Get an optional int value associated with a key, or zero if there is no + * such key or if the value is not a number. If the value is a string, an + * attempt will be made to evaluate it as a number. + * + * @param key + * A key string. + * @return An object which is the value. + */ + public int optInt(String key) { + return this.optInt(key, 0); + } + + /** + * Get an optional int value associated with a key, or the default if there + * is no such key or if the value is not a number. If the value is a string, + * an attempt will be made to evaluate it as a number. + * + * @param key + * A key string. + * @param defaultValue + * The default. + * @return An object which is the value. + */ + public int optInt(String key, int defaultValue) { + final Number val = this.optNumber(key, null); + if (val == null) { + return defaultValue; + } + return val.intValue(); + } + + /** + * Get an optional JSONArray associated with a key. It returns null if there + * is no such key, or if its value is not a JSONArray. + * + * @param key + * A key string. + * @return A JSONArray which is the value. + */ + public JSONArray optJSONArray(String key) { + Object o = this.opt(key); + return o instanceof JSONArray ? (JSONArray) o : null; + } + + /** + * Get an optional JSONObject associated with a key. It returns null if + * there is no such key, or if its value is not a JSONObject. + * + * @param key + * A key string. + * @return A JSONObject which is the value. + */ + public JSONObject optJSONObject(String key) { return this.optJSONObject(key, null); } + + /** + * Get an optional JSONObject associated with a key, or the default if there + * is no such key or if the value is not a JSONObject. + * + * @param key + * A key string. + * @param defaultValue + * The default. + * @return An JSONObject which is the value. + */ + public JSONObject optJSONObject(String key, JSONObject defaultValue) { + Object object = this.opt(key); + return object instanceof JSONObject ? (JSONObject) object : defaultValue; + } + + /** + * Get an optional long value associated with a key, or zero if there is no + * such key or if the value is not a number. If the value is a string, an + * attempt will be made to evaluate it as a number. + * + * @param key + * A key string. + * @return An object which is the value. + */ + public long optLong(String key) { + return this.optLong(key, 0); + } + + /** + * Get an optional long value associated with a key, or the default if there + * is no such key or if the value is not a number. If the value is a string, + * an attempt will be made to evaluate it as a number. + * + * @param key + * A key string. + * @param defaultValue + * The default. + * @return An object which is the value. + */ + public long optLong(String key, long defaultValue) { + final Number val = this.optNumber(key, null); + if (val == null) { + return defaultValue; + } + + return val.longValue(); + } + + /** + * Get an optional {@link Number} value associated with a key, or null + * if there is no such key or if the value is not a number. If the value is a string, + * an attempt will be made to evaluate it as a number ({@link BigDecimal}). This method + * would be used in cases where type coercion of the number value is unwanted. + * + * @param key + * A key string. + * @return An object which is the value. + */ + public Number optNumber(String key) { + return this.optNumber(key, null); + } + + /** + * Get an optional {@link Number} value associated with a key, or the default if there + * is no such key or if the value is not a number. If the value is a string, + * an attempt will be made to evaluate it as a number. This method + * would be used in cases where type coercion of the number value is unwanted. + * + * @param key + * A key string. + * @param defaultValue + * The default. + * @return An object which is the value. + */ + public Number optNumber(String key, Number defaultValue) { + Object val = this.opt(key); + if (NULL.equals(val)) { + return defaultValue; + } + if (val instanceof Number){ + return (Number) val; + } + + try { + return stringToNumber(val.toString()); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * Get an optional string associated with a key. It returns an empty string + * if there is no such key. If the value is not a string and is not null, + * then it is converted to a string. + * + * @param key + * A key string. + * @return A string which is the value. + */ + public String optString(String key) { + return this.optString(key, ""); + } + + /** + * Get an optional string associated with a key. It returns the defaultValue + * if there is no such key. + * + * @param key + * A key string. + * @param defaultValue + * The default. + * @return A string which is the value. + */ + public String optString(String key, String defaultValue) { + Object object = this.opt(key); + return NULL.equals(object) ? defaultValue : object.toString(); + } + + /** + * Populates the internal map of the JSONObject with the bean properties. The + * bean can not be recursive. + * + * @see JSONObject#JSONObject(Object) + * + * @param bean + * the bean + */ + private void populateMap(Object bean) { + populateMap(bean, Collections.newSetFromMap(new IdentityHashMap())); + } + + private void populateMap(Object bean, Set objectsRecord) { + Class klass = bean.getClass(); + + // If klass is a System class then set includeSuperClass to false. + + boolean includeSuperClass = klass.getClassLoader() != null; + + Method[] methods = includeSuperClass ? klass.getMethods() : klass.getDeclaredMethods(); + for (final Method method : methods) { + final int modifiers = method.getModifiers(); + if (Modifier.isPublic(modifiers) + && !Modifier.isStatic(modifiers) + && method.getParameterTypes().length == 0 + && !method.isBridge() + && method.getReturnType() != Void.TYPE + && isValidMethodName(method.getName())) { + final String key = getKeyNameFromMethod(method); + if (key != null && !key.isEmpty()) { + try { + final Object result = method.invoke(bean); + if (result != null) { + // check cyclic dependency and throw error if needed + // the wrap and populateMap combination method is + // itself DFS recursive + if (objectsRecord.contains(result)) { + throw recursivelyDefinedObjectException(key); + } + + objectsRecord.add(result); + + this.map.put(key, wrap(result, objectsRecord)); + + objectsRecord.remove(result); + + // we don't use the result anywhere outside of wrap + // if it's a resource we should be sure to close it + // after calling toString + if (result instanceof Closeable) { + try { + ((Closeable) result).close(); + } catch (IOException ignore) { + } + } + } + } catch (IllegalAccessException ignore) { + } catch (IllegalArgumentException ignore) { + } catch (InvocationTargetException ignore) { + } + } + } + } + } + + private static boolean isValidMethodName(String name) { + return !"getClass".equals(name) && !"getDeclaringClass".equals(name); + } + + private static String getKeyNameFromMethod(Method method) { + final int ignoreDepth = getAnnotationDepth(method, JSONPropertyIgnore.class); + if (ignoreDepth > 0) { + final int forcedNameDepth = getAnnotationDepth(method, JSONPropertyName.class); + if (forcedNameDepth < 0 || ignoreDepth <= forcedNameDepth) { + // the hierarchy asked to ignore, and the nearest name override + // was higher or non-existent + return null; + } + } + JSONPropertyName annotation = getAnnotation(method, JSONPropertyName.class); + if (annotation != null && annotation.value() != null && !annotation.value().isEmpty()) { + return annotation.value(); + } + String key; + final String name = method.getName(); + if (name.startsWith("get") && name.length() > 3) { + key = name.substring(3); + } else if (name.startsWith("is") && name.length() > 2) { + key = name.substring(2); + } else { + return null; + } + // if the first letter in the key is not uppercase, then skip. + // This is to maintain backwards compatibility before PR406 + // (https://github.com/stleary/JSON-java/pull/406/) + if (key.length() == 0 || Character.isLowerCase(key.charAt(0))) { + return null; + } + if (key.length() == 1) { + key = key.toLowerCase(Locale.ROOT); + } else if (!Character.isUpperCase(key.charAt(1))) { + key = key.substring(0, 1).toLowerCase(Locale.ROOT) + key.substring(1); + } + return key; + } + + /** + * Searches the class hierarchy to see if the method or it's super + * implementations and interfaces has the annotation. + * + * @param + * type of the annotation + * + * @param m + * method to check + * @param annotationClass + * annotation to look for + * @return the {@link Annotation} if the annotation exists on the current method + * or one of its super class definitions + */ + private static A getAnnotation(final Method m, final Class annotationClass) { + // if we have invalid data the result is null + if (m == null || annotationClass == null) { + return null; + } + + if (m.isAnnotationPresent(annotationClass)) { + return m.getAnnotation(annotationClass); + } + + // if we've already reached the Object class, return null; + Class c = m.getDeclaringClass(); + if (c.getSuperclass() == null) { + return null; + } + + // check directly implemented interfaces for the method being checked + for (Class i : c.getInterfaces()) { + try { + Method im = i.getMethod(m.getName(), m.getParameterTypes()); + return getAnnotation(im, annotationClass); + } catch (final SecurityException ex) { + continue; + } catch (final NoSuchMethodException ex) { + continue; + } + } + + try { + return getAnnotation( + c.getSuperclass().getMethod(m.getName(), m.getParameterTypes()), + annotationClass); + } catch (final SecurityException ex) { + return null; + } catch (final NoSuchMethodException ex) { + return null; + } + } + + /** + * Searches the class hierarchy to see if the method or it's super + * implementations and interfaces has the annotation. Returns the depth of the + * annotation in the hierarchy. + * + * @param m + * method to check + * @param annotationClass + * annotation to look for + * @return Depth of the annotation or -1 if the annotation is not on the method. + */ + private static int getAnnotationDepth(final Method m, final Class annotationClass) { + // if we have invalid data the result is -1 + if (m == null || annotationClass == null) { + return -1; + } + + if (m.isAnnotationPresent(annotationClass)) { + return 1; + } + + // if we've already reached the Object class, return -1; + Class c = m.getDeclaringClass(); + if (c.getSuperclass() == null) { + return -1; + } + + // check directly implemented interfaces for the method being checked + for (Class i : c.getInterfaces()) { + try { + Method im = i.getMethod(m.getName(), m.getParameterTypes()); + int d = getAnnotationDepth(im, annotationClass); + if (d > 0) { + // since the annotation was on the interface, add 1 + return d + 1; + } + } catch (final SecurityException ex) { + continue; + } catch (final NoSuchMethodException ex) { + continue; + } + } + + try { + int d = getAnnotationDepth( + c.getSuperclass().getMethod(m.getName(), m.getParameterTypes()), + annotationClass); + if (d > 0) { + // since the annotation was on the superclass, add 1 + return d + 1; + } + return -1; + } catch (final SecurityException ex) { + return -1; + } catch (final NoSuchMethodException ex) { + return -1; + } + } + + /** + * Put a key/boolean pair in the JSONObject. + * + * @param key + * A key string. + * @param value + * A boolean which is the value. + * @return this. + * @throws JSONException + * If the value is non-finite number. + * @throws NullPointerException + * If the key is null. + */ + public JSONObject put(String key, boolean value) throws JSONException { + return this.put(key, value ? Boolean.TRUE : Boolean.FALSE); + } + + /** + * Put a key/value pair in the JSONObject, where the value will be a + * JSONArray which is produced from a Collection. + * + * @param key + * A key string. + * @param value + * A Collection value. + * @return this. + * @throws JSONException + * If the value is non-finite number. + * @throws NullPointerException + * If the key is null. + */ + public JSONObject put(String key, Collection value) throws JSONException { + return this.put(key, new JSONArray(value)); + } + + /** + * Put a key/double pair in the JSONObject. + * + * @param key + * A key string. + * @param value + * A double which is the value. + * @return this. + * @throws JSONException + * If the value is non-finite number. + * @throws NullPointerException + * If the key is null. + */ + public JSONObject put(String key, double value) throws JSONException { + return this.put(key, Double.valueOf(value)); + } + + /** + * Put a key/float pair in the JSONObject. + * + * @param key + * A key string. + * @param value + * A float which is the value. + * @return this. + * @throws JSONException + * If the value is non-finite number. + * @throws NullPointerException + * If the key is null. + */ + public JSONObject put(String key, float value) throws JSONException { + return this.put(key, Float.valueOf(value)); + } + + /** + * Put a key/int pair in the JSONObject. + * + * @param key + * A key string. + * @param value + * An int which is the value. + * @return this. + * @throws JSONException + * If the value is non-finite number. + * @throws NullPointerException + * If the key is null. + */ + public JSONObject put(String key, int value) throws JSONException { + return this.put(key, Integer.valueOf(value)); + } + + /** + * Put a key/long pair in the JSONObject. + * + * @param key + * A key string. + * @param value + * A long which is the value. + * @return this. + * @throws JSONException + * If the value is non-finite number. + * @throws NullPointerException + * If the key is null. + */ + public JSONObject put(String key, long value) throws JSONException { + return this.put(key, Long.valueOf(value)); + } + + /** + * Put a key/value pair in the JSONObject, where the value will be a + * JSONObject which is produced from a Map. + * + * @param key + * A key string. + * @param value + * A Map value. + * @return this. + * @throws JSONException + * If the value is non-finite number. + * @throws NullPointerException + * If the key is null. + */ + public JSONObject put(String key, Map value) throws JSONException { + return this.put(key, new JSONObject(value)); + } + + /** + * Put a key/value pair in the JSONObject. If the value is null, then the + * key will be removed from the JSONObject if it is present. + * + * @param key + * A key string. + * @param value + * An object which is the value. It should be of one of these + * types: Boolean, Double, Integer, JSONArray, JSONObject, Long, + * String, or the JSONObject.NULL object. + * @return this. + * @throws JSONException + * If the value is non-finite number. + * @throws NullPointerException + * If the key is null. + */ + public JSONObject put(String key, Object value) throws JSONException { + if (key == null) { + throw new NullPointerException("Null key."); + } + if (value != null) { + testValidity(value); + this.map.put(key, value); + } else { + this.remove(key); + } + return this; + } + + /** + * Put a key/value pair in the JSONObject, but only if the key and the value + * are both non-null, and only if there is not already a member with that + * name. + * + * @param key + * key to insert into + * @param value + * value to insert + * @return this. + * @throws JSONException + * if the key is a duplicate + */ + public JSONObject putOnce(String key, Object value) throws JSONException { + if (key != null && value != null) { + if (this.opt(key) != null) { + throw new JSONException("Duplicate key \"" + key + "\""); + } + return this.put(key, value); + } + return this; + } + + /** + * Put a key/value pair in the JSONObject, but only if the key and the value + * are both non-null. + * + * @param key + * A key string. + * @param value + * An object which is the value. It should be of one of these + * types: Boolean, Double, Integer, JSONArray, JSONObject, Long, + * String, or the JSONObject.NULL object. + * @return this. + * @throws JSONException + * If the value is a non-finite number. + */ + public JSONObject putOpt(String key, Object value) throws JSONException { + if (key != null && value != null) { + return this.put(key, value); + } + return this; + } + + /** + * Creates a JSONPointer using an initialization string and tries to + * match it to an item within this JSONObject. For example, given a + * JSONObject initialized with this document: + *
+     * {
+     *     "a":{"b":"c"}
+     * }
+     * 
+ * and this JSONPointer string: + *
+     * "/a/b"
+     * 
+ * Then this method will return the String "c". + * A JSONPointerException may be thrown from code called by this method. + * + * @param jsonPointer string that can be used to create a JSONPointer + * @return the item matched by the JSONPointer, otherwise null + */ + public Object query(String jsonPointer) { + return query(new JSONPointer(jsonPointer)); + } + /** + * Uses a user initialized JSONPointer and tries to + * match it to an item within this JSONObject. For example, given a + * JSONObject initialized with this document: + *
+     * {
+     *     "a":{"b":"c"}
+     * }
+     * 
+ * and this JSONPointer: + *
+     * "/a/b"
+     * 
+ * Then this method will return the String "c". + * A JSONPointerException may be thrown from code called by this method. + * + * @param jsonPointer string that can be used to create a JSONPointer + * @return the item matched by the JSONPointer, otherwise null + */ + public Object query(JSONPointer jsonPointer) { + return jsonPointer.queryFrom(this); + } + + /** + * Queries and returns a value from this object using {@code jsonPointer}, or + * returns null if the query fails due to a missing key. + * + * @param jsonPointer the string representation of the JSON pointer + * @return the queried value or {@code null} + * @throws IllegalArgumentException if {@code jsonPointer} has invalid syntax + */ + public Object optQuery(String jsonPointer) { + return optQuery(new JSONPointer(jsonPointer)); + } + + /** + * Queries and returns a value from this object using {@code jsonPointer}, or + * returns null if the query fails due to a missing key. + * + * @param jsonPointer The JSON pointer + * @return the queried value or {@code null} + * @throws IllegalArgumentException if {@code jsonPointer} has invalid syntax + */ + public Object optQuery(JSONPointer jsonPointer) { + try { + return jsonPointer.queryFrom(this); + } catch (JSONPointerException e) { + return null; + } + } + + /** + * Produce a string in double quotes with backslash sequences in all the + * right places. A backslash will be inserted within </, producing + * <\/, allowing JSON text to be delivered in HTML. In JSON text, a + * string cannot contain a control character or an unescaped quote or + * backslash. + * + * @param string + * A String + * @return A String correctly formatted for insertion in a JSON text. + */ + public static String quote(String string) { + StringWriter sw = new StringWriter(); + synchronized (sw.getBuffer()) { + try { + return quote(string, sw).toString(); + } catch (IOException ignored) { + // will never happen - we are writing to a string writer + return ""; + } + } + } + + public static Writer quote(String string, Writer w) throws IOException { + if (string == null || string.isEmpty()) { + w.write("\"\""); + return w; + } + + char b; + char c = 0; + String hhhh; + int i; + int len = string.length(); + + w.write('"'); + for (i = 0; i < len; i += 1) { + b = c; + c = string.charAt(i); + switch (c) { + case '\\': + case '"': + w.write('\\'); + w.write(c); + break; + case '/': + if (b == '<') { + w.write('\\'); + } + w.write(c); + break; + case '\b': + w.write("\\b"); + break; + case '\t': + w.write("\\t"); + break; + case '\n': + w.write("\\n"); + break; + case '\f': + w.write("\\f"); + break; + case '\r': + w.write("\\r"); + break; + default: + if (c < ' ' || (c >= '\u0080' && c < '\u00a0') + || (c >= '\u2000' && c < '\u2100')) { + w.write("\\u"); + hhhh = Integer.toHexString(c); + w.write("0000", 0, 4 - hhhh.length()); + w.write(hhhh); + } else { + w.write(c); + } + } + } + w.write('"'); + return w; + } + + /** + * Remove a name and its value, if present. + * + * @param key + * The name to be removed. + * @return The value that was associated with the name, or null if there was + * no value. + */ + public Object remove(String key) { + return this.map.remove(key); + } + + /** + * Determine if two JSONObjects are similar. + * They must contain the same set of names which must be associated with + * similar values. + * + * @param other The other JSONObject + * @return true if they are equal + */ + public boolean similar(Object other) { + try { + if (!(other instanceof JSONObject)) { + return false; + } + if (!this.keySet().equals(((JSONObject)other).keySet())) { + return false; + } + for (final Entry entry : this.entrySet()) { + String name = entry.getKey(); + Object valueThis = entry.getValue(); + Object valueOther = ((JSONObject)other).get(name); + if(valueThis == valueOther) { + continue; + } + if(valueThis == null) { + return false; + } + if (valueThis instanceof JSONObject) { + if (!((JSONObject)valueThis).similar(valueOther)) { + return false; + } + } else if (valueThis instanceof JSONArray) { + if (!((JSONArray)valueThis).similar(valueOther)) { + return false; + } + } else if (valueThis instanceof Number && valueOther instanceof Number) { + if (!isNumberSimilar((Number)valueThis, (Number)valueOther)) { + return false; + }; + } else if (!valueThis.equals(valueOther)) { + return false; + } + } + return true; + } catch (Throwable exception) { + return false; + } + } + + /** + * Compares two numbers to see if they are similar. + * + * If either of the numbers are Double or Float instances, then they are checked to have + * a finite value. If either value is not finite (NaN or ±infinity), then this + * function will always return false. If both numbers are finite, they are first checked + * to be the same type and implement {@link Comparable}. If they do, then the actual + * {@link Comparable#compareTo(Object)} is called. If they are not the same type, or don't + * implement Comparable, then they are converted to {@link BigDecimal}s. Finally the + * BigDecimal values are compared using {@link BigDecimal#compareTo(BigDecimal)}. + * + * @param l the Left value to compare. Can not be null. + * @param r the right value to compare. Can not be null. + * @return true if the numbers are similar, false otherwise. + */ + static boolean isNumberSimilar(Number l, Number r) { + if (!numberIsFinite(l) || !numberIsFinite(r)) { + // non-finite numbers are never similar + return false; + } + + // if the classes are the same and implement Comparable + // then use the built in compare first. + if(l.getClass().equals(r.getClass()) && l instanceof Comparable) { + @SuppressWarnings({ "rawtypes", "unchecked" }) + int compareTo = ((Comparable)l).compareTo(r); + return compareTo==0; + } + + // BigDecimal should be able to handle all of our number types that we support through + // documentation. Convert to BigDecimal first, then use the Compare method to + // decide equality. + final BigDecimal lBigDecimal = objectToBigDecimal(l, null, false); + final BigDecimal rBigDecimal = objectToBigDecimal(r, null, false); + if (lBigDecimal == null || rBigDecimal == null) { + return false; + } + return lBigDecimal.compareTo(rBigDecimal) == 0; + } + + private static boolean numberIsFinite(Number n) { + if (n instanceof Double && (((Double) n).isInfinite() || ((Double) n).isNaN())) { + return false; + } else if (n instanceof Float && (((Float) n).isInfinite() || ((Float) n).isNaN())) { + return false; + } + return true; + } + + /** + * Tests if the value should be tried as a decimal. It makes no test if there are actual digits. + * + * @param val value to test + * @return true if the string is "-0" or if it contains '.', 'e', or 'E', false otherwise. + */ + protected static boolean isDecimalNotation(final String val) { + return val.indexOf('.') > -1 || val.indexOf('e') > -1 + || val.indexOf('E') > -1 || "-0".equals(val); + } + + /** + * Converts a string to a number using the narrowest possible type. Possible + * returns for this function are BigDecimal, Double, BigInteger, Long, and Integer. + * When a Double is returned, it should always be a valid Double and not NaN or +-infinity. + * + * @param val value to convert + * @return Number representation of the value. + * @throws NumberFormatException thrown if the value is not a valid number. A public + * caller should catch this and wrap it in a {@link JSONException} if applicable. + */ + protected static Number stringToNumber(final String val) throws NumberFormatException { + char initial = val.charAt(0); + if ((initial >= '0' && initial <= '9') || initial == '-') { + // decimal representation + if (isDecimalNotation(val)) { + // Use a BigDecimal all the time so we keep the original + // representation. BigDecimal doesn't support -0.0, ensure we + // keep that by forcing a decimal. + try { + BigDecimal bd = new BigDecimal(val); + if(initial == '-' && BigDecimal.ZERO.compareTo(bd)==0) { + return Double.valueOf(-0.0); + } + return bd; + } catch (NumberFormatException retryAsDouble) { + // this is to support "Hex Floats" like this: 0x1.0P-1074 + try { + Double d = Double.valueOf(val); + if(d.isNaN() || d.isInfinite()) { + throw new NumberFormatException("val ["+val+"] is not a valid number."); + } + return d; + } catch (NumberFormatException ignore) { + throw new NumberFormatException("val ["+val+"] is not a valid number."); + } + } + } + // block items like 00 01 etc. Java number parsers treat these as Octal. + if(initial == '0' && val.length() > 1) { + char at1 = val.charAt(1); + if(at1 >= '0' && at1 <= '9') { + throw new NumberFormatException("val ["+val+"] is not a valid number."); + } + } else if (initial == '-' && val.length() > 2) { + char at1 = val.charAt(1); + char at2 = val.charAt(2); + if(at1 == '0' && at2 >= '0' && at2 <= '9') { + throw new NumberFormatException("val ["+val+"] is not a valid number."); + } + } + // integer representation. + // This will narrow any values to the smallest reasonable Object representation + // (Integer, Long, or BigInteger) + + // BigInteger down conversion: We use a similar bitLength compare as + // BigInteger#intValueExact uses. Increases GC, but objects hold + // only what they need. i.e. Less runtime overhead if the value is + // long lived. + BigInteger bi = new BigInteger(val); + if(bi.bitLength() <= 31){ + return Integer.valueOf(bi.intValue()); + } + if(bi.bitLength() <= 63){ + return Long.valueOf(bi.longValue()); + } + return bi; + } + throw new NumberFormatException("val ["+val+"] is not a valid number."); + } + + /** + * Try to convert a string into a number, boolean, or null. If the string + * can't be converted, return the string. + * + * @param string + * A String. can not be null. + * @return A simple JSON value. + * @throws NullPointerException + * Thrown if the string is null. + */ + // Changes to this method must be copied to the corresponding method in + // the XML class to keep full support for Android + public static Object stringToValue(String string) { + if ("".equals(string)) { + return string; + } + + // check JSON key words true/false/null + if ("true".equalsIgnoreCase(string)) { + return Boolean.TRUE; + } + if ("false".equalsIgnoreCase(string)) { + return Boolean.FALSE; + } + if ("null".equalsIgnoreCase(string)) { + return JSONObject.NULL; + } + + /* + * If it might be a number, try converting it. If a number cannot be + * produced, then the value will just be a string. + */ + + char initial = string.charAt(0); + if ((initial >= '0' && initial <= '9') || initial == '-') { + try { + return stringToNumber(string); + } catch (Exception ignore) { + } + } + return string; + } + + /** + * Throw an exception if the object is a NaN or infinite number. + * + * @param o + * The object to test. + * @throws JSONException + * If o is a non-finite number. + */ + public static void testValidity(Object o) throws JSONException { + if (o instanceof Number && !numberIsFinite((Number) o)) { + throw new JSONException("JSON does not allow non-finite numbers."); + } + } + + /** + * Produce a JSONArray containing the values of the members of this + * JSONObject. + * + * @param names + * A JSONArray containing a list of key strings. This determines + * the sequence of the values in the result. + * @return A JSONArray of values. + * @throws JSONException + * If any of the values are non-finite numbers. + */ + public JSONArray toJSONArray(JSONArray names) throws JSONException { + if (names == null || names.isEmpty()) { + return null; + } + JSONArray ja = new JSONArray(); + for (int i = 0; i < names.length(); i += 1) { + ja.put(this.opt(names.getString(i))); + } + return ja; + } + + /** + * Make a JSON text of this JSONObject. For compactness, no whitespace is + * added. If this would not result in a syntactically correct JSON text, + * then null will be returned instead. + *

+ * Warning: This method assumes that the data structure is acyclical. + * + * + * @return a printable, displayable, portable, transmittable representation + * of the object, beginning with { (left + * brace) and ending with } (right + * brace). + */ + @Override + public String toString() { + try { + return this.toString(0); + } catch (Exception e) { + return null; + } + } + + /** + * Make a pretty-printed JSON text of this JSONObject. + * + *

If

{@code indentFactor > 0}
and the {@link JSONObject} + * has only one key, then the object will be output on a single line: + *
{@code {"key": 1}}
+ * + *

If an object has 2 or more keys, then it will be output across + * multiple lines:

{@code {
+     *  "key1": 1,
+     *  "key2": "value 2",
+     *  "key3": 3
+     * }}
+ *

+ * Warning: This method assumes that the data structure is acyclical. + * + * + * @param indentFactor + * The number of spaces to add to each level of indentation. + * @return a printable, displayable, portable, transmittable representation + * of the object, beginning with { (left + * brace) and ending with } (right + * brace). + * @throws JSONException + * If the object contains an invalid number. + */ + public String toString(int indentFactor) throws JSONException { + StringWriter w = new StringWriter(); + synchronized (w.getBuffer()) { + return this.write(w, indentFactor, 0).toString(); + } + } + + /** + * Make a JSON text of an Object value. If the object has an + * value.toJSONString() method, then that method will be used to produce the + * JSON text. The method is required to produce a strictly conforming text. + * If the object does not contain a toJSONString method (which is the most + * common case), then a text will be produced by other means. If the value + * is an array or Collection, then a JSONArray will be made from it and its + * toJSONString method will be called. If the value is a MAP, then a + * JSONObject will be made from it and its toJSONString method will be + * called. Otherwise, the value's toString method will be called, and the + * result will be quoted. + * + *

+ * Warning: This method assumes that the data structure is acyclical. + * + * @param value + * The value to be serialized. + * @return a printable, displayable, transmittable representation of the + * object, beginning with { (left + * brace) and ending with } (right + * brace). + * @throws JSONException + * If the value is or contains an invalid number. + */ + public static String valueToString(Object value) throws JSONException { + // moves the implementation to JSONWriter as: + // 1. It makes more sense to be part of the writer class + // 2. For Android support this method is not available. By implementing it in the Writer + // Android users can use the writer with the built in Android JSONObject implementation. + return JSONWriter.valueToString(value); + } + + /** + * Wrap an object, if necessary. If the object is null, return the NULL + * object. If it is an array or collection, wrap it in a JSONArray. If it is + * a map, wrap it in a JSONObject. If it is a standard property (Double, + * String, et al) then it is already wrapped. Otherwise, if it comes from + * one of the java packages, turn it into a string. And if it doesn't, try + * to wrap it in a JSONObject. If the wrapping fails, then null is returned. + * + * @param object + * The object to wrap + * @return The wrapped value + */ + public static Object wrap(Object object) { + return wrap(object, null); + } + + private static Object wrap(Object object, Set objectsRecord) { + try { + if (NULL.equals(object)) { + return NULL; + } + if (object instanceof JSONObject || object instanceof JSONArray + || NULL.equals(object) || object instanceof JSONString + || object instanceof Byte || object instanceof Character + || object instanceof Short || object instanceof Integer + || object instanceof Long || object instanceof Boolean + || object instanceof Float || object instanceof Double + || object instanceof String || object instanceof BigInteger + || object instanceof BigDecimal || object instanceof Enum) { + return object; + } + + if (object instanceof Collection) { + Collection coll = (Collection) object; + return new JSONArray(coll); + } + if (object.getClass().isArray()) { + return new JSONArray(object); + } + if (object instanceof Map) { + Map map = (Map) object; + return new JSONObject(map); + } + Package objectPackage = object.getClass().getPackage(); + String objectPackageName = objectPackage != null ? objectPackage + .getName() : ""; + if (objectPackageName.startsWith("java.") + || objectPackageName.startsWith("javax.") + || object.getClass().getClassLoader() == null) { + return object.toString(); + } + if (objectsRecord != null) { + return new JSONObject(object, objectsRecord); + } + else { + return new JSONObject(object); + } + } + catch (JSONException exception) { + throw exception; + } catch (Exception exception) { + return null; + } + } + + /** + * Write the contents of the JSONObject as JSON text to a writer. For + * compactness, no whitespace is added. + *

+ * Warning: This method assumes that the data structure is acyclical. + * + * @param writer the writer object + * @return The writer. + * @throws JSONException if a called function has an error + */ + public Writer write(Writer writer) throws JSONException { + return this.write(writer, 0, 0); + } + + static final Writer writeValue(Writer writer, Object value, + int indentFactor, int indent) throws JSONException, IOException { + if (value == null || value.equals(null)) { + writer.write("null"); + } else if (value instanceof JSONString) { + Object o; + try { + o = ((JSONString) value).toJSONString(); + } catch (Exception e) { + throw new JSONException(e); + } + writer.write(o != null ? o.toString() : quote(value.toString())); + } else if (value instanceof Number) { + // not all Numbers may match actual JSON Numbers. i.e. fractions or Imaginary + final String numberAsString = numberToString((Number) value); + if(NUMBER_PATTERN.matcher(numberAsString).matches()) { + writer.write(numberAsString); + } else { + // The Number value is not a valid JSON number. + // Instead we will quote it as a string + quote(numberAsString, writer); + } + } else if (value instanceof Boolean) { + writer.write(value.toString()); + } else if (value instanceof Enum) { + writer.write(quote(((Enum)value).name())); + } else if (value instanceof JSONObject) { + ((JSONObject) value).write(writer, indentFactor, indent); + } else if (value instanceof JSONArray) { + ((JSONArray) value).write(writer, indentFactor, indent); + } else if (value instanceof Map) { + Map map = (Map) value; + new JSONObject(map).write(writer, indentFactor, indent); + } else if (value instanceof Collection) { + Collection coll = (Collection) value; + new JSONArray(coll).write(writer, indentFactor, indent); + } else if (value.getClass().isArray()) { + new JSONArray(value).write(writer, indentFactor, indent); + } else { + quote(value.toString(), writer); + } + return writer; + } + + static final void indent(Writer writer, int indent) throws IOException { + for (int i = 0; i < indent; i += 1) { + writer.write(' '); + } + } + + /** + * Write the contents of the JSONObject as JSON text to a writer. + * + *

If

{@code indentFactor > 0}
and the {@link JSONObject} + * has only one key, then the object will be output on a single line: + *
{@code {"key": 1}}
+ * + *

If an object has 2 or more keys, then it will be output across + * multiple lines:

{@code {
+     *  "key1": 1,
+     *  "key2": "value 2",
+     *  "key3": 3
+     * }}
+ *

+ * Warning: This method assumes that the data structure is acyclical. + * + * + * @param writer + * Writes the serialized JSON + * @param indentFactor + * The number of spaces to add to each level of indentation. + * @param indent + * The indentation of the top level. + * @return The writer. + * @throws JSONException if a called function has an error or a write error + * occurs + */ + public Writer write(Writer writer, int indentFactor, int indent) + throws JSONException { + try { + boolean needsComma = false; + final int length = this.length(); + writer.write('{'); + + if (length == 1) { + final Entry entry = this.entrySet().iterator().next(); + final String key = entry.getKey(); + writer.write(quote(key)); + writer.write(':'); + if (indentFactor > 0) { + writer.write(' '); + } + try{ + writeValue(writer, entry.getValue(), indentFactor, indent); + } catch (Exception e) { + throw new JSONException("Unable to write JSONObject value for key: " + key, e); + } + } else if (length != 0) { + final int newIndent = indent + indentFactor; + for (final Entry entry : this.entrySet()) { + if (needsComma) { + writer.write(','); + } + if (indentFactor > 0) { + writer.write('\n'); + } + indent(writer, newIndent); + final String key = entry.getKey(); + writer.write(quote(key)); + writer.write(':'); + if (indentFactor > 0) { + writer.write(' '); + } + try { + writeValue(writer, entry.getValue(), indentFactor, newIndent); + } catch (Exception e) { + throw new JSONException("Unable to write JSONObject value for key: " + key, e); + } + needsComma = true; + } + if (indentFactor > 0) { + writer.write('\n'); + } + indent(writer, indent); + } + writer.write('}'); + return writer; + } catch (IOException exception) { + throw new JSONException(exception); + } + } + + /** + * Returns a java.util.Map containing all of the entries in this object. + * If an entry in the object is a JSONArray or JSONObject it will also + * be converted. + *

+ * Warning: This method assumes that the data structure is acyclical. + * + * @return a java.util.Map containing the entries of this object + */ + public Map toMap() { + Map results = new HashMap(); + for (Entry entry : this.entrySet()) { + Object value; + if (entry.getValue() == null || NULL.equals(entry.getValue())) { + value = null; + } else if (entry.getValue() instanceof JSONObject) { + value = ((JSONObject) entry.getValue()).toMap(); + } else if (entry.getValue() instanceof JSONArray) { + value = ((JSONArray) entry.getValue()).toList(); + } else { + value = entry.getValue(); + } + results.put(entry.getKey(), value); + } + return results; + } + + /** + * Create a new JSONException in a common format for incorrect conversions. + * @param key name of the key + * @param valueType the type of value being coerced to + * @param cause optional cause of the coercion failure + * @return JSONException that can be thrown. + */ + private static JSONException wrongValueFormatException( + String key, + String valueType, + Throwable cause) { + return new JSONException( + "JSONObject[" + quote(key) + "] is not a " + valueType + "." + , cause); + } + + /** + * Create a new JSONException in a common format for incorrect conversions. + * @param key name of the key + * @param valueType the type of value being coerced to + * @param cause optional cause of the coercion failure + * @return JSONException that can be thrown. + */ + private static JSONException wrongValueFormatException( + String key, + String valueType, + Object value, + Throwable cause) { + return new JSONException( + "JSONObject[" + quote(key) + "] is not a " + valueType + " (" + value + ")." + , cause); + } + + /** + * Create a new JSONException in a common format for recursive object definition. + * @param key name of the key + * @return JSONException that can be thrown. + */ + private static JSONException recursivelyDefinedObjectException(String key) { + return new JSONException( + "JavaBean object contains recursively defined member variable of key " + quote(key) + ); + } +} diff --git a/src/main/java/org/json/JSONPointer.java b/src/main/java/org/json/JSONPointer.java new file mode 100644 index 0000000..f1f7f33 --- /dev/null +++ b/src/main/java/org/json/JSONPointer.java @@ -0,0 +1,295 @@ +package org.json; + +import static java.lang.String.format; + +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/* +Copyright (c) 2002 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +/** + * A JSON Pointer is a simple query language defined for JSON documents by + * RFC 6901. + * + * In a nutshell, JSONPointer allows the user to navigate into a JSON document + * using strings, and retrieve targeted objects, like a simple form of XPATH. + * Path segments are separated by the '/' char, which signifies the root of + * the document when it appears as the first char of the string. Array + * elements are navigated using ordinals, counting from 0. JSONPointer strings + * may be extended to any arbitrary number of segments. If the navigation + * is successful, the matched item is returned. A matched item may be a + * JSONObject, a JSONArray, or a JSON value. If the JSONPointer string building + * fails, an appropriate exception is thrown. If the navigation fails to find + * a match, a JSONPointerException is thrown. + * + * @author JSON.org + * @version 2016-05-14 + */ +public class JSONPointer { + + // used for URL encoding and decoding + private static final String ENCODING = "utf-8"; + + /** + * This class allows the user to build a JSONPointer in steps, using + * exactly one segment in each step. + */ + public static class Builder { + + // Segments for the eventual JSONPointer string + private final List refTokens = new ArrayList(); + + /** + * Creates a {@code JSONPointer} instance using the tokens previously set using the + * {@link #append(String)} method calls. + * @return a JSONPointer object + */ + public JSONPointer build() { + return new JSONPointer(this.refTokens); + } + + /** + * Adds an arbitrary token to the list of reference tokens. It can be any non-null value. + * + * Unlike in the case of JSON string or URI fragment representation of JSON pointers, the + * argument of this method MUST NOT be escaped. If you want to query the property called + * {@code "a~b"} then you should simply pass the {@code "a~b"} string as-is, there is no + * need to escape it as {@code "a~0b"}. + * + * @param token the new token to be appended to the list + * @return {@code this} + * @throws NullPointerException if {@code token} is null + */ + public Builder append(String token) { + if (token == null) { + throw new NullPointerException("token cannot be null"); + } + this.refTokens.add(token); + return this; + } + + /** + * Adds an integer to the reference token list. Although not necessarily, mostly this token will + * denote an array index. + * + * @param arrayIndex the array index to be added to the token list + * @return {@code this} + */ + public Builder append(int arrayIndex) { + this.refTokens.add(String.valueOf(arrayIndex)); + return this; + } + } + + /** + * Static factory method for {@link Builder}. Example usage: + * + *


+     * JSONPointer pointer = JSONPointer.builder()
+     *       .append("obj")
+     *       .append("other~key").append("another/key")
+     *       .append("\"")
+     *       .append(0)
+     *       .build();
+     * 
+ * + * @return a builder instance which can be used to construct a {@code JSONPointer} instance by chained + * {@link Builder#append(String)} calls. + */ + public static Builder builder() { + return new Builder(); + } + + // Segments for the JSONPointer string + private final List refTokens; + + /** + * Pre-parses and initializes a new {@code JSONPointer} instance. If you want to + * evaluate the same JSON Pointer on different JSON documents then it is recommended + * to keep the {@code JSONPointer} instances due to performance considerations. + * + * @param pointer the JSON String or URI Fragment representation of the JSON pointer. + * @throws IllegalArgumentException if {@code pointer} is not a valid JSON pointer + */ + public JSONPointer(final String pointer) { + if (pointer == null) { + throw new NullPointerException("pointer cannot be null"); + } + if (pointer.isEmpty() || pointer.equals("#")) { + this.refTokens = Collections.emptyList(); + return; + } + String refs; + if (pointer.startsWith("#/")) { + refs = pointer.substring(2); + try { + refs = URLDecoder.decode(refs, ENCODING); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } else if (pointer.startsWith("/")) { + refs = pointer.substring(1); + } else { + throw new IllegalArgumentException("a JSON pointer should start with '/' or '#/'"); + } + this.refTokens = new ArrayList(); + int slashIdx = -1; + int prevSlashIdx = 0; + do { + prevSlashIdx = slashIdx + 1; + slashIdx = refs.indexOf('/', prevSlashIdx); + if(prevSlashIdx == slashIdx || prevSlashIdx == refs.length()) { + // found 2 slashes in a row ( obj//next ) + // or single slash at the end of a string ( obj/test/ ) + this.refTokens.add(""); + } else if (slashIdx >= 0) { + final String token = refs.substring(prevSlashIdx, slashIdx); + this.refTokens.add(unescape(token)); + } else { + // last item after separator, or no separator at all. + final String token = refs.substring(prevSlashIdx); + this.refTokens.add(unescape(token)); + } + } while (slashIdx >= 0); + // using split does not take into account consecutive separators or "ending nulls" + //for (String token : refs.split("/")) { + // this.refTokens.add(unescape(token)); + //} + } + + public JSONPointer(List refTokens) { + this.refTokens = new ArrayList(refTokens); + } + + /** + * @see rfc6901 section 3 + */ + private static String unescape(String token) { + return token.replace("~1", "/").replace("~0", "~"); + } + + /** + * Evaluates this JSON Pointer on the given {@code document}. The {@code document} + * is usually a {@link JSONObject} or a {@link JSONArray} instance, but the empty + * JSON Pointer ({@code ""}) can be evaluated on any JSON values and in such case the + * returned value will be {@code document} itself. + * + * @param document the JSON document which should be the subject of querying. + * @return the result of the evaluation + * @throws JSONPointerException if an error occurs during evaluation + */ + public Object queryFrom(Object document) throws JSONPointerException { + if (this.refTokens.isEmpty()) { + return document; + } + Object current = document; + for (String token : this.refTokens) { + if (current instanceof JSONObject) { + current = ((JSONObject) current).opt(unescape(token)); + } else if (current instanceof JSONArray) { + current = readByIndexToken(current, token); + } else { + throw new JSONPointerException(format( + "value [%s] is not an array or object therefore its key %s cannot be resolved", current, + token)); + } + } + return current; + } + + /** + * Matches a JSONArray element by ordinal position + * @param current the JSONArray to be evaluated + * @param indexToken the array index in string form + * @return the matched object. If no matching item is found a + * @throws JSONPointerException is thrown if the index is out of bounds + */ + private static Object readByIndexToken(Object current, String indexToken) throws JSONPointerException { + try { + int index = Integer.parseInt(indexToken); + JSONArray currentArr = (JSONArray) current; + if (index >= currentArr.length()) { + throw new JSONPointerException(format("index %s is out of bounds - the array has %d elements", indexToken, + Integer.valueOf(currentArr.length()))); + } + try { + return currentArr.get(index); + } catch (JSONException e) { + throw new JSONPointerException("Error reading value at index position " + index, e); + } + } catch (NumberFormatException e) { + throw new JSONPointerException(format("%s is not an array index", indexToken), e); + } + } + + /** + * Returns a string representing the JSONPointer path value using string + * representation + */ + @Override + public String toString() { + StringBuilder rval = new StringBuilder(""); + for (String token: this.refTokens) { + rval.append('/').append(escape(token)); + } + return rval.toString(); + } + + /** + * Escapes path segment values to an unambiguous form. + * The escape char to be inserted is '~'. The chars to be escaped + * are ~, which maps to ~0, and /, which maps to ~1. + * @param token the JSONPointer segment value to be escaped + * @return the escaped value for the token + * + * @see rfc6901 section 3 + */ + private static String escape(String token) { + return token.replace("~", "~0") + .replace("/", "~1"); + } + + /** + * Returns a string representing the JSONPointer path value using URI + * fragment identifier representation + * @return a uri fragment string + */ + public String toURIFragment() { + try { + StringBuilder rval = new StringBuilder("#"); + for (String token : this.refTokens) { + rval.append('/').append(URLEncoder.encode(token, ENCODING)); + } + return rval.toString(); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } + +} diff --git a/src/main/java/org/json/JSONPointerException.java b/src/main/java/org/json/JSONPointerException.java new file mode 100644 index 0000000..0ce1aeb --- /dev/null +++ b/src/main/java/org/json/JSONPointerException.java @@ -0,0 +1,45 @@ +package org.json; + +/* +Copyright (c) 2002 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +/** + * The JSONPointerException is thrown by {@link JSONPointer} if an error occurs + * during evaluating a pointer. + * + * @author JSON.org + * @version 2016-05-13 + */ +public class JSONPointerException extends JSONException { + private static final long serialVersionUID = 8872944667561856751L; + + public JSONPointerException(String message) { + super(message); + } + + public JSONPointerException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/src/main/java/org/json/JSONPropertyIgnore.java b/src/main/java/org/json/JSONPropertyIgnore.java new file mode 100644 index 0000000..682de74 --- /dev/null +++ b/src/main/java/org/json/JSONPropertyIgnore.java @@ -0,0 +1,43 @@ +package org.json; + +/* +Copyright (c) 2018 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +@Documented +@Retention(RUNTIME) +@Target({METHOD}) +/** + * Use this annotation on a getter method to override the Bean name + * parser for Bean -> JSONObject mapping. If this annotation is + * present at any level in the class hierarchy, then the method will + * not be serialized from the bean into the JSONObject. + */ +public @interface JSONPropertyIgnore { } diff --git a/src/main/java/org/json/JSONPropertyName.java b/src/main/java/org/json/JSONPropertyName.java new file mode 100644 index 0000000..a1bcd58 --- /dev/null +++ b/src/main/java/org/json/JSONPropertyName.java @@ -0,0 +1,47 @@ +package org.json; + +/* +Copyright (c) 2018 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +@Documented +@Retention(RUNTIME) +@Target({METHOD}) +/** + * Use this annotation on a getter method to override the Bean name + * parser for Bean -> JSONObject mapping. A value set to empty string "" + * will have the Bean parser fall back to the default field name processing. + */ +public @interface JSONPropertyName { + /** + * @return The name of the property as to be used in the JSON Object. + */ + String value(); +} diff --git a/src/main/java/org/json/JSONString.java b/src/main/java/org/json/JSONString.java new file mode 100644 index 0000000..bcd9a81 --- /dev/null +++ b/src/main/java/org/json/JSONString.java @@ -0,0 +1,43 @@ +package org.json; + +/* +Copyright (c) 2002 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ + +/** + * The JSONString interface allows a toJSONString() + * method so that a class can change the behavior of + * JSONObject.toString(), JSONArray.toString(), + * and JSONWriter.value(Object). The + * toJSONString method will be used instead of the default behavior + * of using the Object's toString() method and quoting the result. + */ +public interface JSONString { + /** + * The toJSONString method allows a class to produce its own JSON + * serialization. + * + * @return A strictly syntactically correct JSON text. + */ + public String toJSONString(); +} diff --git a/src/main/java/org/json/JSONStringer.java b/src/main/java/org/json/JSONStringer.java new file mode 100644 index 0000000..d2a4dfb --- /dev/null +++ b/src/main/java/org/json/JSONStringer.java @@ -0,0 +1,79 @@ +package org.json; + +/* +Copyright (c) 2006 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +import java.io.StringWriter; + +/** + * JSONStringer provides a quick and convenient way of producing JSON text. + * The texts produced strictly conform to JSON syntax rules. No whitespace is + * added, so the results are ready for transmission or storage. Each instance of + * JSONStringer can produce one JSON text. + *

+ * A JSONStringer instance provides a value method for appending + * values to the + * text, and a key + * method for adding keys before values in objects. There are array + * and endArray methods that make and bound array values, and + * object and endObject methods which make and bound + * object values. All of these methods return the JSONWriter instance, + * permitting cascade style. For example,

+ * myString = new JSONStringer()
+ *     .object()
+ *         .key("JSON")
+ *         .value("Hello, World!")
+ *     .endObject()
+ *     .toString();
which produces the string
+ * {"JSON":"Hello, World!"}
+ *

+ * The first method called must be array or object. + * There are no methods for adding commas or colons. JSONStringer adds them for + * you. Objects and arrays can be nested up to 200 levels deep. + *

+ * This can sometimes be easier than using a JSONObject to build a string. + * @author JSON.org + * @version 2015-12-09 + */ +public class JSONStringer extends JSONWriter { + /** + * Make a fresh JSONStringer. It can be used to build one JSON text. + */ + public JSONStringer() { + super(new StringWriter()); + } + + /** + * Return the JSON text. This method is used to obtain the product of the + * JSONStringer instance. It will return null if there was a + * problem in the construction of the JSON text (such as the calls to + * array were not properly balanced with calls to + * endArray). + * @return The JSON text. + */ + @Override + public String toString() { + return this.mode == 'd' ? this.writer.toString() : null; + } +} diff --git a/src/main/java/org/json/JSONTokener.java b/src/main/java/org/json/JSONTokener.java new file mode 100644 index 0000000..7f0c86a --- /dev/null +++ b/src/main/java/org/json/JSONTokener.java @@ -0,0 +1,545 @@ +package org.json; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.StringReader; + +/* +Copyright (c) 2002 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ + +/** + * A JSONTokener takes a source string and extracts characters and tokens from + * it. It is used by the JSONObject and JSONArray constructors to parse + * JSON source strings. + * @author JSON.org + * @version 2014-05-03 + */ +public class JSONTokener { + /** current read character position on the current line. */ + private long character; + /** flag to indicate if the end of the input has been found. */ + private boolean eof; + /** current read index of the input. */ + private long index; + /** current line of the input. */ + private long line; + /** previous character read from the input. */ + private char previous; + /** Reader for the input. */ + private final Reader reader; + /** flag to indicate that a previous character was requested. */ + private boolean usePrevious; + /** the number of characters read in the previous line. */ + private long characterPreviousLine; + + + /** + * Construct a JSONTokener from a Reader. The caller must close the Reader. + * + * @param reader A reader. + */ + public JSONTokener(Reader reader) { + this.reader = reader.markSupported() + ? reader + : new BufferedReader(reader); + this.eof = false; + this.usePrevious = false; + this.previous = 0; + this.index = 0; + this.character = 1; + this.characterPreviousLine = 0; + this.line = 1; + } + + + /** + * Construct a JSONTokener from an InputStream. The caller must close the input stream. + * @param inputStream The source. + */ + public JSONTokener(InputStream inputStream) { + this(new InputStreamReader(inputStream)); + } + + + /** + * Construct a JSONTokener from a string. + * + * @param s A source string. + */ + public JSONTokener(String s) { + this(new StringReader(s)); + } + + + /** + * Back up one character. This provides a sort of lookahead capability, + * so that you can test for a digit or letter before attempting to parse + * the next number or identifier. + * @throws JSONException Thrown if trying to step back more than 1 step + * or if already at the start of the string + */ + public void back() throws JSONException { + if (this.usePrevious || this.index <= 0) { + throw new JSONException("Stepping back two steps is not supported"); + } + this.decrementIndexes(); + this.usePrevious = true; + this.eof = false; + } + + /** + * Decrements the indexes for the {@link #back()} method based on the previous character read. + */ + private void decrementIndexes() { + this.index--; + if(this.previous=='\r' || this.previous == '\n') { + this.line--; + this.character=this.characterPreviousLine ; + } else if(this.character > 0){ + this.character--; + } + } + + /** + * Get the hex value of a character (base16). + * @param c A character between '0' and '9' or between 'A' and 'F' or + * between 'a' and 'f'. + * @return An int between 0 and 15, or -1 if c was not a hex digit. + */ + public static int dehexchar(char c) { + if (c >= '0' && c <= '9') { + return c - '0'; + } + if (c >= 'A' && c <= 'F') { + return c - ('A' - 10); + } + if (c >= 'a' && c <= 'f') { + return c - ('a' - 10); + } + return -1; + } + + /** + * Checks if the end of the input has been reached. + * + * @return true if at the end of the file and we didn't step back + */ + public boolean end() { + return this.eof && !this.usePrevious; + } + + + /** + * Determine if the source string still contains characters that next() + * can consume. + * @return true if not yet at the end of the source. + * @throws JSONException thrown if there is an error stepping forward + * or backward while checking for more data. + */ + public boolean more() throws JSONException { + if(this.usePrevious) { + return true; + } + try { + this.reader.mark(1); + } catch (IOException e) { + throw new JSONException("Unable to preserve stream position", e); + } + try { + // -1 is EOF, but next() can not consume the null character '\0' + if(this.reader.read() <= 0) { + this.eof = true; + return false; + } + this.reader.reset(); + } catch (IOException e) { + throw new JSONException("Unable to read the next character from the stream", e); + } + return true; + } + + + /** + * Get the next character in the source string. + * + * @return The next character, or 0 if past the end of the source string. + * @throws JSONException Thrown if there is an error reading the source string. + */ + public char next() throws JSONException { + int c; + if (this.usePrevious) { + this.usePrevious = false; + c = this.previous; + } else { + try { + c = this.reader.read(); + } catch (IOException exception) { + throw new JSONException(exception); + } + } + if (c <= 0) { // End of stream + this.eof = true; + return 0; + } + this.incrementIndexes(c); + this.previous = (char) c; + return this.previous; + } + + /** + * Get the last character read from the input or '\0' if nothing has been read yet. + * @return the last character read from the input. + */ + protected char getPrevious() { return this.previous;} + + /** + * Increments the internal indexes according to the previous character + * read and the character passed as the current character. + * @param c the current character read. + */ + private void incrementIndexes(int c) { + if(c > 0) { + this.index++; + if(c=='\r') { + this.line++; + this.characterPreviousLine = this.character; + this.character=0; + }else if (c=='\n') { + if(this.previous != '\r') { + this.line++; + this.characterPreviousLine = this.character; + } + this.character=0; + } else { + this.character++; + } + } + } + + /** + * Consume the next character, and check that it matches a specified + * character. + * @param c The character to match. + * @return The character. + * @throws JSONException if the character does not match. + */ + public char next(char c) throws JSONException { + char n = this.next(); + if (n != c) { + if(n > 0) { + throw this.syntaxError("Expected '" + c + "' and instead saw '" + + n + "'"); + } + throw this.syntaxError("Expected '" + c + "' and instead saw ''"); + } + return n; + } + + + /** + * Get the next n characters. + * + * @param n The number of characters to take. + * @return A string of n characters. + * @throws JSONException + * Substring bounds error if there are not + * n characters remaining in the source string. + */ + public String next(int n) throws JSONException { + if (n == 0) { + return ""; + } + + char[] chars = new char[n]; + int pos = 0; + + while (pos < n) { + chars[pos] = this.next(); + if (this.end()) { + throw this.syntaxError("Substring bounds error"); + } + pos += 1; + } + return new String(chars); + } + + + /** + * Get the next char in the string, skipping whitespace. + * @throws JSONException Thrown if there is an error reading the source string. + * @return A character, or 0 if there are no more characters. + */ + public char nextClean() throws JSONException { + for (;;) { + char c = this.next(); + if (c == 0 || c > ' ') { + return c; + } + } + } + + + /** + * Return the characters up to the next close quote character. + * Backslash processing is done. The formal JSON format does not + * allow strings in single quotes, but an implementation is allowed to + * accept them. + * @param quote The quoting character, either + * " (double quote) or + * ' (single quote). + * @return A String. + * @throws JSONException Unterminated string. + */ + public String nextString(char quote) throws JSONException { + char c; + StringBuilder sb = new StringBuilder(); + for (;;) { + c = this.next(); + switch (c) { + case 0: + case '\n': + case '\r': + throw this.syntaxError("Unterminated string"); + case '\\': + c = this.next(); + switch (c) { + case 'b': + sb.append('\b'); + break; + case 't': + sb.append('\t'); + break; + case 'n': + sb.append('\n'); + break; + case 'f': + sb.append('\f'); + break; + case 'r': + sb.append('\r'); + break; + case 'u': + try { + sb.append((char)Integer.parseInt(this.next(4), 16)); + } catch (NumberFormatException e) { + throw this.syntaxError("Illegal escape.", e); + } + break; + case '"': + case '\'': + case '\\': + case '/': + sb.append(c); + break; + default: + throw this.syntaxError("Illegal escape."); + } + break; + default: + if (c == quote) { + return sb.toString(); + } + sb.append(c); + } + } + } + + + /** + * Get the text up but not including the specified character or the + * end of line, whichever comes first. + * @param delimiter A delimiter character. + * @return A string. + * @throws JSONException Thrown if there is an error while searching + * for the delimiter + */ + public String nextTo(char delimiter) throws JSONException { + StringBuilder sb = new StringBuilder(); + for (;;) { + char c = this.next(); + if (c == delimiter || c == 0 || c == '\n' || c == '\r') { + if (c != 0) { + this.back(); + } + return sb.toString().trim(); + } + sb.append(c); + } + } + + + /** + * Get the text up but not including one of the specified delimiter + * characters or the end of line, whichever comes first. + * @param delimiters A set of delimiter characters. + * @return A string, trimmed. + * @throws JSONException Thrown if there is an error while searching + * for the delimiter + */ + public String nextTo(String delimiters) throws JSONException { + char c; + StringBuilder sb = new StringBuilder(); + for (;;) { + c = this.next(); + if (delimiters.indexOf(c) >= 0 || c == 0 || + c == '\n' || c == '\r') { + if (c != 0) { + this.back(); + } + return sb.toString().trim(); + } + sb.append(c); + } + } + + + /** + * Get the next value. The value can be a Boolean, Double, Integer, + * JSONArray, JSONObject, Long, or String, or the JSONObject.NULL object. + * @throws JSONException If syntax error. + * + * @return An object. + */ + public Object nextValue() throws JSONException { + char c = this.nextClean(); + String string; + + switch (c) { + case '"': + case '\'': + return this.nextString(c); + case '{': + this.back(); + try { + return new JSONObject(this); + } catch (StackOverflowError e) { + throw new JSONException("JSON Array or Object depth too large to process.", e); + } + case '[': + this.back(); + try { + return new JSONArray(this); + } catch (StackOverflowError e) { + throw new JSONException("JSON Array or Object depth too large to process.", e); + } + } + + /* + * Handle unquoted text. This could be the values true, false, or + * null, or it can be a number. An implementation (such as this one) + * is allowed to also accept non-standard forms. + * + * Accumulate characters until we reach the end of the text or a + * formatting character. + */ + + StringBuilder sb = new StringBuilder(); + while (c >= ' ' && ",:]}/\\\"[{;=#".indexOf(c) < 0) { + sb.append(c); + c = this.next(); + } + if (!this.eof) { + this.back(); + } + + string = sb.toString().trim(); + if ("".equals(string)) { + throw this.syntaxError("Missing value"); + } + return JSONObject.stringToValue(string); + } + + + /** + * Skip characters until the next character is the requested character. + * If the requested character is not found, no characters are skipped. + * @param to A character to skip to. + * @return The requested character, or zero if the requested character + * is not found. + * @throws JSONException Thrown if there is an error while searching + * for the to character + */ + public char skipTo(char to) throws JSONException { + char c; + try { + long startIndex = this.index; + long startCharacter = this.character; + long startLine = this.line; + this.reader.mark(1000000); + do { + c = this.next(); + if (c == 0) { + // in some readers, reset() may throw an exception if + // the remaining portion of the input is greater than + // the mark size (1,000,000 above). + this.reader.reset(); + this.index = startIndex; + this.character = startCharacter; + this.line = startLine; + return 0; + } + } while (c != to); + this.reader.mark(1); + } catch (IOException exception) { + throw new JSONException(exception); + } + this.back(); + return c; + } + + /** + * Make a JSONException to signal a syntax error. + * + * @param message The error message. + * @return A JSONException object, suitable for throwing + */ + public JSONException syntaxError(String message) { + return new JSONException(message + this.toString()); + } + + /** + * Make a JSONException to signal a syntax error. + * + * @param message The error message. + * @param causedBy The throwable that caused the error. + * @return A JSONException object, suitable for throwing + */ + public JSONException syntaxError(String message, Throwable causedBy) { + return new JSONException(message + this.toString(), causedBy); + } + + /** + * Make a printable string of this JSONTokener. + * + * @return " at {index} [character {character} line {line}]" + */ + @Override + public String toString() { + return " at " + this.index + " [character " + this.character + " line " + + this.line + "]"; + } +} diff --git a/src/main/java/org/json/JSONWriter.java b/src/main/java/org/json/JSONWriter.java new file mode 100644 index 0000000..dafb1b2 --- /dev/null +++ b/src/main/java/org/json/JSONWriter.java @@ -0,0 +1,414 @@ +package org.json; + +import java.io.IOException; +import java.util.Collection; +import java.util.Map; + +/* +Copyright (c) 2006 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +/** + * JSONWriter provides a quick and convenient way of producing JSON text. + * The texts produced strictly conform to JSON syntax rules. No whitespace is + * added, so the results are ready for transmission or storage. Each instance of + * JSONWriter can produce one JSON text. + *

+ * A JSONWriter instance provides a value method for appending + * values to the + * text, and a key + * method for adding keys before values in objects. There are array + * and endArray methods that make and bound array values, and + * object and endObject methods which make and bound + * object values. All of these methods return the JSONWriter instance, + * permitting a cascade style. For example,

+ * new JSONWriter(myWriter)
+ *     .object()
+ *         .key("JSON")
+ *         .value("Hello, World!")
+ *     .endObject();
which writes
+ * {"JSON":"Hello, World!"}
+ *

+ * The first method called must be array or object. + * There are no methods for adding commas or colons. JSONWriter adds them for + * you. Objects and arrays can be nested up to 200 levels deep. + *

+ * This can sometimes be easier than using a JSONObject to build a string. + * @author JSON.org + * @version 2016-08-08 + */ +public class JSONWriter { + private static final int maxdepth = 200; + + /** + * The comma flag determines if a comma should be output before the next + * value. + */ + private boolean comma; + + /** + * The current mode. Values: + * 'a' (array), + * 'd' (done), + * 'i' (initial), + * 'k' (key), + * 'o' (object). + */ + protected char mode; + + /** + * The object/array stack. + */ + private final JSONObject stack[]; + + /** + * The stack top index. A value of 0 indicates that the stack is empty. + */ + private int top; + + /** + * The writer that will receive the output. + */ + protected Appendable writer; + + /** + * Make a fresh JSONWriter. It can be used to build one JSON text. + * @param w an appendable object + */ + public JSONWriter(Appendable w) { + this.comma = false; + this.mode = 'i'; + this.stack = new JSONObject[maxdepth]; + this.top = 0; + this.writer = w; + } + + /** + * Append a value. + * @param string A string value. + * @return this + * @throws JSONException If the value is out of sequence. + */ + private JSONWriter append(String string) throws JSONException { + if (string == null) { + throw new JSONException("Null pointer"); + } + if (this.mode == 'o' || this.mode == 'a') { + try { + if (this.comma && this.mode == 'a') { + this.writer.append(','); + } + this.writer.append(string); + } catch (IOException e) { + // Android as of API 25 does not support this exception constructor + // however we won't worry about it. If an exception is happening here + // it will just throw a "Method not found" exception instead. + throw new JSONException(e); + } + if (this.mode == 'o') { + this.mode = 'k'; + } + this.comma = true; + return this; + } + throw new JSONException("Value out of sequence."); + } + + /** + * Begin appending a new array. All values until the balancing + * endArray will be appended to this array. The + * endArray method must be called to mark the array's end. + * @return this + * @throws JSONException If the nesting is too deep, or if the object is + * started in the wrong place (for example as a key or after the end of the + * outermost array or object). + */ + public JSONWriter array() throws JSONException { + if (this.mode == 'i' || this.mode == 'o' || this.mode == 'a') { + this.push(null); + this.append("["); + this.comma = false; + return this; + } + throw new JSONException("Misplaced array."); + } + + /** + * End something. + * @param m Mode + * @param c Closing character + * @return this + * @throws JSONException If unbalanced. + */ + private JSONWriter end(char m, char c) throws JSONException { + if (this.mode != m) { + throw new JSONException(m == 'a' + ? "Misplaced endArray." + : "Misplaced endObject."); + } + this.pop(m); + try { + this.writer.append(c); + } catch (IOException e) { + // Android as of API 25 does not support this exception constructor + // however we won't worry about it. If an exception is happening here + // it will just throw a "Method not found" exception instead. + throw new JSONException(e); + } + this.comma = true; + return this; + } + + /** + * End an array. This method most be called to balance calls to + * array. + * @return this + * @throws JSONException If incorrectly nested. + */ + public JSONWriter endArray() throws JSONException { + return this.end('a', ']'); + } + + /** + * End an object. This method most be called to balance calls to + * object. + * @return this + * @throws JSONException If incorrectly nested. + */ + public JSONWriter endObject() throws JSONException { + return this.end('k', '}'); + } + + /** + * Append a key. The key will be associated with the next value. In an + * object, every value must be preceded by a key. + * @param string A key string. + * @return this + * @throws JSONException If the key is out of place. For example, keys + * do not belong in arrays or if the key is null. + */ + public JSONWriter key(String string) throws JSONException { + if (string == null) { + throw new JSONException("Null key."); + } + if (this.mode == 'k') { + try { + JSONObject topObject = this.stack[this.top - 1]; + // don't use the built in putOnce method to maintain Android support + if(topObject.has(string)) { + throw new JSONException("Duplicate key \"" + string + "\""); + } + topObject.put(string, true); + if (this.comma) { + this.writer.append(','); + } + this.writer.append(JSONObject.quote(string)); + this.writer.append(':'); + this.comma = false; + this.mode = 'o'; + return this; + } catch (IOException e) { + // Android as of API 25 does not support this exception constructor + // however we won't worry about it. If an exception is happening here + // it will just throw a "Method not found" exception instead. + throw new JSONException(e); + } + } + throw new JSONException("Misplaced key."); + } + + + /** + * Begin appending a new object. All keys and values until the balancing + * endObject will be appended to this object. The + * endObject method must be called to mark the object's end. + * @return this + * @throws JSONException If the nesting is too deep, or if the object is + * started in the wrong place (for example as a key or after the end of the + * outermost array or object). + */ + public JSONWriter object() throws JSONException { + if (this.mode == 'i') { + this.mode = 'o'; + } + if (this.mode == 'o' || this.mode == 'a') { + this.append("{"); + this.push(new JSONObject()); + this.comma = false; + return this; + } + throw new JSONException("Misplaced object."); + + } + + + /** + * Pop an array or object scope. + * @param c The scope to close. + * @throws JSONException If nesting is wrong. + */ + private void pop(char c) throws JSONException { + if (this.top <= 0) { + throw new JSONException("Nesting error."); + } + char m = this.stack[this.top - 1] == null ? 'a' : 'k'; + if (m != c) { + throw new JSONException("Nesting error."); + } + this.top -= 1; + this.mode = this.top == 0 + ? 'd' + : this.stack[this.top - 1] == null + ? 'a' + : 'k'; + } + + /** + * Push an array or object scope. + * @param jo The scope to open. + * @throws JSONException If nesting is too deep. + */ + private void push(JSONObject jo) throws JSONException { + if (this.top >= maxdepth) { + throw new JSONException("Nesting too deep."); + } + this.stack[this.top] = jo; + this.mode = jo == null ? 'a' : 'k'; + this.top += 1; + } + + /** + * Make a JSON text of an Object value. If the object has an + * value.toJSONString() method, then that method will be used to produce the + * JSON text. The method is required to produce a strictly conforming text. + * If the object does not contain a toJSONString method (which is the most + * common case), then a text will be produced by other means. If the value + * is an array or Collection, then a JSONArray will be made from it and its + * toJSONString method will be called. If the value is a MAP, then a + * JSONObject will be made from it and its toJSONString method will be + * called. Otherwise, the value's toString method will be called, and the + * result will be quoted. + * + *

+ * Warning: This method assumes that the data structure is acyclical. + * + * @param value + * The value to be serialized. + * @return a printable, displayable, transmittable representation of the + * object, beginning with { (left + * brace) and ending with } (right + * brace). + * @throws JSONException + * If the value is or contains an invalid number. + */ + public static String valueToString(Object value) throws JSONException { + if (value == null || value.equals(null)) { + return "null"; + } + if (value instanceof JSONString) { + String object; + try { + object = ((JSONString) value).toJSONString(); + } catch (Exception e) { + throw new JSONException(e); + } + if (object != null) { + return object; + } + throw new JSONException("Bad value from toJSONString: " + object); + } + if (value instanceof Number) { + // not all Numbers may match actual JSON Numbers. i.e. Fractions or Complex + final String numberAsString = JSONObject.numberToString((Number) value); + if(JSONObject.NUMBER_PATTERN.matcher(numberAsString).matches()) { + // Close enough to a JSON number that we will return it unquoted + return numberAsString; + } + // The Number value is not a valid JSON number. + // Instead we will quote it as a string + return JSONObject.quote(numberAsString); + } + if (value instanceof Boolean || value instanceof JSONObject + || value instanceof JSONArray) { + return value.toString(); + } + if (value instanceof Map) { + Map map = (Map) value; + return new JSONObject(map).toString(); + } + if (value instanceof Collection) { + Collection coll = (Collection) value; + return new JSONArray(coll).toString(); + } + if (value.getClass().isArray()) { + return new JSONArray(value).toString(); + } + if(value instanceof Enum){ + return JSONObject.quote(((Enum)value).name()); + } + return JSONObject.quote(value.toString()); + } + + /** + * Append either the value true or the value + * false. + * @param b A boolean. + * @return this + * @throws JSONException if a called function has an error + */ + public JSONWriter value(boolean b) throws JSONException { + return this.append(b ? "true" : "false"); + } + + /** + * Append a double value. + * @param d A double. + * @return this + * @throws JSONException If the number is not finite. + */ + public JSONWriter value(double d) throws JSONException { + return this.value(Double.valueOf(d)); + } + + /** + * Append a long value. + * @param l A long. + * @return this + * @throws JSONException if a called function has an error + */ + public JSONWriter value(long l) throws JSONException { + return this.append(Long.toString(l)); + } + + + /** + * Append an object value. + * @param object The object to append. It can be null, or a Boolean, Number, + * String, JSONObject, or JSONArray, or an object that implements JSONString. + * @return this + * @throws JSONException If the value is out of sequence. + */ + public JSONWriter value(Object object) throws JSONException { + return this.append(valueToString(object)); + } +} diff --git a/src/main/java/org/json/Property.java b/src/main/java/org/json/Property.java new file mode 100644 index 0000000..7caeebb --- /dev/null +++ b/src/main/java/org/json/Property.java @@ -0,0 +1,75 @@ +package org.json; + +/* +Copyright (c) 2002 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +import java.util.Enumeration; +import java.util.Properties; + +/** + * Converts a Property file data into JSONObject and back. + * @author JSON.org + * @version 2015-05-05 + */ +public class Property { + /** + * Converts a property file object into a JSONObject. The property file object is a table of name value pairs. + * @param properties java.util.Properties + * @return JSONObject + * @throws JSONException if a called function has an error + */ + public static JSONObject toJSONObject(java.util.Properties properties) throws JSONException { + // can't use the new constructor for Android support + // JSONObject jo = new JSONObject(properties == null ? 0 : properties.size()); + JSONObject jo = new JSONObject(); + if (properties != null && !properties.isEmpty()) { + Enumeration enumProperties = properties.propertyNames(); + while(enumProperties.hasMoreElements()) { + String name = (String)enumProperties.nextElement(); + jo.put(name, properties.getProperty(name)); + } + } + return jo; + } + + /** + * Converts the JSONObject into a property file object. + * @param jo JSONObject + * @return java.util.Properties + * @throws JSONException if a called function has an error + */ + public static Properties toProperties(JSONObject jo) throws JSONException { + Properties properties = new Properties(); + if (jo != null) { + // Don't use the new entrySet API to maintain Android support + for (final String key : jo.keySet()) { + Object value = jo.opt(key); + if (!JSONObject.NULL.equals(value)) { + properties.put(key, value.toString()); + } + } + } + return properties; + } +} diff --git a/src/main/java/org/json/XML.java b/src/main/java/org/json/XML.java new file mode 100644 index 0000000..9b2ba89 --- /dev/null +++ b/src/main/java/org/json/XML.java @@ -0,0 +1,884 @@ +package org.json; + +/* +Copyright (c) 2015 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +import java.io.Reader; +import java.io.StringReader; +import java.lang.reflect.Method; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.Iterator; + + +/** + * This provides static methods to convert an XML text into a JSONObject, and to + * covert a JSONObject into an XML text. + * + * @author JSON.org + * @version 2016-08-10 + */ +@SuppressWarnings("boxing") +public class XML { + + /** The Character '&'. */ + public static final Character AMP = '&'; + + /** The Character '''. */ + public static final Character APOS = '\''; + + /** The Character '!'. */ + public static final Character BANG = '!'; + + /** The Character '='. */ + public static final Character EQ = '='; + + /** The Character

{@code '>'. }
*/ + public static final Character GT = '>'; + + /** The Character '<'. */ + public static final Character LT = '<'; + + /** The Character '?'. */ + public static final Character QUEST = '?'; + + /** The Character '"'. */ + public static final Character QUOT = '"'; + + /** The Character '/'. */ + public static final Character SLASH = '/'; + + /** + * Null attribute name + */ + public static final String NULL_ATTR = "xsi:nil"; + + public static final String TYPE_ATTR = "xsi:type"; + + /** + * Creates an iterator for navigating Code Points in a string instead of + * characters. Once Java7 support is dropped, this can be replaced with + * + * string.codePoints() + * + * which is available in Java8 and above. + * + * @see http://stackoverflow.com/a/21791059/6030888 + */ + private static Iterable codePointIterator(final String string) { + return new Iterable() { + @Override + public Iterator iterator() { + return new Iterator() { + private int nextIndex = 0; + private int length = string.length(); + + @Override + public boolean hasNext() { + return this.nextIndex < this.length; + } + + @Override + public Integer next() { + int result = string.codePointAt(this.nextIndex); + this.nextIndex += Character.charCount(result); + return result; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + }; + } + + /** + * Replace special characters with XML escapes: + * + *
{@code 
+     * & (ampersand) is replaced by &amp;
+     * < (less than) is replaced by &lt;
+     * > (greater than) is replaced by &gt;
+     * " (double quote) is replaced by &quot;
+     * ' (single quote / apostrophe) is replaced by &apos;
+     * }
+ * + * @param string + * The string to be escaped. + * @return The escaped string. + */ + public static String escape(String string) { + StringBuilder sb = new StringBuilder(string.length()); + for (final int cp : codePointIterator(string)) { + switch (cp) { + case '&': + sb.append("&"); + break; + case '<': + sb.append("<"); + break; + case '>': + sb.append(">"); + break; + case '"': + sb.append("""); + break; + case '\'': + sb.append("'"); + break; + default: + if (mustEscape(cp)) { + sb.append("&#x"); + sb.append(Integer.toHexString(cp)); + sb.append(';'); + } else { + sb.appendCodePoint(cp); + } + } + } + return sb.toString(); + } + + /** + * @param cp code point to test + * @return true if the code point is not valid for an XML + */ + private static boolean mustEscape(int cp) { + /* Valid range from https://www.w3.org/TR/REC-xml/#charsets + * + * #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] + * + * any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. + */ + // isISOControl is true when (cp >= 0 && cp <= 0x1F) || (cp >= 0x7F && cp <= 0x9F) + // all ISO control characters are out of range except tabs and new lines + return (Character.isISOControl(cp) + && cp != 0x9 + && cp != 0xA + && cp != 0xD + ) || !( + // valid the range of acceptable characters that aren't control + (cp >= 0x20 && cp <= 0xD7FF) + || (cp >= 0xE000 && cp <= 0xFFFD) + || (cp >= 0x10000 && cp <= 0x10FFFF) + ) + ; + } + + /** + * Removes XML escapes from the string. + * + * @param string + * string to remove escapes from + * @return string with converted entities + */ + public static String unescape(String string) { + StringBuilder sb = new StringBuilder(string.length()); + for (int i = 0, length = string.length(); i < length; i++) { + char c = string.charAt(i); + if (c == '&') { + final int semic = string.indexOf(';', i); + if (semic > i) { + final String entity = string.substring(i + 1, semic); + sb.append(XMLTokener.unescapeEntity(entity)); + // skip past the entity we just parsed. + i += entity.length() + 1; + } else { + // this shouldn't happen in most cases since the parser + // errors on unclosed entries. + sb.append(c); + } + } else { + // not part of an entity + sb.append(c); + } + } + return sb.toString(); + } + + /** + * Throw an exception if the string contains whitespace. Whitespace is not + * allowed in tagNames and attributes. + * + * @param string + * A string. + * @throws JSONException Thrown if the string contains whitespace or is empty. + */ + public static void noSpace(String string) throws JSONException { + int i, length = string.length(); + if (length == 0) { + throw new JSONException("Empty string."); + } + for (i = 0; i < length; i += 1) { + if (Character.isWhitespace(string.charAt(i))) { + throw new JSONException("'" + string + + "' contains a space character."); + } + } + } + + /** + * Scan the content following the named tag, attaching it to the context. + * + * @param x + * The XMLTokener containing the source string. + * @param context + * The JSONObject that will include the new material. + * @param name + * The tag name. + * @return true if the close tag is processed. + * @throws JSONException + */ + private static boolean parse(XMLTokener x, JSONObject context, String name, XMLParserConfiguration config) + throws JSONException { + char c; + int i; + JSONObject jsonObject = null; + String string; + String tagName; + Object token; + XMLXsiTypeConverter xmlXsiTypeConverter; + + // Test for and skip past these forms: + // + // + // + // + // Report errors for these forms: + // <> + // <= + // << + + token = x.nextToken(); + + // "); + return false; + } + x.back(); + } else if (c == '[') { + token = x.nextToken(); + if ("CDATA".equals(token)) { + if (x.next() == '[') { + string = x.nextCDATA(); + if (string.length() > 0) { + context.accumulate(config.getcDataTagName(), string); + } + return false; + } + } + throw x.syntaxError("Expected 'CDATA['"); + } + i = 1; + do { + token = x.nextMeta(); + if (token == null) { + throw x.syntaxError("Missing '>' after ' 0); + return false; + } else if (token == QUEST) { + + // "); + return false; + } else if (token == SLASH) { + + // Close tag + if (x.nextToken() != GT) { + throw x.syntaxError("Misshaped tag"); + } + if (config.getForceList().contains(tagName)) { + // Force the value to be an array + if (nilAttributeFound) { + context.append(tagName, JSONObject.NULL); + } else if (jsonObject.length() > 0) { + context.append(tagName, jsonObject); + } else { + context.put(tagName, new JSONArray()); + } + } else { + if (nilAttributeFound) { + context.accumulate(tagName, JSONObject.NULL); + } else if (jsonObject.length() > 0) { + context.accumulate(tagName, jsonObject); + } else { + context.accumulate(tagName, ""); + } + } + return false; + + } else if (token == GT) { + // Content, between <...> and + for (;;) { + token = x.nextContent(); + if (token == null) { + if (tagName != null) { + throw x.syntaxError("Unclosed tag " + tagName); + } + return false; + } else if (token instanceof String) { + string = (String) token; + if (string.length() > 0) { + if(xmlXsiTypeConverter != null) { + jsonObject.accumulate(config.getcDataTagName(), + stringToValue(string, xmlXsiTypeConverter)); + } else { + jsonObject.accumulate(config.getcDataTagName(), + config.isKeepStrings() ? string : stringToValue(string)); + } + } + + } else if (token == LT) { + // Nested element + if (parse(x, jsonObject, tagName, config)) { + if (config.getForceList().contains(tagName)) { + // Force the value to be an array + if (jsonObject.length() == 0) { + context.put(tagName, new JSONArray()); + } else if (jsonObject.length() == 1 + && jsonObject.opt(config.getcDataTagName()) != null) { + context.append(tagName, jsonObject.opt(config.getcDataTagName())); + } else { + context.append(tagName, jsonObject); + } + } else { + if (jsonObject.length() == 0) { + context.accumulate(tagName, ""); + } else if (jsonObject.length() == 1 + && jsonObject.opt(config.getcDataTagName()) != null) { + context.accumulate(tagName, jsonObject.opt(config.getcDataTagName())); + } else { + context.accumulate(tagName, jsonObject); + } + } + + return false; + } + } + } + } else { + throw x.syntaxError("Misshaped tag"); + } + } + } + } + + /** + * This method tries to convert the given string value to the target object + * @param string String to convert + * @param typeConverter value converter to convert string to integer, boolean e.t.c + * @return JSON value of this string or the string + */ + public static Object stringToValue(String string, XMLXsiTypeConverter typeConverter) { + if(typeConverter != null) { + return typeConverter.convert(string); + } + return stringToValue(string); + } + + /** + * This method is the same as {@link JSONObject#stringToValue(String)}. + * + * @param string String to convert + * @return JSON value of this string or the string + */ + // To maintain compatibility with the Android API, this method is a direct copy of + // the one in JSONObject. Changes made here should be reflected there. + // This method should not make calls out of the XML object. + public static Object stringToValue(String string) { + if ("".equals(string)) { + return string; + } + + // check JSON key words true/false/null + if ("true".equalsIgnoreCase(string)) { + return Boolean.TRUE; + } + if ("false".equalsIgnoreCase(string)) { + return Boolean.FALSE; + } + if ("null".equalsIgnoreCase(string)) { + return JSONObject.NULL; + } + + /* + * If it might be a number, try converting it. If a number cannot be + * produced, then the value will just be a string. + */ + + char initial = string.charAt(0); + if ((initial >= '0' && initial <= '9') || initial == '-') { + try { + return stringToNumber(string); + } catch (Exception ignore) { + } + } + return string; + } + + /** + * direct copy of {@link JSONObject#stringToNumber(String)} to maintain Android support. + */ + private static Number stringToNumber(final String val) throws NumberFormatException { + char initial = val.charAt(0); + if ((initial >= '0' && initial <= '9') || initial == '-') { + // decimal representation + if (isDecimalNotation(val)) { + // Use a BigDecimal all the time so we keep the original + // representation. BigDecimal doesn't support -0.0, ensure we + // keep that by forcing a decimal. + try { + BigDecimal bd = new BigDecimal(val); + if(initial == '-' && BigDecimal.ZERO.compareTo(bd)==0) { + return Double.valueOf(-0.0); + } + return bd; + } catch (NumberFormatException retryAsDouble) { + // this is to support "Hex Floats" like this: 0x1.0P-1074 + try { + Double d = Double.valueOf(val); + if(d.isNaN() || d.isInfinite()) { + throw new NumberFormatException("val ["+val+"] is not a valid number."); + } + return d; + } catch (NumberFormatException ignore) { + throw new NumberFormatException("val ["+val+"] is not a valid number."); + } + } + } + // block items like 00 01 etc. Java number parsers treat these as Octal. + if(initial == '0' && val.length() > 1) { + char at1 = val.charAt(1); + if(at1 >= '0' && at1 <= '9') { + throw new NumberFormatException("val ["+val+"] is not a valid number."); + } + } else if (initial == '-' && val.length() > 2) { + char at1 = val.charAt(1); + char at2 = val.charAt(2); + if(at1 == '0' && at2 >= '0' && at2 <= '9') { + throw new NumberFormatException("val ["+val+"] is not a valid number."); + } + } + // integer representation. + // This will narrow any values to the smallest reasonable Object representation + // (Integer, Long, or BigInteger) + + // BigInteger down conversion: We use a similar bitLength compare as + // BigInteger#intValueExact uses. Increases GC, but objects hold + // only what they need. i.e. Less runtime overhead if the value is + // long lived. + BigInteger bi = new BigInteger(val); + if(bi.bitLength() <= 31){ + return Integer.valueOf(bi.intValue()); + } + if(bi.bitLength() <= 63){ + return Long.valueOf(bi.longValue()); + } + return bi; + } + throw new NumberFormatException("val ["+val+"] is not a valid number."); + } + + /** + * direct copy of {@link JSONObject#isDecimalNotation(String)} to maintain Android support. + */ + private static boolean isDecimalNotation(final String val) { + return val.indexOf('.') > -1 || val.indexOf('e') > -1 + || val.indexOf('E') > -1 || "-0".equals(val); + } + + + /** + * Convert a well-formed (but not necessarily valid) XML string into a + * JSONObject. Some information may be lost in this transformation because + * JSON is a data format and XML is a document format. XML uses elements, + * attributes, and content text, while JSON uses unordered collections of + * name/value pairs and arrays of values. JSON does not does not like to + * distinguish between elements and attributes. Sequences of similar + * elements are represented as JSONArrays. Content text may be placed in a + * "content" member. Comments, prologs, DTDs, and
{@code 
+     * <[ [ ]]>}
+ * are ignored. + * + * @param string + * The source string. + * @return A JSONObject containing the structured data from the XML string. + * @throws JSONException Thrown if there is an errors while parsing the string + */ + public static JSONObject toJSONObject(String string) throws JSONException { + return toJSONObject(string, XMLParserConfiguration.ORIGINAL); + } + + /** + * Convert a well-formed (but not necessarily valid) XML into a + * JSONObject. Some information may be lost in this transformation because + * JSON is a data format and XML is a document format. XML uses elements, + * attributes, and content text, while JSON uses unordered collections of + * name/value pairs and arrays of values. JSON does not does not like to + * distinguish between elements and attributes. Sequences of similar + * elements are represented as JSONArrays. Content text may be placed in a + * "content" member. Comments, prologs, DTDs, and
{@code 
+     * <[ [ ]]>}
+ * are ignored. + * + * @param reader The XML source reader. + * @return A JSONObject containing the structured data from the XML string. + * @throws JSONException Thrown if there is an errors while parsing the string + */ + public static JSONObject toJSONObject(Reader reader) throws JSONException { + return toJSONObject(reader, XMLParserConfiguration.ORIGINAL); + } + + /** + * Convert a well-formed (but not necessarily valid) XML into a + * JSONObject. Some information may be lost in this transformation because + * JSON is a data format and XML is a document format. XML uses elements, + * attributes, and content text, while JSON uses unordered collections of + * name/value pairs and arrays of values. JSON does not does not like to + * distinguish between elements and attributes. Sequences of similar + * elements are represented as JSONArrays. Content text may be placed in a + * "content" member. Comments, prologs, DTDs, and
{@code
+     * <[ [ ]]>}
+ * are ignored. + * + * All values are converted as strings, for 1, 01, 29.0 will not be coerced to + * numbers but will instead be the exact value as seen in the XML document. + * + * @param reader The XML source reader. + * @param keepStrings If true, then values will not be coerced into boolean + * or numeric values and will instead be left as strings + * @return A JSONObject containing the structured data from the XML string. + * @throws JSONException Thrown if there is an errors while parsing the string + */ + public static JSONObject toJSONObject(Reader reader, boolean keepStrings) throws JSONException { + if(keepStrings) { + return toJSONObject(reader, XMLParserConfiguration.KEEP_STRINGS); + } + return toJSONObject(reader, XMLParserConfiguration.ORIGINAL); + } + + /** + * Convert a well-formed (but not necessarily valid) XML into a + * JSONObject. Some information may be lost in this transformation because + * JSON is a data format and XML is a document format. XML uses elements, + * attributes, and content text, while JSON uses unordered collections of + * name/value pairs and arrays of values. JSON does not does not like to + * distinguish between elements and attributes. Sequences of similar + * elements are represented as JSONArrays. Content text may be placed in a + * "content" member. Comments, prologs, DTDs, and
{@code
+     * <[ [ ]]>}
+ * are ignored. + * + * All values are converted as strings, for 1, 01, 29.0 will not be coerced to + * numbers but will instead be the exact value as seen in the XML document. + * + * @param reader The XML source reader. + * @param config Configuration options for the parser + * @return A JSONObject containing the structured data from the XML string. + * @throws JSONException Thrown if there is an errors while parsing the string + */ + public static JSONObject toJSONObject(Reader reader, XMLParserConfiguration config) throws JSONException { + JSONObject jo = new JSONObject(); + XMLTokener x = new XMLTokener(reader); + while (x.more()) { + x.skipPast("<"); + if(x.more()) { + parse(x, jo, null, config); + } + } + return jo; + } + + /** + * Convert a well-formed (but not necessarily valid) XML string into a + * JSONObject. Some information may be lost in this transformation because + * JSON is a data format and XML is a document format. XML uses elements, + * attributes, and content text, while JSON uses unordered collections of + * name/value pairs and arrays of values. JSON does not does not like to + * distinguish between elements and attributes. Sequences of similar + * elements are represented as JSONArrays. Content text may be placed in a + * "content" member. Comments, prologs, DTDs, and
{@code 
+     * <[ [ ]]>}
+ * are ignored. + * + * All values are converted as strings, for 1, 01, 29.0 will not be coerced to + * numbers but will instead be the exact value as seen in the XML document. + * + * @param string + * The source string. + * @param keepStrings If true, then values will not be coerced into boolean + * or numeric values and will instead be left as strings + * @return A JSONObject containing the structured data from the XML string. + * @throws JSONException Thrown if there is an errors while parsing the string + */ + public static JSONObject toJSONObject(String string, boolean keepStrings) throws JSONException { + return toJSONObject(new StringReader(string), keepStrings); + } + + /** + * Convert a well-formed (but not necessarily valid) XML string into a + * JSONObject. Some information may be lost in this transformation because + * JSON is a data format and XML is a document format. XML uses elements, + * attributes, and content text, while JSON uses unordered collections of + * name/value pairs and arrays of values. JSON does not does not like to + * distinguish between elements and attributes. Sequences of similar + * elements are represented as JSONArrays. Content text may be placed in a + * "content" member. Comments, prologs, DTDs, and
{@code 
+     * <[ [ ]]>}
+ * are ignored. + * + * All values are converted as strings, for 1, 01, 29.0 will not be coerced to + * numbers but will instead be the exact value as seen in the XML document. + * + * @param string + * The source string. + * @param config Configuration options for the parser. + * @return A JSONObject containing the structured data from the XML string. + * @throws JSONException Thrown if there is an errors while parsing the string + */ + public static JSONObject toJSONObject(String string, XMLParserConfiguration config) throws JSONException { + return toJSONObject(new StringReader(string), config); + } + + /** + * Convert a JSONObject into a well-formed, element-normal XML string. + * + * @param object + * A JSONObject. + * @return A string. + * @throws JSONException Thrown if there is an error parsing the string + */ + public static String toString(Object object) throws JSONException { + return toString(object, null, XMLParserConfiguration.ORIGINAL); + } + + /** + * Convert a JSONObject into a well-formed, element-normal XML string. + * + * @param object + * A JSONObject. + * @param tagName + * The optional name of the enclosing tag. + * @return A string. + * @throws JSONException Thrown if there is an error parsing the string + */ + public static String toString(final Object object, final String tagName) { + return toString(object, tagName, XMLParserConfiguration.ORIGINAL); + } + + /** + * Convert a JSONObject into a well-formed, element-normal XML string. + * + * @param object + * A JSONObject. + * @param tagName + * The optional name of the enclosing tag. + * @param config + * Configuration that can control output to XML. + * @return A string. + * @throws JSONException Thrown if there is an error parsing the string + */ + public static String toString(final Object object, final String tagName, final XMLParserConfiguration config) + throws JSONException { + StringBuilder sb = new StringBuilder(); + JSONArray ja; + JSONObject jo; + String string; + + if (object instanceof JSONObject) { + + // Emit + if (tagName != null) { + sb.append('<'); + sb.append(tagName); + sb.append('>'); + } + + // Loop thru the keys. + // don't use the new entrySet accessor to maintain Android Support + jo = (JSONObject) object; + for (final String key : jo.keySet()) { + Object value = jo.opt(key); + if (value == null) { + value = ""; + } else if (value.getClass().isArray()) { + value = new JSONArray(value); + } + + // Emit content in body + if (key.equals(config.getcDataTagName())) { + if (value instanceof JSONArray) { + ja = (JSONArray) value; + int jaLength = ja.length(); + // don't use the new iterator API to maintain support for Android + for (int i = 0; i < jaLength; i++) { + if (i > 0) { + sb.append('\n'); + } + Object val = ja.opt(i); + sb.append(escape(val.toString())); + } + } else { + sb.append(escape(value.toString())); + } + + // Emit an array of similar keys + + } else if (value instanceof JSONArray) { + ja = (JSONArray) value; + int jaLength = ja.length(); + // don't use the new iterator API to maintain support for Android + for (int i = 0; i < jaLength; i++) { + Object val = ja.opt(i); + if (val instanceof JSONArray) { + sb.append('<'); + sb.append(key); + sb.append('>'); + sb.append(toString(val, null, config)); + sb.append("'); + } else { + sb.append(toString(val, key, config)); + } + } + } else if ("".equals(value)) { + sb.append('<'); + sb.append(key); + sb.append("/>"); + + // Emit a new tag + + } else { + sb.append(toString(value, key, config)); + } + } + if (tagName != null) { + + // Emit the close tag + sb.append("'); + } + return sb.toString(); + + } + + if (object != null && (object instanceof JSONArray || object.getClass().isArray())) { + if(object.getClass().isArray()) { + ja = new JSONArray(object); + } else { + ja = (JSONArray) object; + } + int jaLength = ja.length(); + // don't use the new iterator API to maintain support for Android + for (int i = 0; i < jaLength; i++) { + Object val = ja.opt(i); + // XML does not have good support for arrays. If an array + // appears in a place where XML is lacking, synthesize an + // element. + sb.append(toString(val, tagName == null ? "array" : tagName, config)); + } + return sb.toString(); + } + + string = (object == null) ? "null" : escape(object.toString()); + return (tagName == null) ? "\"" + string + "\"" + : (string.length() == 0) ? "<" + tagName + "/>" : "<" + tagName + + ">" + string + ""; + + } +} diff --git a/src/main/java/org/json/XMLParserConfiguration.java b/src/main/java/org/json/XMLParserConfiguration.java new file mode 100644 index 0000000..a1fd63e --- /dev/null +++ b/src/main/java/org/json/XMLParserConfiguration.java @@ -0,0 +1,320 @@ +package org.json; +/* +Copyright (c) 2002 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + + +/** + * Configuration object for the XML parser. The configuration is immutable. + * @author AylwardJ + */ +@SuppressWarnings({""}) +public class XMLParserConfiguration { + /** Original Configuration of the XML Parser. */ + public static final XMLParserConfiguration ORIGINAL + = new XMLParserConfiguration(); + /** Original configuration of the XML Parser except that values are kept as strings. */ + public static final XMLParserConfiguration KEEP_STRINGS + = new XMLParserConfiguration().withKeepStrings(true); + + /** + * When parsing the XML into JSON, specifies if values should be kept as strings (true), or if + * they should try to be guessed into JSON values (numeric, boolean, string) + */ + private boolean keepStrings; + + /** + * The name of the key in a JSON Object that indicates a CDATA section. Historically this has + * been the value "content" but can be changed. Use null to indicate no CDATA + * processing. + */ + private String cDataTagName; + + /** + * When parsing the XML into JSON, specifies if values with attribute xsi:nil="true" + * should be kept as attribute(false), or they should be converted to + * null(true) + */ + private boolean convertNilAttributeToNull; + + /** + * This will allow type conversion for values in XML if xsi:type attribute is defined + */ + private Map> xsiTypeMap; + + /** + * When parsing the XML into JSON, specifies the tags whose values should be converted + * to arrays + */ + private Set forceList; + + /** + * Default parser configuration. Does not keep strings (tries to implicitly convert + * values), and the CDATA Tag Name is "content". + */ + public XMLParserConfiguration () { + this.keepStrings = false; + this.cDataTagName = "content"; + this.convertNilAttributeToNull = false; + this.xsiTypeMap = Collections.emptyMap(); + this.forceList = Collections.emptySet(); + } + + /** + * Configure the parser string processing and use the default CDATA Tag Name as "content". + * @param keepStrings true to parse all values as string. + * false to try and convert XML string values into a JSON value. + * @deprecated This constructor has been deprecated in favor of using the new builder + * pattern for the configuration. + * This constructor may be removed in a future release. + */ + @Deprecated + public XMLParserConfiguration (final boolean keepStrings) { + this(keepStrings, "content", false); + } + + /** + * Configure the parser string processing to try and convert XML values to JSON values and + * use the passed CDATA Tag Name the processing value. Pass null to + * disable CDATA processing + * @param cDataTagName null to disable CDATA processing. Any other value + * to use that value as the JSONObject key name to process as CDATA. + * @deprecated This constructor has been deprecated in favor of using the new builder + * pattern for the configuration. + * This constructor may be removed in a future release. + */ + @Deprecated + public XMLParserConfiguration (final String cDataTagName) { + this(false, cDataTagName, false); + } + + /** + * Configure the parser to use custom settings. + * @param keepStrings true to parse all values as string. + * false to try and convert XML string values into a JSON value. + * @param cDataTagName null to disable CDATA processing. Any other value + * to use that value as the JSONObject key name to process as CDATA. + * @deprecated This constructor has been deprecated in favor of using the new builder + * pattern for the configuration. + * This constructor may be removed in a future release. + */ + @Deprecated + public XMLParserConfiguration (final boolean keepStrings, final String cDataTagName) { + this.keepStrings = keepStrings; + this.cDataTagName = cDataTagName; + this.convertNilAttributeToNull = false; + } + + /** + * Configure the parser to use custom settings. + * @param keepStrings true to parse all values as string. + * false to try and convert XML string values into a JSON value. + * @param cDataTagName null to disable CDATA processing. Any other value + * to use that value as the JSONObject key name to process as CDATA. + * @param convertNilAttributeToNull true to parse values with attribute xsi:nil="true" as null. + * false to parse values with attribute xsi:nil="true" as {"xsi:nil":true}. + * @deprecated This constructor has been deprecated in favor of using the new builder + * pattern for the configuration. + * This constructor may be removed or marked private in a future release. + */ + @Deprecated + public XMLParserConfiguration (final boolean keepStrings, final String cDataTagName, final boolean convertNilAttributeToNull) { + this.keepStrings = keepStrings; + this.cDataTagName = cDataTagName; + this.convertNilAttributeToNull = convertNilAttributeToNull; + } + + /** + * Configure the parser to use custom settings. + * @param keepStrings true to parse all values as string. + * false to try and convert XML string values into a JSON value. + * @param cDataTagName null to disable CDATA processing. Any other value + * to use that value as the JSONObject key name to process as CDATA. + * @param convertNilAttributeToNull true to parse values with attribute xsi:nil="true" as null. + * false to parse values with attribute xsi:nil="true" as {"xsi:nil":true}. + * @param xsiTypeMap new HashMap>() to parse values with attribute + * xsi:type="integer" as integer, xsi:type="string" as string + * @param forceList new HashSet() to parse the provided tags' values as arrays + */ + private XMLParserConfiguration (final boolean keepStrings, final String cDataTagName, + final boolean convertNilAttributeToNull, final Map> xsiTypeMap, final Set forceList ) { + this.keepStrings = keepStrings; + this.cDataTagName = cDataTagName; + this.convertNilAttributeToNull = convertNilAttributeToNull; + this.xsiTypeMap = Collections.unmodifiableMap(xsiTypeMap); + this.forceList = Collections.unmodifiableSet(forceList); + } + + /** + * Provides a new instance of the same configuration. + */ + @Override + protected XMLParserConfiguration clone() { + // future modifications to this method should always ensure a "deep" + // clone in the case of collections. i.e. if a Map is added as a configuration + // item, a new map instance should be created and if possible each value in the + // map should be cloned as well. If the values of the map are known to also + // be immutable, then a shallow clone of the map is acceptable. + return new XMLParserConfiguration( + this.keepStrings, + this.cDataTagName, + this.convertNilAttributeToNull, + this.xsiTypeMap, + this.forceList + ); + } + + /** + * When parsing the XML into JSON, specifies if values should be kept as strings (true), or if + * they should try to be guessed into JSON values (numeric, boolean, string) + * + * @return The keepStrings configuration value. + */ + public boolean isKeepStrings() { + return this.keepStrings; + } + + /** + * When parsing the XML into JSON, specifies if values should be kept as strings (true), or if + * they should try to be guessed into JSON values (numeric, boolean, string) + * + * @param newVal + * new value to use for the keepStrings configuration option. + * + * @return The existing configuration will not be modified. A new configuration is returned. + */ + public XMLParserConfiguration withKeepStrings(final boolean newVal) { + XMLParserConfiguration newConfig = this.clone(); + newConfig.keepStrings = newVal; + return newConfig; + } + + /** + * The name of the key in a JSON Object that indicates a CDATA section. Historically this has + * been the value "content" but can be changed. Use null to indicate no CDATA + * processing. + * + * @return The cDataTagName configuration value. + */ + public String getcDataTagName() { + return this.cDataTagName; + } + + /** + * The name of the key in a JSON Object that indicates a CDATA section. Historically this has + * been the value "content" but can be changed. Use null to indicate no CDATA + * processing. + * + * @param newVal + * new value to use for the cDataTagName configuration option. + * + * @return The existing configuration will not be modified. A new configuration is returned. + */ + public XMLParserConfiguration withcDataTagName(final String newVal) { + XMLParserConfiguration newConfig = this.clone(); + newConfig.cDataTagName = newVal; + return newConfig; + } + + /** + * When parsing the XML into JSON, specifies if values with attribute xsi:nil="true" + * should be kept as attribute(false), or they should be converted to + * null(true) + * + * @return The convertNilAttributeToNull configuration value. + */ + public boolean isConvertNilAttributeToNull() { + return this.convertNilAttributeToNull; + } + + /** + * When parsing the XML into JSON, specifies if values with attribute xsi:nil="true" + * should be kept as attribute(false), or they should be converted to + * null(true) + * + * @param newVal + * new value to use for the convertNilAttributeToNull configuration option. + * + * @return The existing configuration will not be modified. A new configuration is returned. + */ + public XMLParserConfiguration withConvertNilAttributeToNull(final boolean newVal) { + XMLParserConfiguration newConfig = this.clone(); + newConfig.convertNilAttributeToNull = newVal; + return newConfig; + } + + /** + * When parsing the XML into JSON, specifies that the values with attribute xsi:type + * will be converted to target type defined to client in this configuration + * {@code Map>} to parse values with attribute + * xsi:type="integer" as integer, xsi:type="string" as string + * @return xsiTypeMap unmodifiable configuration map. + */ + public Map> getXsiTypeMap() { + return this.xsiTypeMap; + } + + /** + * When parsing the XML into JSON, specifies that the values with attribute xsi:type + * will be converted to target type defined to client in this configuration + * {@code Map>} to parse values with attribute + * xsi:type="integer" as integer, xsi:type="string" as string + * @param xsiTypeMap {@code new HashMap>()} to parse values with attribute + * xsi:type="integer" as integer, xsi:type="string" as string + * @return The existing configuration will not be modified. A new configuration is returned. + */ + public XMLParserConfiguration withXsiTypeMap(final Map> xsiTypeMap) { + XMLParserConfiguration newConfig = this.clone(); + Map> cloneXsiTypeMap = new HashMap>(xsiTypeMap); + newConfig.xsiTypeMap = Collections.unmodifiableMap(cloneXsiTypeMap); + return newConfig; + } + + /** + * When parsing the XML into JSON, specifies that tags that will be converted to arrays + * in this configuration {@code Set} to parse the provided tags' values as arrays + * @return forceList unmodifiable configuration set. + */ + public Set getForceList() { + return this.forceList; + } + + /** + * When parsing the XML into JSON, specifies that tags that will be converted to arrays + * in this configuration {@code Set} to parse the provided tags' values as arrays + * @param forceList {@code new HashSet()} to parse the provided tags' values as arrays + * @return The existing configuration will not be modified. A new configuration is returned. + */ + public XMLParserConfiguration withForceList(final Set forceList) { + XMLParserConfiguration newConfig = this.clone(); + Set cloneForceList = new HashSet(forceList); + newConfig.forceList = Collections.unmodifiableSet(cloneForceList); + return newConfig; + } +} diff --git a/src/main/java/org/json/XMLTokener.java b/src/main/java/org/json/XMLTokener.java new file mode 100644 index 0000000..3bbd382 --- /dev/null +++ b/src/main/java/org/json/XMLTokener.java @@ -0,0 +1,416 @@ +package org.json; + +/* +Copyright (c) 2002 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +import java.io.Reader; + +/** + * The XMLTokener extends the JSONTokener to provide additional methods + * for the parsing of XML texts. + * @author JSON.org + * @version 2015-12-09 + */ +public class XMLTokener extends JSONTokener { + + + /** The table of entity values. It initially contains Character values for + * amp, apos, gt, lt, quot. + */ + public static final java.util.HashMap entity; + + static { + entity = new java.util.HashMap(8); + entity.put("amp", XML.AMP); + entity.put("apos", XML.APOS); + entity.put("gt", XML.GT); + entity.put("lt", XML.LT); + entity.put("quot", XML.QUOT); + } + + /** + * Construct an XMLTokener from a Reader. + * @param r A source reader. + */ + public XMLTokener(Reader r) { + super(r); + } + + /** + * Construct an XMLTokener from a string. + * @param s A source string. + */ + public XMLTokener(String s) { + super(s); + } + + /** + * Get the text in the CDATA block. + * @return The string up to the ]]>. + * @throws JSONException If the ]]> is not found. + */ + public String nextCDATA() throws JSONException { + char c; + int i; + StringBuilder sb = new StringBuilder(); + while (more()) { + c = next(); + sb.append(c); + i = sb.length() - 3; + if (i >= 0 && sb.charAt(i) == ']' && + sb.charAt(i + 1) == ']' && sb.charAt(i + 2) == '>') { + sb.setLength(i); + return sb.toString(); + } + } + throw syntaxError("Unclosed CDATA"); + } + + + /** + * Get the next XML outer token, trimming whitespace. There are two kinds + * of tokens: the
{@code '<' }
character which begins a markup + * tag, and the content + * text between markup tags. + * + * @return A string, or a
{@code '<' }
Character, or null if + * there is no more source text. + * @throws JSONException if a called function has an error + */ + public Object nextContent() throws JSONException { + char c; + StringBuilder sb; + do { + c = next(); + } while (Character.isWhitespace(c)); + if (c == 0) { + return null; + } + if (c == '<') { + return XML.LT; + } + sb = new StringBuilder(); + for (;;) { + if (c == 0) { + return sb.toString().trim(); + } + if (c == '<') { + back(); + return sb.toString().trim(); + } + if (c == '&') { + sb.append(nextEntity(c)); + } else { + sb.append(c); + } + c = next(); + } + } + + + /** + *
{@code
+     * Return the next entity. These entities are translated to Characters:
+     *     &  '  >  <  ".
+     * }
+ * @param ampersand An ampersand character. + * @return A Character or an entity String if the entity is not recognized. + * @throws JSONException If missing ';' in XML entity. + */ + public Object nextEntity(@SuppressWarnings("unused") char ampersand) throws JSONException { + StringBuilder sb = new StringBuilder(); + for (;;) { + char c = next(); + if (Character.isLetterOrDigit(c) || c == '#') { + sb.append(Character.toLowerCase(c)); + } else if (c == ';') { + break; + } else { + throw syntaxError("Missing ';' in XML entity: &" + sb); + } + } + String string = sb.toString(); + return unescapeEntity(string); + } + + /** + * Unescape an XML entity encoding; + * @param e entity (only the actual entity value, not the preceding & or ending ; + * @return + */ + static String unescapeEntity(String e) { + // validate + if (e == null || e.isEmpty()) { + return ""; + } + // if our entity is an encoded unicode point, parse it. + if (e.charAt(0) == '#') { + int cp; + if (e.charAt(1) == 'x' || e.charAt(1) == 'X') { + // hex encoded unicode + cp = Integer.parseInt(e.substring(2), 16); + } else { + // decimal encoded unicode + cp = Integer.parseInt(e.substring(1)); + } + return new String(new int[] {cp},0,1); + } + Character knownEntity = entity.get(e); + if(knownEntity==null) { + // we don't know the entity so keep it encoded + return '&' + e + ';'; + } + return knownEntity.toString(); + } + + + /** + *
{@code 
+     * Returns the next XML meta token. This is used for skipping over 
+     * and  structures.
+     *  }
+ * @return
{@code Syntax characters (< > / = ! ?) are returned as
+     *  Character, and strings and names are returned as Boolean. We don't care
+     *  what the values actually are.
+     *  }
+ * @throws JSONException If a string is not properly closed or if the XML + * is badly structured. + */ + public Object nextMeta() throws JSONException { + char c; + char q; + do { + c = next(); + } while (Character.isWhitespace(c)); + switch (c) { + case 0: + throw syntaxError("Misshaped meta tag"); + case '<': + return XML.LT; + case '>': + return XML.GT; + case '/': + return XML.SLASH; + case '=': + return XML.EQ; + case '!': + return XML.BANG; + case '?': + return XML.QUEST; + case '"': + case '\'': + q = c; + for (;;) { + c = next(); + if (c == 0) { + throw syntaxError("Unterminated string"); + } + if (c == q) { + return Boolean.TRUE; + } + } + default: + for (;;) { + c = next(); + if (Character.isWhitespace(c)) { + return Boolean.TRUE; + } + switch (c) { + case 0: + throw syntaxError("Unterminated string"); + case '<': + case '>': + case '/': + case '=': + case '!': + case '?': + case '"': + case '\'': + back(); + return Boolean.TRUE; + } + } + } + } + + + /** + *
{@code
+     * Get the next XML Token. These tokens are found inside of angle
+     * brackets. It may be one of these characters: / > = ! ? or it
+     * may be a string wrapped in single quotes or double quotes, or it may be a
+     * name.
+     * }
+ * @return a String or a Character. + * @throws JSONException If the XML is not well formed. + */ + public Object nextToken() throws JSONException { + char c; + char q; + StringBuilder sb; + do { + c = next(); + } while (Character.isWhitespace(c)); + switch (c) { + case 0: + throw syntaxError("Misshaped element"); + case '<': + throw syntaxError("Misplaced '<'"); + case '>': + return XML.GT; + case '/': + return XML.SLASH; + case '=': + return XML.EQ; + case '!': + return XML.BANG; + case '?': + return XML.QUEST; + +// Quoted string + + case '"': + case '\'': + q = c; + sb = new StringBuilder(); + for (;;) { + c = next(); + if (c == 0) { + throw syntaxError("Unterminated string"); + } + if (c == q) { + return sb.toString(); + } + if (c == '&') { + sb.append(nextEntity(c)); + } else { + sb.append(c); + } + } + default: + +// Name + + sb = new StringBuilder(); + for (;;) { + sb.append(c); + c = next(); + if (Character.isWhitespace(c)) { + return sb.toString(); + } + switch (c) { + case 0: + return sb.toString(); + case '>': + case '/': + case '=': + case '!': + case '?': + case '[': + case ']': + back(); + return sb.toString(); + case '<': + case '"': + case '\'': + throw syntaxError("Bad character in a name"); + } + } + } + } + + + /** + * Skip characters until past the requested string. + * If it is not found, we are left at the end of the source with a result of false. + * @param to A string to skip past. + */ + // The Android implementation of JSONTokener has a public method of public void skipPast(String to) + // even though ours does not have that method, to have API compatibility, our method in the subclass + // should match. + public void skipPast(String to) { + boolean b; + char c; + int i; + int j; + int offset = 0; + int length = to.length(); + char[] circle = new char[length]; + + /* + * First fill the circle buffer with as many characters as are in the + * to string. If we reach an early end, bail. + */ + + for (i = 0; i < length; i += 1) { + c = next(); + if (c == 0) { + return; + } + circle[i] = c; + } + + /* We will loop, possibly for all of the remaining characters. */ + + for (;;) { + j = offset; + b = true; + + /* Compare the circle buffer with the to string. */ + + for (i = 0; i < length; i += 1) { + if (circle[j] != to.charAt(i)) { + b = false; + break; + } + j += 1; + if (j >= length) { + j -= length; + } + } + + /* If we exit the loop with b intact, then victory is ours. */ + + if (b) { + return; + } + + /* Get the next character. If there isn't one, then defeat is ours. */ + + c = next(); + if (c == 0) { + return; + } + /* + * Shove the character in the circle buffer and advance the + * circle offset. The offset is mod n. + */ + circle[offset] = c; + offset += 1; + if (offset >= length) { + offset -= length; + } + } + } +} diff --git a/src/main/java/org/json/XMLXsiTypeConverter.java b/src/main/java/org/json/XMLXsiTypeConverter.java new file mode 100644 index 0000000..0f8a8c3 --- /dev/null +++ b/src/main/java/org/json/XMLXsiTypeConverter.java @@ -0,0 +1,66 @@ +package org.json; +/* +Copyright (c) 2002 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +/** + * Type conversion configuration interface to be used with xsi:type attributes. + *
+ * XML Sample
+ * {@code
+ *      
+ *          12345
+ *          54321
+ *      
+ * }
+ * JSON Output
+ * {@code
+ *     {
+ *         "root" : {
+ *             "asString" : "12345",
+ *             "asInt": 54321
+ *         }
+ *     }
+ * }
+ *
+ * Usage
+ * {@code
+ *      Map> xsiTypeMap = new HashMap>();
+ *      xsiTypeMap.put("string", new XMLXsiTypeConverter() {
+ *          @Override public String convert(final String value) {
+ *              return value;
+ *          }
+ *      });
+ *      xsiTypeMap.put("integer", new XMLXsiTypeConverter() {
+ *          @Override public Integer convert(final String value) {
+ *              return Integer.valueOf(value);
+ *          }
+ *      });
+ * }
+ * 
+ * @author kumar529 + * @param return type of convert method + */ +public interface XMLXsiTypeConverter { + T convert(String value); +} diff --git a/src/teavm/java/net/lax1dude/eaglercraft/adapter/EaglerAdapterImpl2.java b/src/teavm/java/net/lax1dude/eaglercraft/adapter/EaglerAdapterImpl2.java index 7bcba2f..7cdf763 100644 --- a/src/teavm/java/net/lax1dude/eaglercraft/adapter/EaglerAdapterImpl2.java +++ b/src/teavm/java/net/lax1dude/eaglercraft/adapter/EaglerAdapterImpl2.java @@ -9,6 +9,7 @@ import java.nio.charset.Charset; import java.util.HashMap; import java.util.LinkedList; +import org.json.JSONObject; import org.teavm.interop.Async; import org.teavm.interop.AsyncCallback; import org.teavm.jso.JSBody; @@ -52,6 +53,8 @@ import net.lax1dude.eaglercraft.AssetRepository; import net.lax1dude.eaglercraft.Base64; import net.lax1dude.eaglercraft.EarlyLoadScreen; import net.lax1dude.eaglercraft.LocalStorageManager; +import net.lax1dude.eaglercraft.ServerQuery; +import net.lax1dude.eaglercraft.ServerQuery.QueryResponse; import net.lax1dude.eaglercraft.adapter.teavm.WebGLQuery; import net.lax1dude.eaglercraft.adapter.teavm.WebGLVertexArray; import net.minecraft.src.MathHelper; @@ -1032,6 +1035,7 @@ public class EaglerAdapterImpl2 { sock.onMessage(new EventListener() { @Override public void handleEvent(MessageEvent evt) { + if(isString(evt.getData())) return; Uint8Array a = Uint8Array.create(evt.getDataAsArray()); byte[] b = new byte[a.getByteLength()]; for(int i = 0; i < b.length; ++i) { @@ -1575,7 +1579,115 @@ public class EaglerAdapterImpl2 { } public static final void setClipboard(String str) { + @JSBody(params = { "obj" }, script = "return typeof obj === \"string\";") + private static native boolean isString(JSObject obj); + + private static class ServerQueryImpl implements ServerQuery { + + private final LinkedList queryResponses = new LinkedList(); + private final LinkedList queryResponsesBytes = new LinkedList(); + private final String type; + private boolean open; + + private final WebSocket sock; + + private ServerQueryImpl(String type_, String uri) { + type = type_; + WebSocket s = null; + try { + s = WebSocket.create(uri); + s.setBinaryType("arraybuffer"); + open = true; + }catch(Throwable t) { + open = false; + } + sock = s; + if(open) { + sock.onOpen(new EventListener() { + @Override + public void handleEvent(MessageEvent evt) { + sock.send("Accept: " + type); + } + }); + sock.onClose(new EventListener() { + @Override + public void handleEvent(CloseEvent evt) { + open = false; + } + }); + sock.onMessage(new EventListener() { + @Override + public void handleEvent(MessageEvent evt) { + if(isString(evt.getData())) { + try { + queryResponses.add(new QueryResponse(new JSONObject(evt.getDataAsString()))); + }catch(Throwable t) { + System.err.println("Query response could not be parsed: " + t.toString()); + } + }else { + Uint8Array a = Uint8Array.create(evt.getDataAsArray()); + byte[] b = new byte[a.getByteLength()]; + for(int i = 0; i < b.length; ++i) { + b[i] = (byte) (a.get(i) & 0xFF); + } + queryResponsesBytes.add(b); + } + } + }); + Window.setTimeout(new TimerHandler() { + @Override + public void onTimer() { + if(open && sock.getReadyState() != 1) { + if(sock.getReadyState() == 0) { + sock.close(); + } + open = false; + } + } + }, 5000l); + } + } + + @Override + public boolean isQueryOpen() { + return open; + } + + @Override + public void close() { + open = false; + sock.close(); + } + + @Override + public void send(String str) { + sock.send(str); + } + + @Override + public int responseAvailable() { + return queryResponses.size(); + } + + @Override + public int responseBinaryAvailable() { + return queryResponsesBytes.size(); + } + + @Override + public QueryResponse getResponse() { + return queryResponses.size() > 0 ? queryResponses.remove(0) : null; + } + + @Override + public byte[] getBinaryResponse() { + return queryResponsesBytes.size() > 0 ? queryResponsesBytes.remove(0) : null; + } } + public static final ServerQuery openQuery(String type, String uri) { + return new ServerQueryImpl(type, uri); + } + } diff --git a/stable-download/java/bukkit_command/craftbukkit-1.5.2-R1.0.jar b/stable-download/java/bukkit_command/craftbukkit-1.5.2-R1.0.jar index 14c97303f55ea47cd31b98bb88b8694148ca5673..81941084a8ce74743ec03db827ce04f6ea34ed58 100644 GIT binary patch delta 92894 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μ;;SsBmy>c~SFFa)v|i9(D(9|50Y|_llD=p_Dow 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

A0D`ip&f#Er;nOjJ&k{tINYX&k%NPZ(16 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Ƴ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