commit 1b16a1d67ebd0f049bb5853d9ed8fde19f13e26f Author: Mark Vainomaa Date: Sat Aug 27 16:18:28 2016 +0300 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..40d56b9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,21 @@ +# ---> Java +*.class + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.ear + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +# IntelliJ IDEA +*.iml +.idea/ + +# Maven +target/ +dependency-reduced-pom.xml diff --git a/Bannerparser/pom.xml b/Bannerparser/pom.xml new file mode 100644 index 0000000..e2fc0cd --- /dev/null +++ b/Bannerparser/pom.xml @@ -0,0 +1,40 @@ + + + + utils + eu.mikroskeem + 1.0-SNAPSHOT + + 4.0.0 + + bannerparser + + + + spigot-repo + https://hub.spigotmc.org/nexus/content/repositories/snapshots/ + + + + + org.bukkit + bukkit + 1.10.2-R0.1-SNAPSHOT + provided + + + org.jetbrains + annotations-java5 + RELEASE + + + junit + junit + 4.12 + test + + + + \ No newline at end of file diff --git a/Bannerparser/src/main/java/eu/mikroskeem/utils/bannerparser/IntegerFromString.java b/Bannerparser/src/main/java/eu/mikroskeem/utils/bannerparser/IntegerFromString.java new file mode 100644 index 0000000..79c740e --- /dev/null +++ b/Bannerparser/src/main/java/eu/mikroskeem/utils/bannerparser/IntegerFromString.java @@ -0,0 +1,33 @@ +package eu.mikroskeem.utils.bannerparser; + +public class IntegerFromString { + public static String valueOf(int value){ + for (IntegerFromStringEnum anEnum : IntegerFromStringEnum.values()) { + if(value == anEnum.getValue()){ + return anEnum.toString(); + } + } + return null; + } + + private enum IntegerFromStringEnum { + ONE(1), + TWO(2), + THREE(3), + FOUR(4), + FIVE(5), + SIX(6), + SEVEN(7), + EIGHT(8), + NINE(9), + ZERO(0); + + private int value; + IntegerFromStringEnum(int value) { + this.value = value; + } + public int getValue(){ + return value; + } + } +} \ No newline at end of file diff --git a/Bannerparser/src/main/java/eu/mikroskeem/utils/bannerparser/ParseQuery.java b/Bannerparser/src/main/java/eu/mikroskeem/utils/bannerparser/ParseQuery.java new file mode 100644 index 0000000..fd8626c --- /dev/null +++ b/Bannerparser/src/main/java/eu/mikroskeem/utils/bannerparser/ParseQuery.java @@ -0,0 +1,21 @@ +package eu.mikroskeem.utils.bannerparser; + +import java.io.UnsupportedEncodingException; +import java.net.URL; +import java.net.URLDecoder; +import java.util.LinkedHashMap; +import java.util.Map; + + +public class ParseQuery { + public static Map splitQuery(URL url) throws UnsupportedEncodingException { + Map query_pairs = new LinkedHashMap<>(); + String query = url.getQuery(); + String[] pairs = query.split("&"); + for (String pair : pairs) { + int idx = pair.indexOf("="); + query_pairs.put(URLDecoder.decode(pair.substring(0, idx), "UTF-8"), URLDecoder.decode(pair.substring(idx + 1), "UTF-8")); + } + return query_pairs; + } +} diff --git a/Bannerparser/src/main/java/eu/mikroskeem/utils/bannerparser/parsers/Parser.java b/Bannerparser/src/main/java/eu/mikroskeem/utils/bannerparser/parsers/Parser.java new file mode 100644 index 0000000..2eb046a --- /dev/null +++ b/Bannerparser/src/main/java/eu/mikroskeem/utils/bannerparser/parsers/Parser.java @@ -0,0 +1,10 @@ +package eu.mikroskeem.utils.bannerparser.parsers; + +import org.bukkit.block.banner.Pattern; + +import java.net.URL; +import java.util.ArrayList; + +public interface Parser { + ArrayList fromUrl(URL url); +} diff --git a/Bannerparser/src/main/java/eu/mikroskeem/utils/bannerparser/parsers/Parsers.java b/Bannerparser/src/main/java/eu/mikroskeem/utils/bannerparser/parsers/Parsers.java new file mode 100644 index 0000000..245da69 --- /dev/null +++ b/Bannerparser/src/main/java/eu/mikroskeem/utils/bannerparser/parsers/Parsers.java @@ -0,0 +1,29 @@ +package eu.mikroskeem.utils.bannerparser.parsers; + +import eu.mikroskeem.utils.bannerparser.parsers.needcoolshoes.NeedCoolShoesParser; +import eu.mikroskeem.utils.bannerparser.parsers.planetminecraft.PlanetMinecraftParser; +import org.bukkit.block.banner.Pattern; + +import java.net.URL; +import java.util.ArrayList; + +public class Parsers { + public static Parser getParser(URL url){ + String host = url.getHost(); + if(host.contains("planetminecraft.com")){ + return new PlanetMinecraftParser(); + } else if (host.contains("needcoolshoes.com")){ + return new NeedCoolShoesParser(); + } + return null; + } + + public static ArrayList parse(URL url){ + Parser parser = getParser(url); + if(parser != null){ + return parser.fromUrl(url); + } else { + return null; + } + } +} diff --git a/Bannerparser/src/main/java/eu/mikroskeem/utils/bannerparser/parsers/needcoolshoes/ColorParser.java b/Bannerparser/src/main/java/eu/mikroskeem/utils/bannerparser/parsers/needcoolshoes/ColorParser.java new file mode 100644 index 0000000..ed0a93f --- /dev/null +++ b/Bannerparser/src/main/java/eu/mikroskeem/utils/bannerparser/parsers/needcoolshoes/ColorParser.java @@ -0,0 +1,38 @@ +package eu.mikroskeem.utils.bannerparser.parsers.needcoolshoes; + +import org.bukkit.DyeColor; +import static org.bukkit.DyeColor.*; + +class ColorParser { + static DyeColor valueOf(String a){ + return ColorEnum.valueOf(a).getColor(); + } + + @SuppressWarnings("unused") + private enum ColorEnum { + a(BLACK), + b(RED), + c(GREEN), + d(BROWN), + e(BLUE), + f(PURPLE), + g(CYAN), + h(SILVER), + i(GRAY), + j(PINK), + k(LIME), + l(YELLOW), + m(LIGHT_BLUE), + n(MAGENTA), + o(ORANGE), + p(WHITE); + + private DyeColor color; + ColorEnum(DyeColor color) { + this.color = color; + } + public DyeColor getColor() { + return color; + } + } +} \ No newline at end of file diff --git a/Bannerparser/src/main/java/eu/mikroskeem/utils/bannerparser/parsers/needcoolshoes/NeedCoolShoesParser.java b/Bannerparser/src/main/java/eu/mikroskeem/utils/bannerparser/parsers/needcoolshoes/NeedCoolShoesParser.java new file mode 100644 index 0000000..1b4f890 --- /dev/null +++ b/Bannerparser/src/main/java/eu/mikroskeem/utils/bannerparser/parsers/needcoolshoes/NeedCoolShoesParser.java @@ -0,0 +1,47 @@ +package eu.mikroskeem.utils.bannerparser.parsers.needcoolshoes; + +import eu.mikroskeem.utils.bannerparser.parsers.Parser; +import org.bukkit.DyeColor; +import org.bukkit.block.banner.Pattern; +import org.bukkit.block.banner.PatternType; + +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class NeedCoolShoesParser implements Parser { + /* + * See http://www.needcoolshoes.com/banner + */ + public ArrayList fromUrl(URL url){ + try { + String bannerData = url.getQuery().split("\\?=")[0].substring(1); + return parse(bannerData); + } catch (ArrayIndexOutOfBoundsException e){ + return null; + } + } + + private ArrayList parse(String whole){ + ArrayList patterns = new ArrayList<>(); + List propertyList = Arrays.asList(whole.split("(?<=\\G..)")); + + propertyList.forEach(property->{ + DyeColor color = parseColor(property.charAt(0)); + PatternType patternType = parsePattern(property.charAt(1)); + patterns.add(new Pattern(color, patternType)); + }); + + return patterns; + } + + private PatternType parsePattern(char part){ + String partStr = String.valueOf(part); + return PatternParser.valueOf(partStr); + } + private DyeColor parseColor(char part){ + String partStr = String.valueOf(part); + return ColorParser.valueOf(partStr); + } +} diff --git a/Bannerparser/src/main/java/eu/mikroskeem/utils/bannerparser/parsers/needcoolshoes/PatternParser.java b/Bannerparser/src/main/java/eu/mikroskeem/utils/bannerparser/parsers/needcoolshoes/PatternParser.java new file mode 100644 index 0000000..5a8f2c0 --- /dev/null +++ b/Bannerparser/src/main/java/eu/mikroskeem/utils/bannerparser/parsers/needcoolshoes/PatternParser.java @@ -0,0 +1,73 @@ +package eu.mikroskeem.utils.bannerparser.parsers.needcoolshoes; + +import org.bukkit.block.banner.PatternType; +import static org.bukkit.block.banner.PatternType.*; + +class PatternParser { + static PatternType valueOf(String a) { + return PatternEnum.valueOf(a).getPattern(); + } + + @SuppressWarnings("unused") + private enum PatternEnum { + a(BASE), + + e(BRICKS), + j(CROSS), + z(STRAIGHT_CROSS), + + p(GRADIENT), + K(GRADIENT_UP), + + q(HALF_HORIZONTAL_MIRROR), + L(HALF_VERTICAL), + H(HALF_VERTICAL_MIRROR), + M(HALF_HORIZONTAL), + + E(STRIPE_TOP), + f(STRIPE_BOTTOM), + s(STRIPE_LEFT), + y(STRIPE_RIGHT), + + r(DIAGONAL_LEFT), + J(DIAGONAL_RIGHT_MIRROR), + I(DIAGONAL_LEFT_MIRROR), + x(DIAGONAL_RIGHT), + + m(STRIPE_DOWNLEFT), + n(STRIPE_DOWNRIGHT), + + l(STRIPE_MIDDLE), + w(STRIPE_CENTER), + + C(SQUARE_TOP_LEFT), + b(SQUARE_BOTTOM_LEFT), + D(SQUARE_TOP_RIGHT), + d(SQUARE_BOTTOM_RIGHT), + + F(TRIANGLE_TOP), + g(TRIANGLE_BOTTOM), + + v(RHOMBUS_MIDDLE), + t(CIRCLE_MIDDLE), + h(TRIANGLES_BOTTOM), + G(TRIANGLES_TOP), + + B(STRIPE_SMALL), + + c(BORDER), + i(CURLY_BORDER), + o(FLOWER), + k(CREEPER), + A(SKULL), + u(MOJANG); + + private PatternType type; + PatternEnum(PatternType type) { + this.type = type; + } + public PatternType getPattern() { + return type; + } + } +} diff --git a/Bannerparser/src/main/java/eu/mikroskeem/utils/bannerparser/parsers/planetminecraft/ColorParser.java b/Bannerparser/src/main/java/eu/mikroskeem/utils/bannerparser/parsers/planetminecraft/ColorParser.java new file mode 100644 index 0000000..dbcb482 --- /dev/null +++ b/Bannerparser/src/main/java/eu/mikroskeem/utils/bannerparser/parsers/planetminecraft/ColorParser.java @@ -0,0 +1,46 @@ +package eu.mikroskeem.utils.bannerparser.parsers.planetminecraft; + +import eu.mikroskeem.utils.bannerparser.IntegerFromString; +import org.bukkit.DyeColor; +import static org.bukkit.DyeColor.*; + +class ColorParser { + static DyeColor valueOf(String a){ + try { + /* Test for integer value first */ + String name = IntegerFromString.valueOf(Integer.valueOf(a)); + return ColorEnum.valueOf(name).getColor(); + } catch (NumberFormatException e){ + /* Return by string identifier */ + return ColorEnum.valueOf(a).getColor(); + } + } + + @SuppressWarnings("unused") + private enum ColorEnum { + g(WHITE), + EIGHT(SILVER), + NINE(GRAY), + ONE(BLACK), + c(YELLOW), + f(ORANGE), + TWO(RED), + FOUR(BROWN), + b(LIME), + THREE(GREEN), + d(LIGHT_BLUE), + SEVEN(CYAN), + FIVE(BLUE), + a(PINK), + e(MAGENTA), + SIX(PURPLE); + + private DyeColor color; + ColorEnum(DyeColor color) { + this.color = color; + } + public DyeColor getColor() { + return color; + } + } +} \ No newline at end of file diff --git a/Bannerparser/src/main/java/eu/mikroskeem/utils/bannerparser/parsers/planetminecraft/PatternParser.java b/Bannerparser/src/main/java/eu/mikroskeem/utils/bannerparser/parsers/planetminecraft/PatternParser.java new file mode 100644 index 0000000..7714ea8 --- /dev/null +++ b/Bannerparser/src/main/java/eu/mikroskeem/utils/bannerparser/parsers/planetminecraft/PatternParser.java @@ -0,0 +1,76 @@ +package eu.mikroskeem.utils.bannerparser.parsers.planetminecraft; + +import eu.mikroskeem.utils.bannerparser.IntegerFromString; +import org.bukkit.block.banner.PatternType; +import static org.bukkit.block.banner.PatternType.*; + +class PatternParser { + static PatternType valueOf(String a) { + try { + /* Test for integer value first */ + String name = IntegerFromString.valueOf(Integer.valueOf(a)); + return PatternEnum.valueOf(name).getPattern(); + } catch (NumberFormatException e){ + /* Return by string identifier */ + return PatternEnum.valueOf(a).getPattern(); + } + } + + @SuppressWarnings("unused") + private enum PatternEnum { + o(STRIPE_BOTTOM), + v(STRIPE_TOP), + s(STRIPE_LEFT), + u(STRIPE_RIGHT), + t(STRIPE_MIDDLE), + p(STRIPE_CENTER), + r(STRIPE_DOWNRIGHT), + q(STRIPE_DOWNLEFT), + SEVEN(CROSS), + + i(STRIPE_SMALL), + n(STRAIGHT_CROSS), + + a(DIAGONAL_RIGHT_MIRROR), + NINE(DIAGONAL_LEFT), + A(DIAGONAL_LEFT_MIRROR), + B(DIAGONAL_RIGHT), + + e(HALF_VERTICAL), + E(HALF_VERTICAL_MIRROR), + + d(HALF_HORIZONTAL), + D(HALF_HORIZONTAL_MIRROR), + + j(SQUARE_BOTTOM_LEFT), + k(SQUARE_BOTTOM_RIGHT), + l(SQUARE_TOP_LEFT), + m(SQUARE_TOP_RIGHT), + + y(TRIANGLE_BOTTOM), + z(TRIANGLE_TOP), + + w(TRIANGLES_BOTTOM), + x(TRIANGLES_TOP), + + FIVE(CIRCLE_MIDDLE), + g(RHOMBUS_MIDDLE), + THREE(BORDER), + EIGHT(CURLY_BORDER), + FOUR(BRICKS), + SIX(CREEPER), + h(SKULL), + b(FLOWER), + f(MOJANG), + c(GRADIENT), + C(GRADIENT_UP); + + private PatternType type; + PatternEnum(PatternType type) { + this.type = type; + } + public PatternType getPattern() { + return type; + } + } +} diff --git a/Bannerparser/src/main/java/eu/mikroskeem/utils/bannerparser/parsers/planetminecraft/PlanetMinecraftParser.java b/Bannerparser/src/main/java/eu/mikroskeem/utils/bannerparser/parsers/planetminecraft/PlanetMinecraftParser.java new file mode 100644 index 0000000..c28f987 --- /dev/null +++ b/Bannerparser/src/main/java/eu/mikroskeem/utils/bannerparser/parsers/planetminecraft/PlanetMinecraftParser.java @@ -0,0 +1,51 @@ +package eu.mikroskeem.utils.bannerparser.parsers.planetminecraft; + +import eu.mikroskeem.utils.bannerparser.parsers.Parser; +import eu.mikroskeem.utils.bannerparser.ParseQuery; +import org.bukkit.DyeColor; +import org.bukkit.block.banner.Pattern; +import org.bukkit.block.banner.PatternType; + +import java.io.UnsupportedEncodingException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class PlanetMinecraftParser implements Parser { + /* + * See http://www.planetminecraft.com/banner/ + */ + public ArrayList fromUrl(URL url){ + try { + String bannerData = ParseQuery.splitQuery(url).getOrDefault("b", ""); + return parse(bannerData); + } catch (UnsupportedEncodingException e){ + return null; + } + } + + private ArrayList parse(String whole){ + ArrayList patterns = new ArrayList<>(); + /* Get base color */ + patterns.add(new Pattern(parseColor(whole.charAt(0)), PatternType.BASE)); + + /* Iterate over all others */ + List propertyList = Arrays.asList(whole.substring(1).split("(?<=\\G..)")); + propertyList.forEach(property->{ + DyeColor color = parseColor(property.charAt(0)); + PatternType patternType = parsePattern(property.charAt(1)); + patterns.add(new Pattern(color, patternType)); + }); + return patterns; + } + + private PatternType parsePattern(char part){ + String partStr = String.valueOf(part); + return PatternParser.valueOf(partStr); + } + private DyeColor parseColor(char part){ + String partStr = String.valueOf(part); + return ColorParser.valueOf(partStr); + } +} diff --git a/Bannerparser/src/test/java/eu/mikroskeem/utils/test/bannerparser/ParserTest.java b/Bannerparser/src/test/java/eu/mikroskeem/utils/test/bannerparser/ParserTest.java new file mode 100644 index 0000000..9f845c6 --- /dev/null +++ b/Bannerparser/src/test/java/eu/mikroskeem/utils/test/bannerparser/ParserTest.java @@ -0,0 +1,80 @@ +package eu.mikroskeem.utils.test.bannerparser; + +import eu.mikroskeem.utils.bannerparser.parsers.Parsers; +import eu.mikroskeem.utils.bannerparser.parsers.needcoolshoes.NeedCoolShoesParser; +import eu.mikroskeem.utils.bannerparser.parsers.planetminecraft.PlanetMinecraftParser; +import org.bukkit.DyeColor; +import org.bukkit.block.banner.Pattern; +import org.bukkit.block.banner.PatternType; +import org.junit.Assert; +import org.junit.Test; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; + +public class ParserTest { + @Test + public void testParserSelector() throws MalformedURLException { + URL url = new URL("http://www.planetminecraft.com/banner/?b=g2feC"); + URL url1 = new URL("http://www.needcoolshoes.com/banner?=pabunK"); + URL url2 = new URL("http://example.com"); + Assert.assertEquals(Parsers.getParser(url).getClass(), PlanetMinecraftParser.class); + Assert.assertEquals(Parsers.getParser(url1).getClass(), NeedCoolShoesParser.class); + Assert.assertNull(Parsers.getParser(url2)); + } + + @Test + public void testPMCParser() throws MalformedURLException { + URL url = new URL("http://www.planetminecraft.com/banner/?b=g1Aca"); + ArrayList matchPattern = new ArrayList(){{ + add(new Pattern(DyeColor.WHITE, PatternType.BASE)); + add(new Pattern(DyeColor.BLACK, PatternType.DIAGONAL_LEFT_MIRROR)); + add(new Pattern(DyeColor.YELLOW, PatternType.DIAGONAL_RIGHT_MIRROR)); + }}; + + ArrayList parsed = Parsers.parse(url); + for (int i = 0; i < parsed.size(); i++) { + Assert.assertEquals(matchPattern.get(i), parsed.get(i)); + } + } + + @Test + public void testNCSParser() throws MalformedURLException { + URL url = new URL("http://www.needcoolshoes.com/banner?=paaIlJ"); + ArrayList matchPattern = new ArrayList(){{ + add(new Pattern(DyeColor.WHITE, PatternType.BASE)); + add(new Pattern(DyeColor.BLACK, PatternType.DIAGONAL_LEFT_MIRROR)); + add(new Pattern(DyeColor.YELLOW, PatternType.DIAGONAL_RIGHT_MIRROR)); + }}; + + ArrayList parsed = Parsers.parse(url); + for (int i = 0; i < parsed.size(); i++) { + Assert.assertEquals(matchPattern.get(i), parsed.get(i)); + } + } + + @Test + public void testDiagonals() throws MalformedURLException { + URL url = new URL("http://www.planetminecraft.com/banner/?b=gcAbBda29"); + URL url1 = new URL("http://www.needcoolshoes.com/banner?=palIkxmJbr"); + + ArrayList matchPattern = new ArrayList(){{ + add(new Pattern(DyeColor.WHITE, PatternType.BASE)); + add(new Pattern(DyeColor.YELLOW, PatternType.DIAGONAL_LEFT_MIRROR)); + add(new Pattern(DyeColor.LIME, PatternType.DIAGONAL_RIGHT)); + add(new Pattern(DyeColor.LIGHT_BLUE, PatternType.DIAGONAL_RIGHT_MIRROR)); + add(new Pattern(DyeColor.RED, PatternType.DIAGONAL_LEFT)); + }}; + + ArrayList parsed = Parsers.parse(url); + for (int i = 0; i < parsed.size(); i++) { + Assert.assertTrue(parsed.get(i).equals(matchPattern.get(i))); + } + + ArrayList parsed1 = Parsers.parse(url1); + for (int i = 0; i < parsed1.size(); i++) { + Assert.assertTrue(parsed1.get(i).equals(matchPattern.get(i))); + } + } +} diff --git a/EtcdConnector/pom.xml b/EtcdConnector/pom.xml new file mode 100644 index 0000000..0377356 --- /dev/null +++ b/EtcdConnector/pom.xml @@ -0,0 +1,76 @@ + + + + utils + eu.mikroskeem + 1.0-SNAPSHOT + + 4.0.0 + + etcdconnector + + + + + org.apache.maven.plugins + maven-shade-plugin + 2.4.3 + + + package + + shade + + + + + *:* + + META-INF/maven/** + + + + + + io.netty + eu.mikroskeem.utils.etcdconnector.deps.io.netty + + io.netty.* + + + + + + + + + + + + + org.jetbrains + annotations-java5 + RELEASE + + + + org.slf4j + slf4j-api + 1.7.21 + + + + org.mousio + etcd4j + 2.12.0 + + + + com.google.code.gson + gson + 2.7 + + + \ No newline at end of file diff --git a/EtcdConnector/src/main/java/eu/mikroskeem/utils/etcdconnector/EtcdConnector.java b/EtcdConnector/src/main/java/eu/mikroskeem/utils/etcdconnector/EtcdConnector.java new file mode 100644 index 0000000..07049b1 --- /dev/null +++ b/EtcdConnector/src/main/java/eu/mikroskeem/utils/etcdconnector/EtcdConnector.java @@ -0,0 +1,30 @@ +package eu.mikroskeem.utils.etcdconnector; + +import mousio.client.retry.RetryOnce; +import mousio.etcd4j.EtcdClient; + +import java.io.IOException; +import java.net.URI; + +public class EtcdConnector extends EtcdConnectorBase { + /** + * Sets up EtcdConnector against + * Etcd server with no encryption + * + * @param etcdUrls url(s) where to connect to + */ + public EtcdConnector(URI... etcdUrls) throws IOException { + super(); + + /* Initialize client */ + initClient(etcdUrls); + + /* Test client */ + testEtcd(); + } + + @Override void initClient(URI... urls){ + etcdClient = new EtcdClient(urls); + etcdClient.setRetryHandler(new RetryOnce(5000)); + } +} \ No newline at end of file diff --git a/EtcdConnector/src/main/java/eu/mikroskeem/utils/etcdconnector/EtcdConnectorBase.java b/EtcdConnector/src/main/java/eu/mikroskeem/utils/etcdconnector/EtcdConnectorBase.java new file mode 100644 index 0000000..c36fe40 --- /dev/null +++ b/EtcdConnector/src/main/java/eu/mikroskeem/utils/etcdconnector/EtcdConnectorBase.java @@ -0,0 +1,206 @@ +package eu.mikroskeem.utils.etcdconnector; + + +import com.google.gson.Gson; +import mousio.etcd4j.EtcdClient; +import mousio.etcd4j.responses.*; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeoutException; + +abstract class EtcdConnectorBase { + final Logger logger; + EtcdClient etcdClient; + + EtcdConnectorBase() throws IOException { + /* Set up logger */ + logger = LoggerFactory.getLogger("EtcdConnector"); + } + + + /** + * Initializes EtcdClient object + */ + abstract void initClient(URI... urls); + + /** + * Tests if Etcd connection is working + * + * @throws IOException if connection doesn't work + */ + void testEtcd() throws IOException { + /* Test client */ + try { + logger.debug("Testing Etcd connection..."); + EtcdVersionResponse ver = etcdClient.version(); + logger.debug("Etcd server version: {}", ver.getServer()); + } catch (NullPointerException e){ + throw new IOException("Etcd connection test failed!"); + } + logger.debug("Etcd is working!"); + } + + /** + * Closes Etcd4j client + * + * @throws IOException Thrown by Etcd4j + */ + public void close() throws IOException { + if(this.etcdClient != null){ + this.etcdClient.close(); + } + } + + /** + * Gets etcd key value + * + * @param path Key path + * @return Key value + */ + @Nullable + public String getKey(@NotNull String path){ + logger.debug("getKey: {}", path); + try { + EtcdKeysResponse response = etcdClient.get(path).send().get(); + /* Parse object */ + String rawResp = response.getNode().getValue(); + if(rawResp != null){ + return new Gson().fromJson(rawResp, String.class); + } + return null; + } catch(EtcdException e){ + if(!e.isErrorCode(EtcdErrorCode.KeyNotFound)) { + e.printStackTrace(); + } + } catch(IOException|EtcdAuthenticationException |TimeoutException e){ + e.printStackTrace(); + } + return null; + } + + /** + * Gets etcd key value and sets default, + * if key isn't defined + * + * @param path Key path + * @param defaultValue Value to set if key is nonexistent + * @return Key value + */ + @Nullable + public String getKey(@NotNull String path, @NotNull String defaultValue){ + logger.debug("getKey: {}, {}", path, defaultValue); + try { + EtcdKeysResponse response = etcdClient.get(path).send().get(); + /* Parse object */ + String rawResp = response.getNode().getValue(); + if(rawResp != null){ + return new Gson().fromJson(rawResp, String.class); + } + return null; + } catch(EtcdException e){ + if(e.isErrorCode(EtcdErrorCode.KeyNotFound)){ + /* Put default value to there then */ + putKey(path, defaultValue); + return defaultValue; + } else e.printStackTrace(); + } catch(IOException|EtcdAuthenticationException|TimeoutException e){ + e.printStackTrace(); + } + return null; + } + + /** + * Gets etcd directory contents and returns it as + * List of String + * + * @param path directory path + * @return directory contents + */ + @Nullable + public List getDir(@NotNull String path){ + logger.debug("getDir: {}", path); + List ret = new ArrayList<>(); + try { + EtcdKeysResponse response = etcdClient.getDir(path).send().get(); + response.getNode().getNodes().forEach(etcdNode -> ret.add((new File(etcdNode.getKey())).getName())); + return ret; + } catch(EtcdException e){ + if(!(e.isErrorCode(EtcdErrorCode.KeyNotFound))){ + e.printStackTrace(); + } + return null; + } catch(IOException|EtcdAuthenticationException|TimeoutException e){ + e.printStackTrace(); + } + return null; + } + + /** + * Sets etcd key value + * + * @param path key path + * @param value key value + * @return whether write succeeded or not + */ + public boolean putKey(@NotNull String path, @NotNull String value){ + logger.debug("putKey: {}, {}", path, value); + try { + /* Serialize value */ + EtcdKeysResponse response = etcdClient.put(path, new Gson().toJson(value)).send().get(); + response.getNode().getValue(); + return true; + } catch(Exception e) { + e.printStackTrace(); + } + return false; + } + + /** + * Sets etcd key value with TTL + * + * @param path key path + * @param value key value + * @param ttl key ttl (seconds) + * @return whether write succeeded or not + */ + public boolean putKey(@NotNull String path, @NotNull String value, @NotNull int ttl){ + logger.debug("putKey: {}, {}, {}", path, value, ttl); + try { + EtcdKeysResponse response = etcdClient.put(path, new Gson().toJson(value)).ttl(ttl).send().get(); + response.getNode().getValue(); + return true; + } catch(Exception e) { + e.printStackTrace(); + } + return false; + } + + /** + * Deletes etcd key + * @param path key path + * @return whether delete succeeded or not + */ + public boolean deleteKey(@NotNull String path){ + logger.debug("deleteKey: {}", path); + try { + EtcdKeysResponse response = etcdClient.delete(path).send().get(); + response.getNode().getValue(); + return true; + } catch(EtcdException e){ + if(!(e.isErrorCode(EtcdErrorCode.KeyNotFound))){ + e.printStackTrace(); + } + } catch(Exception e){ + e.printStackTrace(); + } + return false; + } +} diff --git a/Itemutils/pom.xml b/Itemutils/pom.xml new file mode 100644 index 0000000..c1471c8 --- /dev/null +++ b/Itemutils/pom.xml @@ -0,0 +1,33 @@ + + + + utils + eu.mikroskeem + 1.0-SNAPSHOT + + 4.0.0 + + itemutils + + + + spigot-repo + https://hub.spigotmc.org/nexus/content/repositories/snapshots/ + + + + + org.bukkit + bukkit + 1.10.2-R0.1-SNAPSHOT + provided + + + org.jetbrains + annotations-java5 + RELEASE + + + \ No newline at end of file diff --git a/Itemutils/src/main/java/eu/mikroskeem/utils/itemutils/Shield.java b/Itemutils/src/main/java/eu/mikroskeem/utils/itemutils/Shield.java new file mode 100644 index 0000000..420266b --- /dev/null +++ b/Itemutils/src/main/java/eu/mikroskeem/utils/itemutils/Shield.java @@ -0,0 +1,35 @@ +package eu.mikroskeem.utils.itemutils; + +import org.apache.commons.lang.Validate; +import org.bukkit.Material; +import org.bukkit.block.Banner; +import org.bukkit.block.banner.Pattern; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.BlockStateMeta; +import org.bukkit.inventory.meta.ItemMeta; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; + +public class Shield { + /** + * Set Minecraft shield design + * + * @param shieldStack Shield itemstack to apply design on + * @param patternList Banner design patterns + */ + public static void setShieldDesign(@NotNull ItemStack shieldStack, @Nullable ArrayList patternList){ + Validate.isTrue(shieldStack.getType().equals(Material.SHIELD), "Item must be a shield"); + + ItemMeta shieldMeta = shieldStack.getItemMeta(); + BlockStateMeta shieldbMeta = (BlockStateMeta)shieldMeta; + + Banner banner = (Banner)shieldbMeta.getBlockState(); + banner.setPatterns(patternList); + banner.update(); // TODO: find out if it is needed + + shieldbMeta.setBlockState(banner); + shieldStack.setItemMeta(shieldMeta); + } +} \ No newline at end of file diff --git a/Paste/pom.xml b/Paste/pom.xml new file mode 100644 index 0000000..829b930 --- /dev/null +++ b/Paste/pom.xml @@ -0,0 +1,32 @@ + + + + utils + eu.mikroskeem + 1.0-SNAPSHOT + + 4.0.0 + + paste + + + + org.json + json + 20160212 + + + org.jetbrains + annotations-java5 + RELEASE + + + junit + junit + 4.12 + test + + + \ No newline at end of file diff --git a/Paste/src/main/java/eu/mikroskeem/utils/paste/IPaste.java b/Paste/src/main/java/eu/mikroskeem/utils/paste/IPaste.java new file mode 100644 index 0000000..d7488f8 --- /dev/null +++ b/Paste/src/main/java/eu/mikroskeem/utils/paste/IPaste.java @@ -0,0 +1,7 @@ +package eu.mikroskeem.utils.paste; + +import java.io.IOException; + +public interface IPaste { + String paste(String content) throws IOException; +} diff --git a/Paste/src/main/java/eu/mikroskeem/utils/paste/Paste.java b/Paste/src/main/java/eu/mikroskeem/utils/paste/Paste.java new file mode 100644 index 0000000..b0b09f7 --- /dev/null +++ b/Paste/src/main/java/eu/mikroskeem/utils/paste/Paste.java @@ -0,0 +1,43 @@ +package eu.mikroskeem.utils.paste; + + +import eu.mikroskeem.utils.paste.providers.Hastebin; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; + +/** + * + * @author Mark + */ +public class Paste { + private final IPaste pasteProvider; + public Paste(){ + /* Currently only supported provider */ + this.pasteProvider = new Hastebin(); + } + + /** + * Format exception into proper string + * + * @param e Exception to format + * @return Exception as string + */ + public static String formatException(Exception e) { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + e.printStackTrace(pw); + return sw.toString(); + } + + /** + * Paste stacktrace to pastebin + * + * @param e Exception to paste + * @return Paste url + */ + public String pasteException(Exception e) throws IOException { + return pasteProvider.paste(formatException(e)); + } +} diff --git a/Paste/src/main/java/eu/mikroskeem/utils/paste/providers/Hastebin.java b/Paste/src/main/java/eu/mikroskeem/utils/paste/providers/Hastebin.java new file mode 100644 index 0000000..497bae7 --- /dev/null +++ b/Paste/src/main/java/eu/mikroskeem/utils/paste/providers/Hastebin.java @@ -0,0 +1,39 @@ +package eu.mikroskeem.utils.paste.providers; + +import eu.mikroskeem.utils.paste.IPaste; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.json.JSONObject; + +import java.io.BufferedReader; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; + +public class Hastebin implements IPaste { + @Nullable + public String paste(@NotNull String content) throws IOException { + HttpURLConnection connection = null; + try { + URL url = new URL("https://paste.nightsnack.cf/documents"); + connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("POST"); + connection.setDoInput(true); + connection.setDoOutput(true); + DataOutputStream wr = new DataOutputStream(connection.getOutputStream()); + wr.writeBytes(content); + wr.flush(); + wr.close(); + BufferedReader rd = new BufferedReader(new InputStreamReader(connection.getInputStream())); + return String.format("https://paste.nightsnack.cf/raw/%s", new JSONObject(rd.readLine()).get("key")); + } catch (MalformedURLException e) { + return null; + } finally { + if (connection == null) { return null; } + connection.disconnect(); + } + } +} diff --git a/Paste/src/test/java/eu/mikroskeem/utils/test/paste/PasteTest.java b/Paste/src/test/java/eu/mikroskeem/utils/test/paste/PasteTest.java new file mode 100644 index 0000000..7127b34 --- /dev/null +++ b/Paste/src/test/java/eu/mikroskeem/utils/test/paste/PasteTest.java @@ -0,0 +1,29 @@ +package eu.mikroskeem.utils.test.paste; + +import eu.mikroskeem.utils.paste.Paste; +import org.junit.Assert; +import org.junit.Test; + +import java.io.IOException; + +public class PasteTest { + @Test + public void testExceptionPaste(){ + Paste paste = new Paste(); + try { + throw new RuntimeException("Fake exception"); + } catch (RuntimeException e){ + String url; + try { + url = paste.pasteException(e); + } catch (IOException ioex){ + /* Test paste server down? */ + Assert.fail("Paste server seems to be down, unable to test"); + return; + } + Assert.assertNotNull(url); + System.out.println("Example paste:"); + System.out.println(url); + } + } +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..1aafad3 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# Utils + +Various utils diff --git a/Reflect/pom.xml b/Reflect/pom.xml new file mode 100644 index 0000000..ffcdcd2 --- /dev/null +++ b/Reflect/pom.xml @@ -0,0 +1,26 @@ + + + + utils + eu.mikroskeem + 1.0-SNAPSHOT + + 4.0.0 + + reflect + + + org.jetbrains + annotations-java5 + RELEASE + + + junit + junit + 4.12 + test + + + \ No newline at end of file diff --git a/Reflect/src/main/java/eu/mikroskeem/utils/reflect/Reflect.java b/Reflect/src/main/java/eu/mikroskeem/utils/reflect/Reflect.java new file mode 100644 index 0000000..4698867 --- /dev/null +++ b/Reflect/src/main/java/eu/mikroskeem/utils/reflect/Reflect.java @@ -0,0 +1,124 @@ +package eu.mikroskeem.utils.reflect; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +/** + * Reflection utils + * + * @author Mark + */ +public class Reflect { + + /** + * Find class by name + * + * @param clazz Class to search + * @return Class or null + */ + @Nullable + public static Class getClass(@NotNull String clazz){ + try { + return Class.forName(clazz); + } catch (ClassNotFoundException e){ + return null; + } + } + + /** + * Return whether class exists or not + * + * @param clazz Class to search + * @return Whether class existed or not + */ + public static boolean classExists(@NotNull String clazz){ + return getClass(clazz) != null; + } + + /** + * Get declared class method (public,protected,private) + * + * @param clazz Class to reflect + * @param method Method to search + * @param arguments Method arguments + * @return Method or null + */ + @Nullable + public static Method getMethod(@NotNull Class clazz, @NotNull String method, Class... arguments){ + try { + Method m = clazz.getDeclaredMethod(method, arguments); + m.setAccessible(true); + return m; + } catch (NoSuchMethodException e){ + return null; + } + } + + /** + * Invoke method and get result + * + * @param method Method to invoke + * @param instance Instance where given method resides (null if static) + * @param args Method arguments + * @return Method result or null + */ + @Nullable + public static Object invokeMethod(@NotNull Method method, @Nullable Object instance, @Nullable Object... args){ + try { + return method.invoke(instance, args); + } catch (IllegalAccessException|InvocationTargetException e){ + return null; + } + } + + /** + * Get declared class field (public,protected,private) + * + * @param clazz Class to reflect + * @param field Field to search + * @return Field or null + */ + @Nullable + public static Field getField(@NotNull Class clazz, @NotNull String field){ + try { + Field f = clazz.getDeclaredField(field); + f.setAccessible(true); + return f; + } catch (NoSuchFieldException e){ + return null; + } + } + + /** + * Read field + * + * @param field Field to read + * @param instance Instance where to read (null if static) + * @return Field contents or null; + */ + @Nullable + public static Object readField(@NotNull Field field, @Nullable Object instance){ + try { + return field.get(instance); + } catch (IllegalAccessException e){ + return null; + } + } + + /** + * Write field + * + * @param field Field to write + * @param instance Instance where field resides (null if static) + * @param value Field new contents + */ + public static void writeField(@NotNull Field field, @Nullable Object instance, @Nullable Object value){ + try { + field.set(instance, value); + } catch (IllegalAccessException e){} + } +} diff --git a/Reflect/src/test/java/eu/mikroskeem/utils/test/reflect/ReflectionTestClass.java b/Reflect/src/test/java/eu/mikroskeem/utils/test/reflect/ReflectionTestClass.java new file mode 100644 index 0000000..cdafeae --- /dev/null +++ b/Reflect/src/test/java/eu/mikroskeem/utils/test/reflect/ReflectionTestClass.java @@ -0,0 +1,6 @@ +package eu.mikroskeem.utils.test.reflect; + +public class ReflectionTestClass { + public static String FOOBAR = "nope"; + public static String BAZFED = "yeah"; +} diff --git a/Reflect/src/test/java/eu/mikroskeem/utils/test/reflect/TestReflect.java b/Reflect/src/test/java/eu/mikroskeem/utils/test/reflect/TestReflect.java new file mode 100644 index 0000000..5b32f88 --- /dev/null +++ b/Reflect/src/test/java/eu/mikroskeem/utils/test/reflect/TestReflect.java @@ -0,0 +1,65 @@ +package eu.mikroskeem.utils.test.reflect; + +import eu.mikroskeem.utils.reflect.Reflect; +import org.junit.Assert; +import org.junit.Test; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +public class TestReflect { + @Test + public void testGetClass(){ + Assert.assertEquals(Reflect.getClass("java.lang.String"), String.class); + Assert.assertNotEquals(Reflect.getClass("java.lang.Integer"), String.class); + } + + @Test + public void testClassFind(){ + Assert.assertTrue(Reflect.classExists("java.lang.String")); + Assert.assertFalse(Reflect.classExists("foo.bar.baz.xyz")); + } + + @Test + public void testGetMethod(){ + Class reflectClass = Reflect.getClass("eu.mikroskeem.utils.reflect.Reflect"); + Method method = Reflect.getMethod(reflectClass, "getClass", String.class); + Assert.assertNotNull(method); + Method invalidMethod = Reflect.getMethod(reflectClass, "getClass", Integer.class); + Assert.assertNull(invalidMethod); + } + + @Test + public void testInvokeMethod(){ + Class reflectClass = Reflect.getClass("eu.mikroskeem.utils.reflect.Reflect"); + Method method = Reflect.getMethod(reflectClass, "getClass", String.class); + Class resultClazz = (Class)Reflect.invokeMethod(method, null, "java.lang.String"); + Assert.assertEquals(resultClazz, String.class); + } + + @Test + public void testGetField(){ + Class reflectTestClass = Reflect.getClass("eu.mikroskeem.utils.test.reflect.ReflectionTestClass"); + Field foobarField = Reflect.getField(reflectTestClass, "FOOBAR"); + Assert.assertNotNull(foobarField); + Field invalidField = Reflect.getField(reflectTestClass, "ROOMAZ"); + Assert.assertNull(invalidField); + } + + @Test + public void testReadField(){ + Class reflectTestClass = Reflect.getClass("eu.mikroskeem.utils.test.reflect.ReflectionTestClass"); + Field foobarField = Reflect.getField(reflectTestClass, "FOOBAR"); + String value = (String)Reflect.readField(foobarField, null); + Assert.assertEquals(value, "nope"); + } + + @Test + public void testWriteField(){ + Class reflectTestClass = Reflect.getClass("eu.mikroskeem.utils.test.reflect.ReflectionTestClass"); + Field bazfed = Reflect.getField(reflectTestClass, "BAZFED"); + Reflect.writeField(bazfed, null, "no yeah man :("); + String value = (String)Reflect.readField(bazfed, null); + Assert.assertEquals(value, "no yeah man :("); + } +} diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..f732c03 --- /dev/null +++ b/pom.xml @@ -0,0 +1,55 @@ + + + 4.0.0 + + eu.mikroskeem + utils + pom + 1.0-SNAPSHOT + + Reflect + Bannerparser + EtcdConnector + Paste + Itemutils + + + + + UTF-8 + ${env.USER} + ${env.BUILD_NUMBER} + + + + + + Manual build + + + !env.BUILD_NUMBER + + + + Manual:${maven.build.timestamp} + + + + + + clean compile test package + + + org.apache.maven.plugins + maven-compiler-plugin + 3.5.1 + + 1.8 + 1.8 + + + + + \ No newline at end of file