From b79a59f584c9d347fba730f9777e327f9ce38016 Mon Sep 17 00:00:00 2001 From: Mysticdrew Date: Thu, 7 Mar 2024 22:15:04 -0600 Subject: [PATCH] remove ModInfo --- .../journeymap/client/JourneymapClient.java | 8 +- src/main/java/modinfo/Config.java | 208 ---------- src/main/java/modinfo/ModInfo.java | 383 ------------------ src/main/java/modinfo/mp/v1/Client.java | 204 ---------- src/main/java/modinfo/mp/v1/Message.java | 108 ----- src/main/java/modinfo/mp/v1/Payload.java | 213 ---------- 6 files changed, 1 insertion(+), 1123 deletions(-) delete mode 100644 src/main/java/modinfo/Config.java delete mode 100644 src/main/java/modinfo/ModInfo.java delete mode 100644 src/main/java/modinfo/mp/v1/Client.java delete mode 100644 src/main/java/modinfo/mp/v1/Message.java delete mode 100644 src/main/java/modinfo/mp/v1/Payload.java diff --git a/src/main/java/journeymap/client/JourneymapClient.java b/src/main/java/journeymap/client/JourneymapClient.java index 7f67eff..d98176f 100644 --- a/src/main/java/journeymap/client/JourneymapClient.java +++ b/src/main/java/journeymap/client/JourneymapClient.java @@ -41,7 +41,6 @@ import journeymap.common.CommonProxy; import journeymap.common.Journeymap; import journeymap.common.version.VersionCheck; -import modinfo.ModInfo; import net.minecraft.client.Minecraft; import net.minecraft.entity.player.EntityPlayerMP; import org.apache.logging.log4j.LogManager; @@ -258,7 +257,7 @@ public void initialize(FMLInitializationEvent event) throws Throwable // Logging for thread debugging threadLogging = false; - + logger.info("initialize EXIT, " + (timer == null ? "" : timer.getLogReportString())); } catch (Throwable t) @@ -313,11 +312,6 @@ public void postInitialize(FMLPostInitializationEvent event) VersionCheck.getVersionAvailable(); - // ModInfo with a single ping - ModInfo modInfo = new ModInfo("UA-28839029-5", "en_US", Journeymap.MOD_ID, MOD_NAME, FULL_VERSION, false); - modInfo.reportAppView(); - - // threadLogging = getLogger().isTraceEnabled(); } catch (Throwable t) { diff --git a/src/main/java/modinfo/Config.java b/src/main/java/modinfo/Config.java deleted file mode 100644 index 93a261d..0000000 --- a/src/main/java/modinfo/Config.java +++ /dev/null @@ -1,208 +0,0 @@ -/* - * JourneyMap Mod for Minecraft - * Copyright (c) 2011-2017 Techbrew Interactive, LLC . All Rights Reserved. - */ - -package modinfo; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import net.minecraft.client.Minecraft; -import org.apache.logging.log4j.Level; - -import java.io.*; -import java.util.UUID; - -/** - * @author techbrew 2/20/14. - */ -public class Config implements Serializable -{ - - private static final String[] HEADERS = { - "// ModInfo v%s - Configuration file for %s", - "// ModInfo is a simple utility which helps the Mod developer support their mod.", - "// For more information: https://github.com/MCModInfo/modinfo/blob/master/README.md" - }; - private static final String PARENT_DIR = "config"; - private static final String FILE_PATTERN = "%s_ModInfo.cfg"; - private static final String ENABLED_STATUS_PATTERN = "Enabled (%s)"; - private static final String DISABLED_STATUS_PATTERN = "Disabled (%s)"; - - private String modId; - private Boolean enable; - private String salt; - private String status; - private Boolean verbose; - - private Config() - { - } - - public static synchronized Config getInstance(String modId) - { - Config config = null; - File configFile = getFile(modId); - if (configFile.exists()) - { - try - { - Gson gson = new Gson(); - config = gson.fromJson(new FileReader(configFile), Config.class); - } - catch (Exception e) - { - ModInfo.LOGGER.log(Level.ERROR, "Can't read file " + configFile, e.getMessage()); - if (configFile.exists()) - { - configFile.delete(); - } - } - } - - if (config == null) - { - config = new Config(); - } - - config.validate(modId); - - return config; - } - - static boolean isConfirmedDisabled(Config config) - { - return config.enable == false && generateStatusString(config).equals(config.status); - } - - static String generateStatusString(Config config) - { - return generateStatusString(config.modId, config.enable); - } - - static String generateStatusString(String modId, Boolean enable) - { - UUID uuid = ModInfo.createUUID(modId, enable.toString()); - String pattern = enable ? ENABLED_STATUS_PATTERN : DISABLED_STATUS_PATTERN; - return String.format(pattern, uuid.toString()); - } - - private static File getFile(String modId) - { - Minecraft minecraft = Minecraft.getMinecraft(); - File dir = new File(minecraft.mcDataDir, PARENT_DIR); - if (!dir.exists()) - { - dir.mkdirs(); - } - return new File(dir, String.format(FILE_PATTERN, modId.replaceAll("%", "_"))); - } - - private void validate(String modId) - { - boolean dirty = false; - - if (!modId.equals(this.modId)) - { - this.modId = modId; - dirty = true; - } - - if (enable == null) - { - this.enable = Boolean.TRUE; - dirty = true; - } - - if (salt == null) - { - salt = Long.toHexString(System.currentTimeMillis()); - dirty = true; - } - - if (verbose == null) - { - this.verbose = Boolean.FALSE; - dirty = true; - } - - if (dirty) - { - save(); - } - } - - public void save() - { - File configFile = getFile(modId); - try - { - // Header - String lineEnding = System.getProperty("line.separator"); - StringBuilder sb = new StringBuilder(); - for (String line : HEADERS) - { - sb.append(line).append(lineEnding); - } - String header = String.format(sb.toString(), ModInfo.VERSION, this.modId); - - // Json body - Gson gson = new GsonBuilder().setPrettyPrinting().create(); - String json = gson.toJson(this); - - // Write to file - FileWriter fw = new FileWriter(configFile); - fw.write(header); - fw.write(json); - fw.flush(); - fw.close(); - - } - catch (IOException e) - { - ModInfo.LOGGER.log(Level.ERROR, "Can't save file " + configFile, e); - } - } - - public String getSalt() - { - return salt; - } - - public String getModId() - { - return modId; - } - - public Boolean isEnabled() - { - return enable; - } - - public Boolean isVerbose() - { - return verbose; - } - - public String getStatus() - { - return status; - } - - void disable() - { - this.enable = false; - confirmStatus(); - } - - public void confirmStatus() - { - String newStatus = generateStatusString(this); - if (!newStatus.equals(status)) - { - status = newStatus; - save(); - } - } - -} diff --git a/src/main/java/modinfo/ModInfo.java b/src/main/java/modinfo/ModInfo.java deleted file mode 100644 index 4bb8888..0000000 --- a/src/main/java/modinfo/ModInfo.java +++ /dev/null @@ -1,383 +0,0 @@ -/* - * JourneyMap Mod for Minecraft - * Copyright (c) 2011-2017 Techbrew Interactive, LLC . All Rights Reserved. - */ - -package modinfo; - -import cpw.mods.fml.common.Loader; -import modinfo.mp.v1.Client; -import modinfo.mp.v1.Message; -import modinfo.mp.v1.Payload; -import net.minecraft.client.Minecraft; -import net.minecraft.client.resources.Language; -import net.minecraft.client.resources.Locale; -import net.minecraft.server.integrated.IntegratedServer; -import org.apache.logging.log4j.Level; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.lwjgl.opengl.Display; -import org.lwjgl.opengl.DisplayMode; - -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.*; - -/** - * @author techbrew 2/18/14. - */ -public class ModInfo -{ - - public static final String VERSION = "0.2"; - public static final Logger LOGGER = LogManager.getLogger("modinfo"); - - private final Minecraft minecraft = Minecraft.getMinecraft(); - private final String trackingId; - private final String modId; - private final String modName; - private final String modVersion; - private Locale reportingLocale; - private Config config; - private Client client; - - public ModInfo(String trackingId, String reportingLanguageCode, String modId, String modName, String modVersion, boolean singleUse) - { - this.trackingId = trackingId; - this.modId = modId; - this.modName = modName; - this.modVersion = modVersion; - - try - { - this.reportingLocale = getLocale(reportingLanguageCode); - this.config = Config.getInstance(this.modId); - this.client = createClient(); - if (singleUse) - { - singleUse(); - } - else if (this.config.isEnabled()) - { - if (Config.generateStatusString(modId, false).equals(config.getStatus())) - { - optIn(); - } - else - { - config.confirmStatus(); - } - } - else - { - optOut(); - } - } - catch (Throwable t) - { - LOGGER.log(Level.ERROR, "Unable to configure ModInfo", t); - } - } - - /** - * Adapted from UUID.nameUUIDFromBytes(); - * - * @param parts - * @return - */ - static UUID createUUID(String... parts) - { - MessageDigest md; - try - { - md = MessageDigest.getInstance("MD5"); - } - catch (NoSuchAlgorithmException nsae) - { - throw new InternalError("MD5 not supported"); - } - - for (String part : parts) - { - md.update(part.getBytes()); - } - - byte[] md5Bytes = md.digest(); - md5Bytes[6] &= 0x0f; /* clear version */ - md5Bytes[6] |= 0x30; /* set to version 3 */ - md5Bytes[8] &= 0x3f; /* clear variant */ - md5Bytes[8] |= 0x80; /* set to IETF variant */ - - long msb = 0; - long lsb = 0; - for (int i = 0; i < 8; i++) - { - msb = (msb << 8) | (md5Bytes[i] & 0xff); - } - for (int i = 8; i < 16; i++) - { - lsb = (lsb << 8) | (md5Bytes[i] & 0xff); - } - - return new UUID(msb, lsb); - } - - public final boolean isEnabled() - { - return client != null; - } - - public void reportAppView() - { - try - { - if (isEnabled()) - { - Payload payload = new Payload(Payload.Type.AppView); - payload.add(appViewParams()); - payload.add(minecraftParams()); - client.send(payload); - } - } - catch (Throwable t) - { - LOGGER.log(Level.ERROR, t.getMessage(), t); - } - } - - // TODO: Move to subtype of Message where this work can be done in another thread - public void reportException(Throwable e) - { - try - { - if (isEnabled()) - { - final String category = "Exception: " + e.toString(); - final String lineDelim = " / "; - final int actionMaxBytes = Payload.Parameter.EventAction.getMaxBytes(); - final int labelMaxBytes = Payload.Parameter.EventLabel.getMaxBytes(); - final int maxBytes = actionMaxBytes + labelMaxBytes; - - // Get encoded lengths of the stack trace lines - StackTraceElement[] stackTrace = e.getStackTrace(); - ArrayList byteLengths = new ArrayList(stackTrace.length); - int total = 0; - for (int i = 0; i < stackTrace.length; i++) - { - int byteLength = Payload.encode(stackTrace[i].toString() + lineDelim).getBytes().length; - if (total + byteLength > maxBytes) - { - break; - } - total += byteLength; - byteLengths.add(i, byteLength); - } - - int index = 0; - - // Put as many stack trace lines as possible into EventAction - StringBuilder action = new StringBuilder(actionMaxBytes / 11); - { - int actionTotal = 0; - for (; index < byteLengths.size(); index++) - { - int byteLength = byteLengths.get(index); - if (actionTotal + byteLength > actionMaxBytes) - { - break; - } - - actionTotal += byteLength; - action.append(stackTrace[index].toString() + lineDelim); - } - } - - // Put as many stack trace lines as possible into EventLabel - StringBuilder label = new StringBuilder(labelMaxBytes / 11); - { - int labelTotal = 0; - for (; index < byteLengths.size(); index++) - { - int byteLength = byteLengths.get(index); - if (labelTotal + byteLength > labelMaxBytes) - { - break; - } - - labelTotal += byteLength; - label.append(stackTrace[index].toString() + lineDelim); - } - } - - // Report as an event - reportEvent(category, action.toString(), label.toString()); - } - } - catch (Throwable t) - { - LOGGER.log(Level.ERROR, t.getMessage(), t); - } - } - - public void reportEvent(String category, String action, String label) - { - try - { - if (isEnabled()) - { - Payload payload = new Payload(Payload.Type.Event); - payload.add(appViewParams()); - payload.put(Payload.Parameter.EventCategory, category); - payload.put(Payload.Parameter.EventAction, action); - payload.put(Payload.Parameter.EventLabel, label); - client.send(payload); - } - } - catch (Throwable t) - { - LOGGER.log(Level.ERROR, t.getMessage(), t); - } - } - - public void keepAlive() - { - try - { - if (isEnabled()) - { - Payload payload = new Payload(Payload.Type.Event); - payload.put(Payload.Parameter.EventCategory, "ModInfo"); - payload.put(Payload.Parameter.EventAction, "KeepAlive"); - payload.put(Payload.Parameter.NonInteractionHit, "1"); - client.send(payload); - } - } - catch (Throwable t) - { - LOGGER.log(Level.ERROR, t.getMessage(), t); - } - } - - private Locale getLocale(String languageCode) - { - String english = "en_US"; - List langs = Arrays.asList(english); - if (!english.equals(languageCode)) - { - langs.add(languageCode); - } - - Locale locale = new Locale(); - locale.loadLocaleDataFiles(minecraft.getResourceManager(), langs); - return locale; - } - - private String I18n(String translationKey, Object... parms) - { - return reportingLocale.formatMessage(translationKey, parms); - } - - private Client createClient() - { - String salt = config.getSalt(); - String username = minecraft.getSession().getUsername(); - UUID clientId = createUUID(salt, username, modId); - return new Client(trackingId, clientId, config, Minecraft.getMinecraft().getLanguageManager().getCurrentLanguage().getLanguageCode()); - } - - private Map minecraftParams() - { - Map map = new HashMap(); - Language language = minecraft.getLanguageManager().getCurrentLanguage(); - map.put(Payload.Parameter.UserLanguage, language.getLanguageCode()); - - DisplayMode displayMode = Display.getDesktopDisplayMode(); - map.put(Payload.Parameter.ScreenResolution, displayMode.getWidth() + "x" + displayMode.getHeight()); - - StringBuilder desc = new StringBuilder(Loader.MC_VERSION); - if (minecraft.theWorld != null) - { - IntegratedServer server = minecraft.getIntegratedServer(); - boolean multiplayer = server == null || server.getPublic(); - desc.append(", ").append(multiplayer ? this.I18n("menu.multiplayer") : this.I18n("menu.singleplayer")); - } - - map.put(Payload.Parameter.ContentDescription, desc.toString()); - return map; - } - - private Map appViewParams() - { - Map map = new HashMap(); - map.put(Payload.Parameter.ApplicationName, modName); - map.put(Payload.Parameter.ApplicationVersion, modVersion); - return map; - } - - private void optIn() - { - // Send opt-in message and confirm. - Payload payload = new Payload(Payload.Type.Event); - payload.put(Payload.Parameter.EventCategory, "ModInfo"); - payload.put(Payload.Parameter.EventAction, "Opt In"); - - createClient().send(payload, new Message.Callback() - { - public void onResult(Object result) - { - if (Boolean.TRUE.equals(result)) - { - if (config.isEnabled()) - { - config.confirmStatus(); - LOGGER.info("ModInfo for " + config.getModId() + " has been re-enabled. Thank you!"); - } - } - } - }); - } - - public void singleUse() - { - if (Config.isConfirmedDisabled(config)) - { - return; - } - else - { - reportAppView(); - } - config.disable(); - } - - private void optOut() - { - if (Config.isConfirmedDisabled(config)) - { - // Disabled and confirmed, do nothing - LOGGER.info("ModInfo for " + this.modId + " is disabled"); - } - else if (!config.isEnabled()) - { - // Disabled. Send opt-out message and confirm. - Payload payload = new Payload(Payload.Type.Event); - payload.put(Payload.Parameter.EventCategory, "ModInfo"); - payload.put(Payload.Parameter.EventAction, "Opt Out"); - - createClient().send(payload, new Message.Callback() - { - public void onResult(Object result) - { - if (Boolean.TRUE.equals(result)) - { - if (!config.isEnabled()) - { - config.confirmStatus(); - LOGGER.info("ModInfo for " + config.getModId() + " has been disabled"); - } - } - } - }); - } - } -} diff --git a/src/main/java/modinfo/mp/v1/Client.java b/src/main/java/modinfo/mp/v1/Client.java deleted file mode 100644 index 5387975..0000000 --- a/src/main/java/modinfo/mp/v1/Client.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * JourneyMap Mod for Minecraft - * Copyright (c) 2011-2017 Techbrew Interactive, LLC . All Rights Reserved. - */ - -package modinfo.mp.v1; - -import modinfo.Config; -import modinfo.ModInfo; -import org.apache.logging.log4j.Level; - -import java.util.UUID; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.FutureTask; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * @author techbrew 2/17/14. - */ -public class Client -{ - - public static final String ENDPOINT = "http://www.google-analytics.com/collect"; - - private final String VERBOSE_PATTERN = "ModInfo (%s): %s"; - - private final String trackingId; - private final UUID clientId; - private final Config config; - private final String userAgent; - - private final ExecutorService service; - - private int retries = 5; - private int connectTimeout = 5000; - private int readTimeout = 2000; - - private AtomicInteger messageCount = new AtomicInteger(0); - - public Client(String trackingId, UUID clientId, Config config, String defaultUserLanguage) - { - this.trackingId = trackingId; - this.clientId = clientId; - this.config = config; - this.userAgent = createUserAgent(defaultUserLanguage); - this.service = Executors.newFixedThreadPool(2); - - if (config.isVerbose()) - { - showVerboseMessage("User-Agent: " + this.userAgent); - } - } - - public Future send(Payload payload) - { - return send(payload, null); - } - - public Future send(Payload payload, final Message.Callback callback) - { - if (config.isEnabled()) - { - // Ensure required parameters - payload.put(Payload.Parameter.Version, Payload.VERSION); - payload.put(Payload.Parameter.TrackingId, trackingId); - payload.put(Payload.Parameter.ClientId, clientId.toString()); - payload.put(Payload.Parameter.CustomMetric1, Integer.toString(messageCount.incrementAndGet())); - - // Create message and schedule with executor - final Message message = new Message(ENDPOINT, payload, userAgent, retries, connectTimeout, readTimeout); - final FutureTask future = new FutureTask(getRunnableWrapper(message, payload, callback), null); - service.submit(future); - - return future; - } - return null; - } - - private Runnable getRunnableWrapper(final Message message, final Payload payload, final Message.Callback callback) - { - return new Runnable() - { - @Override - public void run() - { - - Object result = null; - - try - { - result = message.call(); - } - catch (Throwable t) - { - ModInfo.LOGGER.log(Level.ERROR, "ModInfo couldn't send message", t); - } - - try - { - if (config.isVerbose() && Boolean.TRUE.equals(result)) - { - showVerboseMessage(payload.toVerboseString()); - } - } - catch (Throwable t) - { - ModInfo.LOGGER.log(Level.ERROR, "ModInfo couldn't do verbose output", t); - } - - try - { - if (callback != null) - { - callback.onResult(result); - } - } - catch (Throwable t) - { - ModInfo.LOGGER.log(Level.ERROR, "ModInfo couldn't use callback", t); - } - } - }; - } - - private String createUserAgent(String defaultUserLanguage) - { - String agent = null; - - try - { - // Get system properties - String os = System.getProperty("os.name"); - if (os == null) - { - os = ""; - } - - String version = System.getProperty("os.version"); - if (version == null) - { - version = ""; - } - - String arch = System.getProperty("os.arch"); - if (arch == null) - { - arch = ""; - } - if (arch.equals("amd64")) - { - arch = "WOW64"; - } - - String lang = String.format("%s_%s", System.getProperty("user.language"), System.getProperty("user.country")); - if (lang.contains("null")) - { - lang = defaultUserLanguage; - } - - // Build user agent string - if (os.startsWith("Mac")) // Mac OS X, x86_64, ? - { - version = version.replace(".", "_"); - agent = String.format("Mozilla/5.0 (Macintosh; U; Intel Mac OS X %s; %s)", version, lang); - } - else if (os.startsWith("Win")) // Windows 7, amd64, 6.1 - { - agent = String.format("Mozilla/5.0 (Windows; U; Windows NT %s; %s; %s)", version, arch, lang); - } - else if (os.startsWith("Linux")) // Linux, os.version = kernel version, os.arch = amd64 - { - agent = String.format("Mozilla/5.0 (Linux; U; Linux %s; %s; %s)", version, arch, lang); - } - else - { - agent = String.format("Mozilla/5.0 (%s; U; %s %s; %s, %s)", os, os, version, arch, lang); - } - } - catch (Throwable t) - { - ModInfo.LOGGER.log(Level.ERROR, "ModInfo couldn't create useragent string", t); - agent = "Mozilla/5.0 (Unknown)"; - } - - return agent; - } - - private void showVerboseMessage(String message) - { - System.out.println(String.format(VERBOSE_PATTERN, config.getModId(), message)); - } - - @Override - protected void finalize() throws Throwable - { - super.finalize(); - if (this.service != null) - { - this.service.shutdown(); - } - } -} diff --git a/src/main/java/modinfo/mp/v1/Message.java b/src/main/java/modinfo/mp/v1/Message.java deleted file mode 100644 index af621b9..0000000 --- a/src/main/java/modinfo/mp/v1/Message.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * JourneyMap Mod for Minecraft - * Copyright (c) 2011-2017 Techbrew Interactive, LLC . All Rights Reserved. - */ - -package modinfo.mp.v1; - -import modinfo.ModInfo; -import org.apache.logging.log4j.Level; - -import java.io.DataOutputStream; -import java.io.IOException; -import java.net.HttpURLConnection; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.concurrent.Callable; - -/** - * @author techbrew 2/18/14. - */ -public class Message implements Callable -{ - private final String endpoint; - private final Payload payload; - private final String userAgent; - private final int retries; - private final int connectionTimeout; - private final int readTimeout; - - Message(String endpoint, Payload payload, String userAgent, int retries, int connectionTimeout, int readTimeout) - { - this.endpoint = endpoint; - this.payload = payload; - this.userAgent = userAgent; - this.retries = retries; - this.connectionTimeout = connectionTimeout; - this.readTimeout = readTimeout; - } - - - @Override - public Object call() - { - String defaultAgent = System.setProperty("http.agent", ""); - int remainingRetries = Math.max(1, retries); - - Exception exception = null; - Integer responseCode = null; - while (responseCode == null && remainingRetries > 0) - { - try - { - String payloadString = payload.toUrlEncodedString(); - - URL url = new URL(endpoint); - HttpURLConnection con = (HttpURLConnection) url.openConnection(); - con.setRequestMethod("POST"); - con.setRequestProperty("User-Agent", userAgent); - con.setConnectTimeout(connectionTimeout); - con.setReadTimeout(readTimeout); - con.setUseCaches(false); - - con.setDoOutput(true); - DataOutputStream wr = new DataOutputStream(con.getOutputStream()); - wr.writeBytes(payloadString); - wr.flush(); - wr.close(); - - responseCode = con.getResponseCode(); - } - catch (MalformedURLException ex) - { - exception = ex; - ModInfo.LOGGER.log(Level.ERROR, "ModInfo got a bad URL: " + endpoint); - break; - } - catch (IOException ex) - { - exception = ex; - ModInfo.LOGGER.log(Level.ERROR, "ModInfo can't send message", ex); - } - finally - { - remainingRetries--; - } - } - - if (defaultAgent != null && defaultAgent.length() > 0) - { - System.setProperty("http.agent", defaultAgent); - } - - if (responseCode != null) - { - return Boolean.TRUE; - } - else if (exception == null) - { - exception = new Exception("ModInfo got a null response from endpoint"); - } - return exception; - } - - public interface Callback - { - public void onResult(Object result); - } -} diff --git a/src/main/java/modinfo/mp/v1/Payload.java b/src/main/java/modinfo/mp/v1/Payload.java deleted file mode 100644 index 4c26023..0000000 --- a/src/main/java/modinfo/mp/v1/Payload.java +++ /dev/null @@ -1,213 +0,0 @@ -/* - * JourneyMap Mod for Minecraft - * Copyright (c) 2011-2017 Techbrew Interactive, LLC . All Rights Reserved. - */ - -package modinfo.mp.v1; - -import modinfo.ModInfo; -import org.apache.logging.log4j.Level; - -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.util.Comparator; -import java.util.Iterator; -import java.util.Map; -import java.util.TreeMap; - -/** - * @author techbrew 2/19/14. - */ -public class Payload -{ - public static final String VERSION = "1"; - - public static Comparator ParameterOrdinalSort = new Comparator() - { - @Override - public int compare(Parameter o1, Parameter o2) - { - //return Integer.compare(o1.ordinal(), o2.ordinal()); - return o1.compareTo(o2); - } - }; - private TreeMap params = new TreeMap(ParameterOrdinalSort); - - public Payload(Type type) - { - params.put(Parameter.HitType, type.getHitName()); - } - - /** - * URL-encodes a String without throwing an exception, which - * should never happen anyway. If there is an exception, the value is returned - * as-is. - * - * @param value - * @return - */ - public static String encode(String value) - { - try - { - return URLEncoder.encode(value, "UTF-8"); - } - catch (UnsupportedEncodingException e) - { - ModInfo.LOGGER.log(Level.ERROR, "Can't encode: " + value); - } - return value; - } - - /** - * Utility method to truncate a string to a length which will not exceed - * maxBytes after it has been URL encoded. The result can optionally be - * returned as encoded since the work will have already been done. - * - * @param value string to truncate - * @param maxBytes encoded byte length limit. If null, no length change is made. - * @param encodeResult true to return result as URL encoded - * @return the (possibly) truncated string, plain or encoded - */ - static String urlClamp(String value, Integer maxBytes, boolean encodeResult) - { - if (maxBytes == null) - { - return encodeResult ? encode(value) : value; - } - else - { - StringBuilder sb = new StringBuilder(value); - String encoded = encode(sb.toString()); - int byteLength = encoded.getBytes().length; - int offset = 0; - while (byteLength > maxBytes) - { - offset = (int) Math.max(1, Math.floor((byteLength - maxBytes) / 11)); - sb.setLength(sb.length() - offset); - encoded = encode(sb.toString()); - byteLength = encoded.getBytes().length; - } - - return encodeResult ? encoded : sb.toString(); - } - } - - public void put(Parameter param, String value) - { - params.put(param, value); - } - - public Payload add(Map map) - { - params.putAll(map); - return this; - } - - String toUrlEncodedString() - { - StringBuilder sb = new StringBuilder(); - Iterator> iter = params.entrySet().iterator(); - while (iter.hasNext()) - { - Map.Entry entry = iter.next(); - Parameter param = entry.getKey(); - sb.append(param.pname).append("="); - sb.append(urlClamp(entry.getValue(), param.maxBytes, true)); - if (iter.hasNext()) - { - sb.append("&"); - } - } - return sb.toString(); - } - - String toVerboseString() - { - StringBuilder sb = new StringBuilder(); - Iterator> iter = params.entrySet().iterator(); - while (iter.hasNext()) - { - Map.Entry entry = iter.next(); - Parameter param = entry.getKey(); - sb.append(param.pname).append("="); - - String value = entry.getValue(); - if (param == Parameter.TrackingId) - { - value = "UA-XXXXXXXX-1"; - } - sb.append(urlClamp(value, param.maxBytes, false)); - if (iter.hasNext()) - { - sb.append("&"); - } - } - return sb.toString(); - } - - public enum Parameter - { - Version("v"), - TrackingId("tid"), - ClientId("cid"), - HitType("t"), - ApplicationName("an", 100), - ApplicationVersion("av", 100), - NonInteractionHit("ni"), - ContentDescription("cd", 2048), - ScreenResolution("sr", 20), - UserLanguage("ul", 20), - ExceptionDescription("exd", 150), - ExceptionFatal("exf"), - EventCategory("ec", 150), - EventAction("ea", 500), - EventLabel("el", 500), - EventValue("ev"), - CustomMetric1("cm1"); // Reserved for message count - - private String pname; - private Integer maxBytes; - - private Parameter(String pname) - { - this.pname = pname; - this.maxBytes = null; - } - - private Parameter(String pname, int maxBytes) - { - this.pname = pname; - this.maxBytes = maxBytes; - } - - public String getParameterName() - { - return this.pname; - } - - public int getMaxBytes() - { - return this.maxBytes; - } - } - - public enum Type - { - AppView("appview"), - Event("event"), - Exception("exception"); - - private String hname; - - private Type(String hname) - { - this.hname = hname; - } - - public String getHitName() - { - return this.hname; - } - } -}