aboutsummaryrefslogtreecommitdiff
path: root/spark-common/src/main/java/me/lucko/spark/common/util
diff options
context:
space:
mode:
authorLuck <git@lucko.me>2019-04-16 21:37:59 +0100
committerLuck <git@lucko.me>2019-04-16 21:37:59 +0100
commitecd4cec8545460a4fc4ca65b911c2503a00cd8e7 (patch)
tree62067383a1044abc3a09724e89c6e7c619e87ec0 /spark-common/src/main/java/me/lucko/spark/common/util
parent8a61b404848ed8e3c27f06eb73239d37d4273240 (diff)
downloadspark-ecd4cec8545460a4fc4ca65b911c2503a00cd8e7.tar.gz
spark-ecd4cec8545460a4fc4ca65b911c2503a00cd8e7.tar.bz2
spark-ecd4cec8545460a4fc4ca65b911c2503a00cd8e7.zip
Lots of refactoring, add tps command
Diffstat (limited to 'spark-common/src/main/java/me/lucko/spark/common/util')
-rw-r--r--spark-common/src/main/java/me/lucko/spark/common/util/AbstractHttpClient.java45
-rw-r--r--spark-common/src/main/java/me/lucko/spark/common/util/BytebinClient.java149
-rw-r--r--spark-common/src/main/java/me/lucko/spark/common/util/ThreadFinder.java60
-rw-r--r--spark-common/src/main/java/me/lucko/spark/common/util/TypeDescriptors.java81
4 files changed, 335 insertions, 0 deletions
diff --git a/spark-common/src/main/java/me/lucko/spark/common/util/AbstractHttpClient.java b/spark-common/src/main/java/me/lucko/spark/common/util/AbstractHttpClient.java
new file mode 100644
index 0000000..1ff169d
--- /dev/null
+++ b/spark-common/src/main/java/me/lucko/spark/common/util/AbstractHttpClient.java
@@ -0,0 +1,45 @@
+/*
+ * This file is part of spark.
+ *
+ * Copyright (c) lucko (Luck) <luck@lucko.me>
+ * Copyright (c) contributors
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+package me.lucko.spark.common.util;
+
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+
+import java.io.IOException;
+
+public class AbstractHttpClient {
+
+ /** The http client */
+ protected final OkHttpClient okHttp;
+
+ public AbstractHttpClient(OkHttpClient okHttp) {
+ this.okHttp = okHttp;
+ }
+
+ protected Response makeHttpRequest(Request request) throws IOException {
+ Response response = this.okHttp.newCall(request).execute();
+ if (!response.isSuccessful()) {
+ throw new RuntimeException("Request was unsuccessful: " + response.code() + " - " + response.message());
+ }
+ return response;
+ }
+}
diff --git a/spark-common/src/main/java/me/lucko/spark/common/util/BytebinClient.java b/spark-common/src/main/java/me/lucko/spark/common/util/BytebinClient.java
new file mode 100644
index 0000000..ff8f4e3
--- /dev/null
+++ b/spark-common/src/main/java/me/lucko/spark/common/util/BytebinClient.java
@@ -0,0 +1,149 @@
+/*
+ * This file is part of bytebin, licensed under the MIT License.
+ *
+ * Copyright (c) lucko (Luck) <luck@lucko.me>
+ * Copyright (c) contributors
+ *
+ * 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 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.
+ */
+
+package me.lucko.spark.common.util;
+
+import okhttp3.MediaType;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.RequestBody;
+import okhttp3.Response;
+
+import java.io.IOException;
+
+/**
+ * Utility for posting content to bytebin.
+ */
+public class BytebinClient extends AbstractHttpClient {
+
+ /** The bytebin URL */
+ private final String url;
+ /** The client user agent */
+ private final String userAgent;
+
+ /**
+ * Creates a new bytebin instance
+ *
+ * @param url the bytebin url
+ * @param userAgent the client user agent string
+ */
+ public BytebinClient(OkHttpClient okHttpClient, String url, String userAgent) {
+ super(okHttpClient);
+ if (url.endsWith("/")) {
+ this.url = url;
+ } else {
+ this.url = url + "/";
+ }
+ this.userAgent = userAgent;
+ }
+
+ /**
+ * POSTs GZIP compressed content to bytebin.
+ *
+ * @param buf the compressed content
+ * @param contentType the type of the content
+ * @param allowModification if the paste should be modifiable
+ * @return the key of the resultant content
+ * @throws IOException if an error occurs
+ */
+ public Content postContent(byte[] buf, MediaType contentType, boolean allowModification) throws IOException {
+ RequestBody body = RequestBody.create(contentType, buf);
+
+ Request.Builder requestBuilder = new Request.Builder()
+ .url(this.url + "post")
+ .header("User-Agent", this.userAgent)
+ .header("Content-Encoding", "gzip");
+
+ if (allowModification) {
+ requestBuilder.header("Allow-Modification", "true");
+ }
+
+ Request request = requestBuilder.post(body).build();
+ try (Response response = makeHttpRequest(request)) {
+ String key = response.header("Location");
+ if (key == null) {
+ throw new IllegalStateException("Key not returned");
+ }
+
+ if (allowModification) {
+ String modificationKey = response.header("Modification-Key");
+ if (modificationKey == null) {
+ throw new IllegalStateException("Modification key not returned");
+ }
+ return new Content(key, modificationKey);
+ } else {
+ return new Content(key);
+ }
+ }
+ }
+
+ /**
+ * PUTs modified GZIP compressed content to bytebin in place of existing content.
+ *
+ * @param existingContent the existing content
+ * @param buf the compressed content to put
+ * @param contentType the type of the content
+ * @throws IOException if an error occurs
+ */
+ public void modifyContent(Content existingContent, byte[] buf, MediaType contentType) throws IOException {
+ if (!existingContent.modifiable) {
+ throw new IllegalArgumentException("Existing content is not modifiable");
+ }
+
+ RequestBody body = RequestBody.create(contentType, buf);
+
+ Request.Builder requestBuilder = new Request.Builder()
+ .url(this.url + existingContent.key())
+ .header("User-Agent", this.userAgent)
+ .header("Content-Encoding", "gzip")
+ .header("Modification-Key", existingContent.modificationKey);
+
+ Request request = requestBuilder.put(body).build();
+ makeHttpRequest(request).close();
+ }
+
+ public static final class Content {
+ private final String key;
+ private final boolean modifiable;
+ private final String modificationKey;
+
+ Content(String key) {
+ this.key = key;
+ this.modifiable = false;
+ this.modificationKey = null;
+ }
+
+ Content(String key, String modificationKey) {
+ this.key = key;
+ this.modifiable = true;
+ this.modificationKey = modificationKey;
+ }
+
+ public String key() {
+ return this.key;
+ }
+ }
+
+}
diff --git a/spark-common/src/main/java/me/lucko/spark/common/util/ThreadFinder.java b/spark-common/src/main/java/me/lucko/spark/common/util/ThreadFinder.java
new file mode 100644
index 0000000..cc0722a
--- /dev/null
+++ b/spark-common/src/main/java/me/lucko/spark/common/util/ThreadFinder.java
@@ -0,0 +1,60 @@
+/*
+ * This file is part of spark.
+ *
+ * Copyright (c) lucko (Luck) <luck@lucko.me>
+ * Copyright (c) contributors
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+package me.lucko.spark.common.util;
+
+import java.util.Arrays;
+import java.util.Objects;
+import java.util.stream.Stream;
+
+/**
+ * Utility to find active threads.
+ */
+public final class ThreadFinder {
+
+ private static final ThreadGroup ROOT_THREAD_GROUP;
+ static {
+ ThreadGroup rootGroup = Thread.currentThread().getThreadGroup();
+ ThreadGroup parentGroup;
+ while ((parentGroup = rootGroup.getParent()) != null) {
+ rootGroup = parentGroup;
+ }
+ ROOT_THREAD_GROUP = rootGroup;
+ }
+
+ // cache the approx active count at the time of construction.
+ // the usages of this class are likely to be somewhat short-lived, so it's good
+ // enough to just cache a value on init.
+ private final int approxActiveCount = ROOT_THREAD_GROUP.activeCount();
+
+ /**
+ * Gets a stream of all known active threads.
+ *
+ * @return a stream of threads
+ */
+ public Stream<Thread> getThreads() {
+ Thread[] threads = new Thread[this.approxActiveCount + 20]; // +20 to allow a bit of growth for newly created threads
+ while (ROOT_THREAD_GROUP.enumerate(threads, true) == threads.length) {
+ threads = new Thread[threads.length * 2];
+ }
+ return Arrays.stream(threads).filter(Objects::nonNull);
+ }
+
+}
diff --git a/spark-common/src/main/java/me/lucko/spark/common/util/TypeDescriptors.java b/spark-common/src/main/java/me/lucko/spark/common/util/TypeDescriptors.java
new file mode 100644
index 0000000..a232e77
--- /dev/null
+++ b/spark-common/src/main/java/me/lucko/spark/common/util/TypeDescriptors.java
@@ -0,0 +1,81 @@
+/*
+ * This file is part of spark.
+ *
+ * Copyright (c) lucko (Luck) <luck@lucko.me>
+ * Copyright (c) contributors
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+package me.lucko.spark.common.util;
+
+/**
+ * Utilities for working with Java type descriptors.
+ */
+public final class TypeDescriptors {
+
+ /**
+ * Returns the Java type corresponding to the given type descriptor.
+ *
+ * @param typeDescriptor a type descriptor.
+ * @return the Java type corresponding to the given type descriptor.
+ */
+ public static String getJavaType(String typeDescriptor) {
+ return getJavaType(typeDescriptor.toCharArray(), 0);
+ }
+
+ private static String getJavaType(char[] buf, int offset) {
+ int len;
+ switch (buf[offset]) {
+ case 'V':
+ return "void";
+ case 'Z':
+ return "boolean";
+ case 'C':
+ return "char";
+ case 'B':
+ return "byte";
+ case 'S':
+ return "short";
+ case 'I':
+ return "int";
+ case 'F':
+ return "float";
+ case 'J':
+ return "long";
+ case 'D':
+ return "double";
+ case '[': // array
+ len = 1;
+ while (buf[offset + len] == '[') {
+ len++;
+ }
+
+ StringBuilder sb = new StringBuilder(getJavaType(buf, offset + len));
+ for (int i = len; i > 0; --i) {
+ sb.append("[]");
+ }
+ return sb.toString();
+ case 'L': // object
+ len = 1;
+ while (buf[offset + len] != ';') {
+ len++;
+ }
+ return new String(buf, offset + 1, len - 1);
+ default:
+ return new String(buf, offset, buf.length - offset);
+ }
+ }
+
+}