From f39e0f9eae0db2f5fdc9cab1913f7ba9e0d50fbe Mon Sep 17 00:00:00 2001 From: Marius Metzger Date: Fri, 23 Jan 2015 16:02:04 +0100 Subject: [PATCH] Added ApiClient for Replay Mod Website API (completely untested). --- .../eu/crushedpixel/replaymod/ReplayMod.java | 9 +- .../replaymod/api/client/ApiClient.java | 133 ++++++++++ .../replaymod/api/client/ApiException.java | 20 ++ .../replaymod/api/client/ApiMethods.java | 14 + .../replaymod/api/client/GsonApiClient.java | 38 +++ .../replaymod/api/client/QueryBuilder.java | 166 ++++++++++++ .../replaymod/api/client/SimpleApiClient.java | 119 +++++++++ .../replaymod/api/client/StreamTools.java | 247 ++++++++++++++++++ .../api/client/holders/ApiError.java | 27 ++ .../replaymod/api/client/holders/AuthKey.java | 14 + .../api/client/holders/Category.java | 23 ++ .../api/client/holders/FileInfo.java | 33 +++ .../replaymod/api/client/holders/Rating.java | 14 + .../replaymod/api/client/holders/Success.java | 10 + .../api/client/holders/UserFiles.java | 20 ++ 15 files changed, 885 insertions(+), 2 deletions(-) create mode 100644 src/main/java/eu/crushedpixel/replaymod/api/client/ApiClient.java create mode 100644 src/main/java/eu/crushedpixel/replaymod/api/client/ApiException.java create mode 100644 src/main/java/eu/crushedpixel/replaymod/api/client/ApiMethods.java create mode 100644 src/main/java/eu/crushedpixel/replaymod/api/client/GsonApiClient.java create mode 100644 src/main/java/eu/crushedpixel/replaymod/api/client/QueryBuilder.java create mode 100644 src/main/java/eu/crushedpixel/replaymod/api/client/SimpleApiClient.java create mode 100644 src/main/java/eu/crushedpixel/replaymod/api/client/StreamTools.java create mode 100644 src/main/java/eu/crushedpixel/replaymod/api/client/holders/ApiError.java create mode 100644 src/main/java/eu/crushedpixel/replaymod/api/client/holders/AuthKey.java create mode 100644 src/main/java/eu/crushedpixel/replaymod/api/client/holders/Category.java create mode 100644 src/main/java/eu/crushedpixel/replaymod/api/client/holders/FileInfo.java create mode 100644 src/main/java/eu/crushedpixel/replaymod/api/client/holders/Rating.java create mode 100644 src/main/java/eu/crushedpixel/replaymod/api/client/holders/Success.java create mode 100644 src/main/java/eu/crushedpixel/replaymod/api/client/holders/UserFiles.java diff --git a/src/main/java/eu/crushedpixel/replaymod/ReplayMod.java b/src/main/java/eu/crushedpixel/replaymod/ReplayMod.java index da6122a3..8ada0e25 100644 --- a/src/main/java/eu/crushedpixel/replaymod/ReplayMod.java +++ b/src/main/java/eu/crushedpixel/replaymod/ReplayMod.java @@ -1,5 +1,7 @@ package eu.crushedpixel.replaymod; +import java.io.IOException; + import net.minecraft.client.Minecraft; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.config.Configuration; @@ -12,6 +14,9 @@ import net.minecraftforge.fml.common.SidedProxy; import net.minecraftforge.fml.common.event.FMLInitializationEvent; import net.minecraftforge.fml.common.event.FMLPostInitializationEvent; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; +import eu.crushedpixel.replaymod.api.client.ApiClient; +import eu.crushedpixel.replaymod.api.client.ApiException; +import eu.crushedpixel.replaymod.api.client.holders.AuthKey; import eu.crushedpixel.replaymod.authentication.AuthenticationHandler; import eu.crushedpixel.replaymod.events.GuiEventHandler; import eu.crushedpixel.replaymod.events.GuiReplayOverlay; @@ -29,9 +34,9 @@ public class ReplayMod //XXX //Known Bugs // - //Keyframe removal doesn't seem to properly work + //Keyframes have problems with Linear Paths //Rain isn't working - // + //Incompatible with Shaders Mod // // diff --git a/src/main/java/eu/crushedpixel/replaymod/api/client/ApiClient.java b/src/main/java/eu/crushedpixel/replaymod/api/client/ApiClient.java new file mode 100644 index 00000000..479eb836 --- /dev/null +++ b/src/main/java/eu/crushedpixel/replaymod/api/client/ApiClient.java @@ -0,0 +1,133 @@ +package eu.crushedpixel.replaymod.api.client; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; +import java.util.List; + +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.FileEntity; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.util.EntityUtils; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import eu.crushedpixel.replaymod.api.client.holders.ApiError; +import eu.crushedpixel.replaymod.api.client.holders.AuthKey; +import eu.crushedpixel.replaymod.api.client.holders.Category; +import eu.crushedpixel.replaymod.api.client.holders.FileInfo; +import eu.crushedpixel.replaymod.api.client.holders.Success; +import eu.crushedpixel.replaymod.api.client.holders.UserFiles; + +public class ApiClient { + + private static Gson gson = new Gson(); + private static JsonParser jsonParser = new JsonParser(); + + public AuthKey getLogin(String username, String password) throws IOException, ApiException { + QueryBuilder builder = new QueryBuilder(ApiMethods.login); + builder.put("user", username); + builder.put("pw", password); + AuthKey auth = invokeAndReturn(builder, AuthKey.class); + return auth; + } + + public UserFiles getUserFiles(String auth, String user) throws IOException, ApiException { + QueryBuilder builder = new QueryBuilder(ApiMethods.replay_files); + builder.put("auth", auth); + builder.put("user", user); + UserFiles files = invokeAndReturn(builder, UserFiles.class); + return files; + } + + public FileInfo[] getFileInfo(String auth, List ids) throws IOException, ApiException { + QueryBuilder builder = new QueryBuilder(ApiMethods.replay_files); + builder.put("auth", auth); + builder.put("ids", buildListString(ids)); + FileInfo[] info = invokeAndReturn(builder, FileInfo[].class); //TODO: Test if that works + return info; + } + + public void uploadFile(String auth, File file, Category category) throws IOException, ApiException { + QueryBuilder builder = new QueryBuilder(ApiMethods.upload_file); + builder.put("auth", auth); + builder.put("category", category.getId()); + String url = builder.toString(); + + HttpClient client = new DefaultHttpClient(); + HttpPost post = new HttpPost(url); + + ((InputStream)client).close(); + + FileEntity entity = new FileEntity(file); + post.setEntity(entity); + HttpResponse response = client.execute(post); + + JsonElement element = jsonParser.parse(EntityUtils.toString(response.getEntity())); + try { + ApiError err = gson.fromJson(element, ApiError.class); + if(err.getDesc() != null) { + throw new ApiException(err); + } + } catch(Exception e) {} + } + + public void downloadFile(String auth, int file, File target) throws IOException { + QueryBuilder builder = new QueryBuilder(ApiMethods.download_file); + builder.put("auth", auth); + builder.put("id", file); + String url = builder.toString(); + URL website = new URL(url); + InputStream is = website.openStream(); + try { //If valid json, an error occured + jsonParser.parse(StreamTools.readStreamtoString(is)); + } catch(Exception e) { + Files.copy(is, target.toPath(), StandardCopyOption.REPLACE_EXISTING); + } + } + + public void rateFile(String auth, int file, boolean like) throws IOException, ApiException { + QueryBuilder builder = new QueryBuilder(ApiMethods.rate_file); + builder.put("auth", auth); + builder.put("id", file); + builder.put("like", like); + invokeAndReturn(builder, Success.class); + } + + public void removeFile(String auth, int file) throws IOException, ApiException { + QueryBuilder builder = new QueryBuilder(ApiMethods.remove_file); + builder.put("auth", auth); + builder.put("id", file); + invokeAndReturn(builder, Success.class); + } + + private T invokeAndReturn(QueryBuilder builder,Class classOfT) throws IOException, ApiException { + JsonObject arr = GsonApiClient.invoke(builder); + return gson.fromJson(arr, classOfT); + } + + @SuppressWarnings("rawtypes") + private String buildListString(List idList) { + if(idList == null) return null; + + String ids = ""; + Integer x=0; + for(Object id : idList) { + x++; + ids += id.toString(); + if(x != idList.size()) { + ids += ","; + } + } + + return ids; + } +} diff --git a/src/main/java/eu/crushedpixel/replaymod/api/client/ApiException.java b/src/main/java/eu/crushedpixel/replaymod/api/client/ApiException.java new file mode 100644 index 00000000..421a054f --- /dev/null +++ b/src/main/java/eu/crushedpixel/replaymod/api/client/ApiException.java @@ -0,0 +1,20 @@ +package eu.crushedpixel.replaymod.api.client; + +import eu.crushedpixel.replaymod.api.client.holders.ApiError; + +public class ApiException extends Exception { + + private static final long serialVersionUID = 349073390504232810L; + + private ApiError error; + + public ApiException(ApiError error) { + super(error.getDesc()); + this.error = error; + } + + public ApiError getError() { + return error; + } + +} diff --git a/src/main/java/eu/crushedpixel/replaymod/api/client/ApiMethods.java b/src/main/java/eu/crushedpixel/replaymod/api/client/ApiMethods.java new file mode 100644 index 00000000..0b4f4cb6 --- /dev/null +++ b/src/main/java/eu/crushedpixel/replaymod/api/client/ApiMethods.java @@ -0,0 +1,14 @@ +package eu.crushedpixel.replaymod.api.client; + +public class ApiMethods { + + public static final String login = "login"; + public static final String logout = "logout"; + public static final String replay_files = "replay_files"; + public static final String file_details = "file_details"; + public static final String upload_file = "upload_file"; + public static final String download_file = "download_file"; + public static final String remove_file = "remove_file"; + public static final String rate_file = "rate_file"; + +} diff --git a/src/main/java/eu/crushedpixel/replaymod/api/client/GsonApiClient.java b/src/main/java/eu/crushedpixel/replaymod/api/client/GsonApiClient.java new file mode 100644 index 00000000..27e54128 --- /dev/null +++ b/src/main/java/eu/crushedpixel/replaymod/api/client/GsonApiClient.java @@ -0,0 +1,38 @@ +package eu.crushedpixel.replaymod.api.client; + +import java.io.IOException; +import java.util.Map; + +import com.google.gson.JsonObject; +import com.google.gson.JsonElement; +import com.google.gson.JsonParser; + +public class GsonApiClient { + + private static final JsonParser parser = new JsonParser(); + + public static JsonObject invoke(QueryBuilder query) throws IOException, ApiException { + String apiResult = SimpleApiClient.invoke(query); + return wrapWithJson(apiResult); + } + + public static JsonObject invokeJson(String url) throws IOException, ApiException { + String apiResult = SimpleApiClient.invokeUrl(url); + return wrapWithJson(apiResult); + } + + public static JsonObject invokeJson(String apiKey, String method, Map paramMap) throws IOException, ApiException { + String apiResult = SimpleApiClient.invoke(method, paramMap); + return wrapWithJson(apiResult); + } + + public static JsonObject invokeJson(String apiKey, String method) throws IOException, ApiException { + String apiResult = SimpleApiClient.invoke(method, null); + return wrapWithJson(apiResult); + } + + private static JsonObject wrapWithJson(String apiResult) { + JsonElement element = parser.parse(apiResult); + return element.getAsJsonObject(); + } +} diff --git a/src/main/java/eu/crushedpixel/replaymod/api/client/QueryBuilder.java b/src/main/java/eu/crushedpixel/replaymod/api/client/QueryBuilder.java new file mode 100644 index 00000000..23393c8b --- /dev/null +++ b/src/main/java/eu/crushedpixel/replaymod/api/client/QueryBuilder.java @@ -0,0 +1,166 @@ +package eu.crushedpixel.replaymod.api.client; + +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.HashMap; +import java.util.Map; + +public class QueryBuilder { + + private static final String API_BASE_URL = "http://ReplayMod.com/api/"; + + public String apiMethod; + public Map paramMap; + + /** + * Creates an empty QueryBuilder from a given apikey. + *
Note that in order to use the QueryBuilder an apiMethod String has to be set. + * @param apiKey The apikey to use + */ + public QueryBuilder() { + this(null); + } + + /** + * Creates an empty QueryBuilder from a given apikey and apiMethod. + * + * @param apiKey The apikey to use + * @param apiMethod The apiMethod to use + */ + public QueryBuilder(String apiMethod) { + this.apiMethod = apiMethod; + } + + /** + * Creates a QueryBuilder from a given apikey and apiMethod containing a single key/value parameter. + * + * @param apiKey The apikey to use + * @param apiMethod The apiMethod to use + * @param key The parameter key + * @param value The parameter value + */ + public QueryBuilder(String apiMethod, String key, String value) { + this(apiMethod); + put(key, value); + } + + /** + * Creates a QueryBuilder from a given apikey and apiMethod containing two key/value parameters. + * + * @param apiKey The apikey to use + * @param apiMethod The apiMethod to use + * @param key1 The first parameter key + * @param value1 The first parameter value + * @param key2 The second parameter key + * @param value2 The second parameter value + */ + public QueryBuilder(String apiMethod, String key1, String value1, String key2, String value2) { + this(apiMethod); + put(key1, value1); + put(key2, value2); + } + + /** + * Creates a QueryBuilder from a given apikey and apiMethod containing three key/value parameters. + * + * @param apiKey The apikey to use + * @param apiMethod The apiMethod to use + * @param key1 The first parameter key + * @param value1 The first parameter value + * @param key2 The second parameter key + * @param value2 The second parameter value + * @param key3 The third parameter key + * @param value3 The third parameter value + */ + public QueryBuilder(String apiMethod, String key1, String value1, String key2, String value2, String key3, String value3) { + this(apiMethod); + put(key1, value1); + put(key2, value2); + put(key3, value3); + } + + /** + * Adds a key/value parameter to the QueryBuilder. + * @param key The parameter key + * @param value The parameter value + */ + public void put(String key, Object value) { + if(key != null && value != null) { + if(paramMap == null) { + paramMap = new HashMap(); + } + paramMap.put(key, value.toString()); + } + } + + /** + * Adds two key/value parameters to the QueryBuilder. + * @param key1 The first parameter key + * @param value1 The first parameter value + * @param key2 The second parameter key + * @param value2 The second parameter value + */ + public void put(String key1, Object value1, String key2, Object value2) { + put(key1, value1); + put(key2, value2); + } + + /** + * Adds three key/value parameters to the QueryBuilder. + * @param key1 The first parameter key + * @param value1 The first parameter value + * @param key2 The second parameter key + * @param value2 The second parameter value + * @param key3 The third parameter key + * @param value3 The third parameter value + */ + public void put(String key1, Object value1, String key2, Object value2, String key3, Object value3) { + put(key1, value1); + put(key2, value2); + put(key3, value3); + } + + /** + * Adds a map of key/value parameters to the QueryBuilder. + * @param paraMap The map to add + */ + public void put(Map paraMap) { + if(paraMap == null) return; + for(String key: paraMap.keySet()) { + put(key,paraMap.get(key)); + } + } + + /** + * Creates an URL from the QueryBuilder using the given apikey and apiMethod and applies all + * parameters to it. + */ + public String toString() { + if(apiMethod == null) throw new IllegalArgumentException("apiMethod may not be null"); + + StringBuilder sb = new StringBuilder(); + + // build base url + sb.append(API_BASE_URL); + sb.append(apiMethod); + + // process parameters + try { + if(paramMap != null) { + boolean first = true; + for(String paramName: paramMap.keySet()) { + if(first) sb.append("?"); + if(!first) sb.append("&"); + first = false; + sb.append(paramName); + sb.append("="); + String value = paramMap.get(paramName); + sb.append(URLEncoder.encode(value, "UTF-8")); + } + } + return sb.toString(); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/main/java/eu/crushedpixel/replaymod/api/client/SimpleApiClient.java b/src/main/java/eu/crushedpixel/replaymod/api/client/SimpleApiClient.java new file mode 100644 index 00000000..dbe98e63 --- /dev/null +++ b/src/main/java/eu/crushedpixel/replaymod/api/client/SimpleApiClient.java @@ -0,0 +1,119 @@ +package eu.crushedpixel.replaymod.api.client; + +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.Map; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import eu.crushedpixel.replaymod.api.client.holders.ApiError; + +public class SimpleApiClient { + + private static final JsonParser jsonParser = new JsonParser(); + private static final Gson gson = new Gson(); + + /** + * Returns a Json String from the given QueryBuilder + * @param query The QueryBuilder to use + * @return A Json String from the API + * @throws IOException + * @throws ApiException + */ + public static String invoke(QueryBuilder query) throws IOException, ApiException { + return invokeImpl(query.toString()); + } + + /** + * Returns a Json String from the given URL + * @param url The URL to parse the Json from + * @return A Json String from the API + * @throws IOException + * @throws ApiException + */ + public static String invokeUrl(String url) throws IOException, ApiException { + return invokeImpl(url); + } + + /** + * Returns a Json String from the API + * @param apiKey The apikey to use + * @param method The apiMethod to be called + * @param paramMap The parameters to apply + * @return A Json String from the API + * @throws IOException + * @throws ApiException + */ + public static String invoke(String method, Map paramMap) throws IOException, ApiException { + return invokeImpl(method, paramMap); + } + + /** + * Returns a Json String from the API + * @param apiKey The apikey to use + * @param method The apiMethod to be called + * @return A Json String from the API + * @throws IOException + * @throws ApiException + */ + public static String invoke(String method) throws IOException, ApiException { + return invokeImpl(method, null); + } + + private static String invokeImpl(String urlString) throws IOException, ApiException { + + // read response + String responseContent = null; + InputStream is = null; + HttpURLConnection httpUrlConnection = null; + HttpURLConnection.setFollowRedirects(false); + try { + URL url = new URL(urlString); + httpUrlConnection = (HttpURLConnection) url.openConnection(); + + httpUrlConnection.setRequestMethod("GET"); + + // give it 15 seconds to respond + httpUrlConnection.setReadTimeout(15*1000); + httpUrlConnection.connect(); + + int responseCode = httpUrlConnection.getResponseCode(); + + if(responseCode != 200) { + is = httpUrlConnection.getErrorStream(); + if(is != null) { + responseContent = StreamTools.readStreamtoString(is,"UTF-8"); + } else { + responseContent = ""; + } + JsonObject response = jsonParser.parse(responseContent).getAsJsonObject(); + throw new ApiException(gson.fromJson(response, ApiError.class)); + } + + is = httpUrlConnection.getInputStream(); + + responseContent = StreamTools.readStreamtoString(is,"UTF-8"); + + } catch(IOException e) { + throw e; + } finally { + if(is != null) { + is.close(); + } + if(httpUrlConnection != null) { + httpUrlConnection.disconnect(); + } + } + return responseContent; + } + + private static String invokeImpl(String method, Map paramMap) throws IOException, ApiException { + QueryBuilder queryBuilder = new QueryBuilder(method); + queryBuilder.put(paramMap); + return invokeImpl(queryBuilder.toString()); + } +} diff --git a/src/main/java/eu/crushedpixel/replaymod/api/client/StreamTools.java b/src/main/java/eu/crushedpixel/replaymod/api/client/StreamTools.java new file mode 100644 index 00000000..6a9fa82a --- /dev/null +++ b/src/main/java/eu/crushedpixel/replaymod/api/client/StreamTools.java @@ -0,0 +1,247 @@ +/* Leichtathletik Daten Verarbeitung (LDV) + * Copyright (C) 2004 Marc Schunk + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +package eu.crushedpixel.replaymod.api.client; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.Reader; +import java.io.StringWriter; +import java.util.zip.GZIPInputStream; +import java.util.zip.GZIPOutputStream; + +/** + * + * @author Marc Schunk, created on 21.06.2004 + * + * A Class to provide helpers of commonly user operations with binary + * and character Streams, such as read to an OutputStream/Writer, + * String, ByteArray. In addition streams can be compressed. + */ + +public class StreamTools { + + /** + * Checks weather the given array is contained in the first array + * + * @param ar1 + * - the containing array + * @param index1 + * - the index where the search starts + * @param ar2 + * - the array that schould be contained + * @return - true of ar2 is contained in ar1 + */ + public static final boolean arrayMatch(char[] ar1, int index1, char[] ar2) { + if((ar1.length - index1 - ar2.length) < 0) + return false; + for(int i = 0; i < ar2.length; i++) { + if(ar1[index1 + i] != ar2[i]) + return false; + } + return true; + } + + /** + * Reads inStream completly and writes it to outStream. Streams will not be + * closed. + * + * @param inStream + * - an InputStream to be read completely + * @param outStream + * - the destination Stream + * @throws IOException + */ + public static void readStream(InputStream inStream, OutputStream outStream) + throws IOException { + byte[] buffer = new byte[4096]; + int len = 0; + while((len = inStream.read(buffer, 0, buffer.length)) > -1) { + outStream.write(buffer, 0, len); + } + } + + /** + * Reads inStream completly into an byte[]. Streams will not be closed. + * + * @param inStream + * - an InputStream to be read completely + * @param outStream + * - the destination Stream + * @throws IOException + */ + public static byte[] readStream(InputStream inStream) throws IOException { + byte[] buffer = new byte[4096]; + int len = 0; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + while((len = inStream.read(buffer, 0, buffer.length)) > -1) { + baos.write(buffer, 0, len); + } + return baos.toByteArray(); + } + + /** + * Reads the given Steam into an String * + * + * @throws IOException + */ + public static String readStreamtoString(InputStream inStream) + throws IOException { + StringWriter sw = new StringWriter(); + InputStreamReader isr = new InputStreamReader(inStream); + + char[] buffer = new char[4096]; + int len = 0; + while((len = isr.read(buffer, 0, buffer.length)) > -1) { + sw.write(buffer, 0, len); + } + return sw.toString(); + } + + /** + * Reads the given Steam into an String using the given encoding + * + * @throws IOException + */ + public static String readStreamtoString(InputStream inStream, String charSet) + throws IOException { + StringWriter sw = new StringWriter(); + InputStreamReader isr = new InputStreamReader(inStream, charSet); + + char[] buffer = new char[4096]; + int len = 0; + while((len = isr.read(buffer, 0, buffer.length)) > -1) { + sw.write(buffer, 0, len); + } + return sw.toString(); + } + + public static String stripComments(String inString, String newLineDelimiter) + throws IOException { + StringWriter sw = new StringWriter(); + // use both windows and linux/unix line seperators to be independent of the file orgin + String[] lines = inString.split("\r\n|\n"); + for(String line : lines) { + if((line.indexOf("#") == -1) && (line.trim().length() > 0)) { + sw.append(line).append(newLineDelimiter); + } + } + return sw.toString(); + } + + public static final String[] umlauteString = {"&", "ß", "ä", + "Ä", "ö", "Ö", "ü", "Ü", "ß"}; + public static final String[] umlauteReplacement = {"&", "ß", "ä", "Ä", "ö", + "Ö", "ü", "Ü", "ß"}; + + public static String replaceSpecialCharacters(String s) { + for(int i = 0; i < umlauteString.length; i++) { + s = s.replaceAll(umlauteString[i], umlauteReplacement[i]); + } + return s; + } + + /** + * Stores the given Stream in an byte[]. Stream is compressed on the fly. + * Streams will not be closed. + * + * @param inStream + * - an InputStream to be read completely + * @param outStream + * - the destination Stream + * @throws IOException + */ + public static byte[] compressStreamToByteArray(InputStream inStream) + throws IOException { + byte[] buffer = new byte[4096]; + int len = 0; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + GZIPOutputStream zos = new GZIPOutputStream(baos); + while((len = inStream.read(buffer, 0, buffer.length)) > -1) { + zos.write(buffer, 0, len); + } + zos.close(); + return baos.toByteArray(); + } + + /** + * Stores the given Stream in an byte[]. Stream is compressed on the fly. + * Streams will not be closed. + * + * @param inStream + * - an InputStream to be read completely + * @param outStream + * - the destination Stream + * @throws IOException + */ + public static byte[] compress(byte[] uncompressed) throws IOException { + ByteArrayInputStream bais = new ByteArrayInputStream(uncompressed); + return compressStreamToByteArray(bais); + } + + /** + * Stores the given Stream in an byte[]. Stream is decompressed on the fly. + * Thus, the input stream should contain compressed content. Streams will + * not be closed. + * + * @param inStream + * - an InputStream to be read completely + * @param outStream + * - the destination Stream + * @throws IOException + */ + public static byte[] decompressStreamToByteArray(InputStream inStream) + throws IOException { + byte[] buffer = new byte[4096]; + int len = 0; + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + GZIPInputStream gzis = new GZIPInputStream(inStream); + while((len = gzis.read(buffer, 0, buffer.length)) > -1) { + baos.write(buffer, 0, len); + } + inStream.close(); + return baos.toByteArray(); + } + + public static byte[] decompress(byte[] compressed) throws IOException { + ByteArrayInputStream bais = new ByteArrayInputStream(compressed); + return decompressStreamToByteArray(bais); + } + + /** + * Reads the given Steam into an String * + * + * @throws IOException + */ + public static String readReaderToString(Reader reader) throws IOException { + StringBuffer sb = new StringBuffer(); + + char[] buffer = new char[4096]; + int len = 0; + while((len = reader.read(buffer, 0, buffer.length)) > -1) { + sb.append(buffer, 0, len); + } + return sb.toString(); + } + +} diff --git a/src/main/java/eu/crushedpixel/replaymod/api/client/holders/ApiError.java b/src/main/java/eu/crushedpixel/replaymod/api/client/holders/ApiError.java new file mode 100644 index 00000000..5050172a --- /dev/null +++ b/src/main/java/eu/crushedpixel/replaymod/api/client/holders/ApiError.java @@ -0,0 +1,27 @@ +package eu.crushedpixel.replaymod.api.client.holders; + +public class ApiError { + + public ApiError(int id, String desc) { + this.id = id; + this.desc = desc; + } + + private int id; + private String desc; + + public int getId() { + return id; + } + public void setId(int id) { + this.id = id; + } + public String getDesc() { + return desc; + } + public void setDesc(String desc) { + this.desc = desc; + } + + +} diff --git a/src/main/java/eu/crushedpixel/replaymod/api/client/holders/AuthKey.java b/src/main/java/eu/crushedpixel/replaymod/api/client/holders/AuthKey.java new file mode 100644 index 00000000..a5b77b82 --- /dev/null +++ b/src/main/java/eu/crushedpixel/replaymod/api/client/holders/AuthKey.java @@ -0,0 +1,14 @@ +package eu.crushedpixel.replaymod.api.client.holders; + +public class AuthKey { + + private String auth; + + public AuthKey(String authkey) { + this.auth = authkey; + } + + public String getAuthkey() { + return auth; + } +} diff --git a/src/main/java/eu/crushedpixel/replaymod/api/client/holders/Category.java b/src/main/java/eu/crushedpixel/replaymod/api/client/holders/Category.java new file mode 100644 index 00000000..8794aedf --- /dev/null +++ b/src/main/java/eu/crushedpixel/replaymod/api/client/holders/Category.java @@ -0,0 +1,23 @@ +package eu.crushedpixel.replaymod.api.client.holders; + +public enum Category { + + SURVIVAL(0), MINIGAME(1), BUILD(2); + + private int id; + + Category(int id) { + this.id = id; + } + + public int getId() { + return this.id; + } + + public Category fromId(int id) { + for(Category c : values()) { + if(c.id == id) return c; + } + return null; + } +} diff --git a/src/main/java/eu/crushedpixel/replaymod/api/client/holders/FileInfo.java b/src/main/java/eu/crushedpixel/replaymod/api/client/holders/FileInfo.java new file mode 100644 index 00000000..d9ffc3c1 --- /dev/null +++ b/src/main/java/eu/crushedpixel/replaymod/api/client/holders/FileInfo.java @@ -0,0 +1,33 @@ +package eu.crushedpixel.replaymod.api.client.holders; + +import eu.crushedpixel.replaymod.recording.ReplayMetaData; + +public class FileInfo { + + private int id; + private ReplayMetaData metadata; + private String owner; + private Rating ratings; + private int size; + private int category; + + public int getId() { + return id; + } + public ReplayMetaData getMetadata() { + return metadata; + } + public String getOwner() { + return owner; + } + public Rating getRatings() { + return ratings; + } + public int getSize() { + return size; + } + public int getCategory() { + return category; + } + +} diff --git a/src/main/java/eu/crushedpixel/replaymod/api/client/holders/Rating.java b/src/main/java/eu/crushedpixel/replaymod/api/client/holders/Rating.java new file mode 100644 index 00000000..82c56307 --- /dev/null +++ b/src/main/java/eu/crushedpixel/replaymod/api/client/holders/Rating.java @@ -0,0 +1,14 @@ +package eu.crushedpixel.replaymod.api.client.holders; + +public class Rating { + + private int negative, positive; + + public int getNegative() { + return negative; + } + + public int getPositive() { + return positive; + } +} diff --git a/src/main/java/eu/crushedpixel/replaymod/api/client/holders/Success.java b/src/main/java/eu/crushedpixel/replaymod/api/client/holders/Success.java new file mode 100644 index 00000000..5db3c4ab --- /dev/null +++ b/src/main/java/eu/crushedpixel/replaymod/api/client/holders/Success.java @@ -0,0 +1,10 @@ +package eu.crushedpixel.replaymod.api.client.holders; + +public class Success { + + private boolean success = false; + + public boolean isSuccess() { + return success; + } +} diff --git a/src/main/java/eu/crushedpixel/replaymod/api/client/holders/UserFiles.java b/src/main/java/eu/crushedpixel/replaymod/api/client/holders/UserFiles.java new file mode 100644 index 00000000..b10ac74b --- /dev/null +++ b/src/main/java/eu/crushedpixel/replaymod/api/client/holders/UserFiles.java @@ -0,0 +1,20 @@ +package eu.crushedpixel.replaymod.api.client.holders; + +public class UserFiles { + + private String user; + private FileInfo[] files; + private int total_size; + + public String getUser() { + return user; + } + public FileInfo[] getFiles() { + return files; + } + public int getTotal_size() { + return total_size; + } + + +}