Implement a mini-application inside the Google Sheets module that provides an easy way to get skin data
This commit is contained in:
parent
c7e4d5b00b
commit
4f6d24dea8
@ -13,6 +13,12 @@
|
||||
<artifactId>mineplex-google-sheets</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.googlecode.json-simple</groupId>
|
||||
<artifactId>json-simple</artifactId>
|
||||
<version>1.1.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.json</groupId>
|
||||
<artifactId>json</artifactId>
|
||||
|
@ -1,74 +1,28 @@
|
||||
package mineplex.googlesheets;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.awt.*;
|
||||
|
||||
import org.json.JSONObject;
|
||||
import mineplex.googlesheets.sheetparser.SheetProviderImpl;
|
||||
import mineplex.googlesheets.skinhelper.SkinHelperUI;
|
||||
|
||||
public class GoogleSheetController
|
||||
{
|
||||
|
||||
private static final int SLEEP_TIME = 1000;
|
||||
private static final String DATA_STORE_DIR = ".." + File.separatorChar + ".." + File.separatorChar + "update" + File.separatorChar + "files";
|
||||
|
||||
public static void main(String[] args) throws InterruptedException
|
||||
public static void main(String[] args)
|
||||
{
|
||||
String sheetToRead = System.getProperty("sheet");
|
||||
SpreadsheetType[] types;
|
||||
String module = System.getProperty("module");
|
||||
|
||||
if (sheetToRead == null)
|
||||
if (module == null || module.equalsIgnoreCase("sheetparser"))
|
||||
{
|
||||
types = SpreadsheetType.values();
|
||||
new SheetProviderImpl();
|
||||
}
|
||||
else
|
||||
else if (module.equalsIgnoreCase("skinhelper"))
|
||||
{
|
||||
types = new SpreadsheetType[]{SpreadsheetType.valueOf(sheetToRead)};
|
||||
}
|
||||
|
||||
System.out.println("Loading Sheet Provider");
|
||||
SheetProvider provider = new SheetProvider();
|
||||
System.out.println("Loaded Sheet Provider");
|
||||
|
||||
for (SpreadsheetType type : types)
|
||||
{
|
||||
System.out.println("Sleeping...");
|
||||
Thread.sleep(SLEEP_TIME);
|
||||
System.out.println("Getting data for " + type.name() + " (" + type.getID() + ")");
|
||||
|
||||
JSONObject object = provider.asJSONObject(type);
|
||||
|
||||
System.out.println("Done");
|
||||
System.out.println("Saving to file...");
|
||||
|
||||
File dir = new File(DATA_STORE_DIR);
|
||||
File file = new File(dir + File.separator + type.name() + ".json");
|
||||
|
||||
if (!dir.exists())
|
||||
EventQueue.invokeLater(() ->
|
||||
{
|
||||
System.out.println("mkdir");
|
||||
dir.mkdirs();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
System.out.println("Deleting");
|
||||
file.delete();
|
||||
System.out.println("new File");
|
||||
file.createNewFile();
|
||||
|
||||
FileWriter writer = new FileWriter(file);
|
||||
|
||||
System.out.println("Writing");
|
||||
writer.write(object.toString());
|
||||
|
||||
System.out.println("Closing...");
|
||||
writer.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
SkinHelperUI frame = new SkinHelperUI();
|
||||
frame.setVisible(true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@ public enum SpreadsheetType
|
||||
_id = id;
|
||||
}
|
||||
|
||||
public String getID()
|
||||
public String getId()
|
||||
{
|
||||
return _id;
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
package mineplex.googlesheets;
|
||||
package mineplex.googlesheets.sheetparser;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -28,13 +28,19 @@ import com.google.api.services.sheets.v4.SheetsScopes;
|
||||
import com.google.api.services.sheets.v4.model.Sheet;
|
||||
import com.google.api.services.sheets.v4.model.Spreadsheet;
|
||||
|
||||
import mineplex.googlesheets.SpreadsheetType;
|
||||
|
||||
/**
|
||||
* A provider class designed with the functionality to get data from a <a href="https://docs.google.com/spreadsheets">Google Spreadsheet</a>.<br>
|
||||
* Then proceed to return this data within the context of a {@link JSONObject}.
|
||||
*/
|
||||
public class SheetProvider
|
||||
{
|
||||
|
||||
/** Application name. */
|
||||
/** Service name. */
|
||||
private static final String APPLICATION_NAME = "Mineplex Google Sheets";
|
||||
|
||||
/** Directory to store user credentials for this application. */
|
||||
/** Directory to store user credentials for the service. */
|
||||
private static final File DATA_STORE_DIR = new File(".." + File.separatorChar + ".." + File.separatorChar + "update" + File.separatorChar + "files");
|
||||
|
||||
/** Global instance of the {@link FileDataStoreFactory}. */
|
||||
@ -46,7 +52,8 @@ public class SheetProvider
|
||||
/** Global instance of the HTTP transport. */
|
||||
private static HttpTransport HTTP_TRANSPORT;
|
||||
|
||||
private static final List<String> SCOPES = Arrays.asList(SheetsScopes.SPREADSHEETS);
|
||||
/** List of all permissions that the service requires */
|
||||
private static final List<String> SCOPES = Collections.singletonList(SheetsScopes.SPREADSHEETS);
|
||||
|
||||
private Sheets _service;
|
||||
private Credential _credential;
|
||||
@ -81,9 +88,9 @@ public class SheetProvider
|
||||
* Creates an authorized Credential object.
|
||||
*
|
||||
* @return an authorized Credential object.
|
||||
* @throws IOException
|
||||
* @throws IOException If the Credential fails to authorise.
|
||||
*/
|
||||
public Credential authorize() throws IOException
|
||||
private Credential authorize() throws IOException
|
||||
{
|
||||
// Load client secrets.
|
||||
InputStream in = new FileInputStream(DATA_STORE_DIR + File.separator + "client_secret.json");
|
||||
@ -91,28 +98,37 @@ public class SheetProvider
|
||||
|
||||
// Build flow and trigger user authorization request.
|
||||
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(HTTP_TRANSPORT, JSON_FACTORY, clientSecrets, SCOPES).setDataStoreFactory(DATA_STORE_FACTORY).setAccessType("offline").build();
|
||||
Credential credential = new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user");
|
||||
return credential;
|
||||
return new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user");
|
||||
}
|
||||
|
||||
/**
|
||||
* Build and return an authorized Sheets API client service.
|
||||
*
|
||||
* @return an authorized Sheets API client service
|
||||
* @throws IOException
|
||||
*/
|
||||
public Sheets getSheetsService()
|
||||
private Sheets getSheetsService()
|
||||
{
|
||||
return new Sheets.Builder(HTTP_TRANSPORT, JSON_FACTORY, _credential).setApplicationName(APPLICATION_NAME).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data comprised inside a Google Spreadsheet in the context of a {@link JSONObject}.
|
||||
*
|
||||
* @param spreadsheet The {@link SpreadsheetType} that you need to get the data from.
|
||||
* @return A {@link JSONObject} containing all the data about a spreadsheet mapped by sheet -> rows -> columns.
|
||||
*/
|
||||
public JSONObject asJSONObject(SpreadsheetType spreadsheet)
|
||||
{
|
||||
JSONObject parent = new JSONObject();
|
||||
JSONArray array = new JSONArray();
|
||||
Map<String, List<List<Object>>> valuesMap = get(spreadsheet);
|
||||
|
||||
for (String sheetName : valuesMap.keySet())
|
||||
|
||||
if (valuesMap == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
valuesMap.forEach((sheetName, lists) ->
|
||||
{
|
||||
List<List<Object>> values = valuesMap.get(sheetName);
|
||||
|
||||
@ -122,20 +138,21 @@ public class SheetProvider
|
||||
object.put("values", values);
|
||||
|
||||
array.put(object);
|
||||
}
|
||||
});
|
||||
|
||||
parent.put("data", array);
|
||||
return parent;
|
||||
}
|
||||
|
||||
public Map<String, List<List<Object>>> get(SpreadsheetType spreadsheet)
|
||||
|
||||
private Map<String, List<List<Object>>> get(SpreadsheetType spreadsheet)
|
||||
{
|
||||
try
|
||||
{
|
||||
Spreadsheet googleSpreadsheet = _service.spreadsheets().get(spreadsheet.getID()).execute();
|
||||
Map<String, List<List<Object>>> valuesMap = new HashMap<>(googleSpreadsheet.getSheets().size() - 1);
|
||||
Spreadsheet googleSpreadsheet = _service.spreadsheets().get(spreadsheet.getId()).execute();
|
||||
List<Sheet> sheets = googleSpreadsheet.getSheets();
|
||||
Map<String, List<List<Object>>> valuesMap = new HashMap<>(sheets.size());
|
||||
|
||||
for (Sheet sheet : googleSpreadsheet.getSheets())
|
||||
for (Sheet sheet : sheets)
|
||||
{
|
||||
String name = sheet.getProperties().getTitle();
|
||||
|
||||
@ -152,9 +169,9 @@ public class SheetProvider
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<List<Object>> get(SpreadsheetType spreadsheet, String sheetName) throws IOException
|
||||
private List<List<Object>> get(SpreadsheetType spreadsheet, String sheetName) throws IOException
|
||||
{
|
||||
return _service.spreadsheets().values().get(spreadsheet.getID(), sheetName).execute().getValues();
|
||||
return _service.spreadsheets().values().get(spreadsheet.getId(), sheetName).execute().getValues();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
package mineplex.googlesheets.sheetparser;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import mineplex.googlesheets.SpreadsheetType;
|
||||
|
||||
public class SheetProviderImpl
|
||||
{
|
||||
|
||||
private static final int SLEEP_TIME = 1000;
|
||||
private static final String DATA_STORE_DIR = ".." + File.separatorChar + ".." + File.separatorChar + "update" + File.separatorChar + "files";
|
||||
|
||||
public SheetProviderImpl()
|
||||
{
|
||||
String sheetToRead = System.getProperty("sheet");
|
||||
SpreadsheetType[] types;
|
||||
|
||||
if (sheetToRead == null)
|
||||
{
|
||||
types = SpreadsheetType.values();
|
||||
}
|
||||
else
|
||||
{
|
||||
types = new SpreadsheetType[]{SpreadsheetType.valueOf(sheetToRead)};
|
||||
}
|
||||
|
||||
System.out.println("Loading Sheet Provider");
|
||||
SheetProvider provider = new SheetProvider();
|
||||
System.out.println("Loaded Sheet Provider");
|
||||
|
||||
for (SpreadsheetType type : types)
|
||||
{
|
||||
System.out.println("Sleeping...");
|
||||
try
|
||||
{
|
||||
Thread.sleep(SLEEP_TIME);
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
System.out.println("Getting data for " + type.name() + " (" + type.getId() + ")");
|
||||
|
||||
JSONObject object = provider.asJSONObject(type);
|
||||
|
||||
System.out.println("Done");
|
||||
System.out.println("Saving to file...");
|
||||
|
||||
File dir = new File(DATA_STORE_DIR);
|
||||
File file = new File(dir + File.separator + type.name() + ".json");
|
||||
|
||||
if (!dir.exists())
|
||||
{
|
||||
dir.mkdirs();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
System.out.println("Deleting");
|
||||
file.delete();
|
||||
System.out.println("Creating a new file");
|
||||
file.createNewFile();
|
||||
|
||||
FileWriter writer = new FileWriter(file);
|
||||
|
||||
System.out.println("Writing");
|
||||
writer.write(object.toString());
|
||||
|
||||
System.out.println("Closing...");
|
||||
writer.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,115 @@
|
||||
package mineplex.googlesheets.skinhelper;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import java.awt.*;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import mineplex.googlesheets.util.SkinFetcher;
|
||||
import mineplex.googlesheets.util.UUIDFetcher;
|
||||
|
||||
public class SkinHelperUI extends JFrame
|
||||
{
|
||||
|
||||
private static final Font FONT = new Font("Verdana", Font.PLAIN, 12);
|
||||
private static final long FETCH_WAIT_TIME = 30;
|
||||
private static final long FETCH_WAIT_MILLISECONDS = TimeUnit.SECONDS.toMillis(FETCH_WAIT_TIME);
|
||||
|
||||
private long _lastFetch;
|
||||
|
||||
public SkinHelperUI()
|
||||
{
|
||||
setTitle("Skin Helper");
|
||||
setResizable(false);
|
||||
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
|
||||
setBounds(100, 100, 150, 300);
|
||||
JPanel contentPane = new JPanel();
|
||||
contentPane.setBackground(Color.DARK_GRAY);
|
||||
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
|
||||
setContentPane(contentPane);
|
||||
contentPane.setLayout(null);
|
||||
|
||||
JTextField txtMinecraftName = new JTextField();
|
||||
txtMinecraftName.setFont(FONT);
|
||||
txtMinecraftName.setForeground(Color.WHITE);
|
||||
txtMinecraftName.setBackground(Color.GRAY);
|
||||
txtMinecraftName.setBounds(10, 55, 124, 20);
|
||||
txtMinecraftName.setColumns(10);
|
||||
contentPane.add(txtMinecraftName);
|
||||
|
||||
JLabel lblMinecraftName = new JLabel("Minecraft Name");
|
||||
lblMinecraftName.setForeground(Color.WHITE);
|
||||
lblMinecraftName.setFont(FONT);
|
||||
lblMinecraftName.setBounds(10, 30, 100, 14);
|
||||
contentPane.add(lblMinecraftName);
|
||||
|
||||
JButton btnOk = new JButton("OK");
|
||||
btnOk.setForeground(Color.WHITE);
|
||||
btnOk.setBackground(Color.DARK_GRAY);
|
||||
btnOk.setBounds(10, 86, 124, 23);
|
||||
contentPane.add(btnOk);
|
||||
|
||||
JLabel lblSkinValue = new JLabel("Skin Value");
|
||||
lblSkinValue.setForeground(Color.WHITE);
|
||||
lblSkinValue.setFont(FONT);
|
||||
lblSkinValue.setBounds(10, 120, 100, 14);
|
||||
contentPane.add(lblSkinValue);
|
||||
|
||||
JTextField txtSkinValue = new JTextField();
|
||||
txtSkinValue.setEditable(false);
|
||||
txtSkinValue.setForeground(Color.WHITE);
|
||||
txtSkinValue.setBackground(Color.GRAY);
|
||||
txtSkinValue.setFont(FONT);
|
||||
txtSkinValue.setColumns(10);
|
||||
txtSkinValue.setBounds(10, 145, 124, 20);
|
||||
contentPane.add(txtSkinValue);
|
||||
|
||||
JLabel lblSkinSignature = new JLabel("Skin Signature");
|
||||
lblSkinSignature.setForeground(Color.WHITE);
|
||||
lblSkinSignature.setFont(FONT);
|
||||
lblSkinSignature.setBounds(10, 176, 100, 14);
|
||||
contentPane.add(lblSkinSignature);
|
||||
|
||||
JTextField txtSkinSignature = new JTextField();
|
||||
txtSkinSignature.setEditable(false);
|
||||
txtSkinSignature.setForeground(Color.WHITE);
|
||||
txtSkinSignature.setBackground(Color.GRAY);
|
||||
txtSkinSignature.setFont(FONT);
|
||||
txtSkinSignature.setColumns(10);
|
||||
txtSkinSignature.setBounds(10, 201, 124, 20);
|
||||
contentPane.add(txtSkinSignature);
|
||||
|
||||
btnOk.addMouseListener(new MouseAdapter()
|
||||
{
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent event)
|
||||
{
|
||||
if (System.currentTimeMillis() - _lastFetch < FETCH_WAIT_MILLISECONDS)
|
||||
{
|
||||
JOptionPane.showMessageDialog(SkinHelperUI.this, "You must wait a minimum of " + FETCH_WAIT_TIME + " seconds between each skin fetch to prevent you from being blocked from using the Mojang API.");
|
||||
return;
|
||||
}
|
||||
|
||||
txtSkinValue.setText("Fetching...");
|
||||
txtSkinSignature.setText(txtSkinValue.getText());
|
||||
|
||||
try
|
||||
{
|
||||
String[] skinData = SkinFetcher.getSkinData(UUIDFetcher.getPlayerUUIDNoDashes(txtMinecraftName.getText()));
|
||||
|
||||
txtSkinValue.setText(skinData[0]);
|
||||
txtSkinSignature.setText(skinData[1]);
|
||||
|
||||
_lastFetch = System.currentTimeMillis();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
JOptionPane.showMessageDialog(SkinHelperUI.this, "Please check the Minecraft Name you have entered. If it is correct please wait a minute and try again.");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package mineplex.googlesheets.util;
|
||||
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
public class SkinFetcher
|
||||
{
|
||||
|
||||
private static final String SKIN_URL = "https://sessionserver.mojang.com/session/minecraft/profile/UUID?unsigned=false";
|
||||
|
||||
public static String[] getSkinData(String uuid) throws Exception
|
||||
{
|
||||
String[] skinData = new String[2];
|
||||
JSONObject object = UtilJSON.getFromURL(SKIN_URL.replaceFirst("UUID", uuid));
|
||||
JSONArray properties = (JSONArray) object.get("properties");
|
||||
|
||||
System.out.println(properties.size());
|
||||
|
||||
for (Object o : properties)
|
||||
{
|
||||
System.out.println(o.toString());
|
||||
}
|
||||
|
||||
JSONObject innerObject = (JSONObject) properties.get(0);
|
||||
|
||||
System.out.println(innerObject.size());
|
||||
|
||||
for (Object o : innerObject.entrySet())
|
||||
{
|
||||
System.out.println(o.toString());
|
||||
}
|
||||
|
||||
skinData[1] = (String) innerObject.get("signature");
|
||||
skinData[0] = (String) innerObject.get("value");
|
||||
|
||||
System.out.println(skinData[0]);
|
||||
System.out.println(skinData[1]);
|
||||
|
||||
return skinData;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
package mineplex.googlesheets.util;
|
||||
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.parser.JSONParser;
|
||||
|
||||
/**
|
||||
* A utility to fetch UUIDs based on a player's name.
|
||||
* Adapted from UUIDFetcher inside Core.Common.
|
||||
*/
|
||||
public class UUIDFetcher
|
||||
{
|
||||
|
||||
private static final String PROFILE_URL = "https://api.mojang.com/profiles/minecraft";
|
||||
private static final JSONParser PARSER = new JSONParser();
|
||||
|
||||
public static String getPlayerUUIDNoDashes(String name) throws Exception
|
||||
{
|
||||
String uuid = null;
|
||||
List<String> nameList = Collections.singletonList(name);
|
||||
|
||||
HttpURLConnection connection = createConnection();
|
||||
String body = JSONArray.toJSONString(nameList);
|
||||
writeBody(connection, body);
|
||||
JSONArray array = (JSONArray) PARSER.parse(new InputStreamReader(connection.getInputStream()));
|
||||
|
||||
for (Object profile : array)
|
||||
{
|
||||
JSONObject jsonProfile = (JSONObject) profile;
|
||||
uuid = (String) jsonProfile.get("id");
|
||||
}
|
||||
|
||||
return uuid;
|
||||
}
|
||||
|
||||
private static void writeBody(HttpURLConnection connection, String body) throws Exception
|
||||
{
|
||||
OutputStream stream = connection.getOutputStream();
|
||||
stream.write(body.getBytes());
|
||||
stream.flush();
|
||||
stream.close();
|
||||
}
|
||||
|
||||
private static HttpURLConnection createConnection() throws Exception
|
||||
{
|
||||
URL url = new URL(PROFILE_URL);
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setRequestMethod("POST");
|
||||
connection.setRequestProperty("Content-Type", "application/json");
|
||||
connection.setUseCaches(false);
|
||||
connection.setDoInput(true);
|
||||
connection.setDoOutput(true);
|
||||
return connection;
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package mineplex.googlesheets.util;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.parser.JSONParser;
|
||||
import org.json.simple.parser.ParseException;
|
||||
|
||||
public class UtilJSON
|
||||
{
|
||||
|
||||
private static final JSONParser PARSER = new JSONParser();
|
||||
|
||||
private static String readAll(Reader rd) throws IOException
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int cp;
|
||||
while ((cp = rd.read()) != -1)
|
||||
{
|
||||
sb.append((char) cp);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static JSONObject getFromURL(String url) throws IOException, ParseException
|
||||
{
|
||||
try (InputStream is = new URL(url).openStream())
|
||||
{
|
||||
BufferedReader rd = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
|
||||
String jsonText = readAll(rd);
|
||||
return (JSONObject) PARSER.parse(jsonText);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user