From f4cb00c0e1abb7d1ad9b1f71189ebd5ac1113254 Mon Sep 17 00:00:00 2001 From: FranKusmiruk Date: Wed, 13 Mar 2019 22:11:47 -0300 Subject: [PATCH 1/2] Attempt to fix the bug with local variables And also update many other things --- build.gradle | 10 +- gradle/wrapper/gradle-wrapper.properties | 2 +- .../java/com/btk5h/skriptdb/SkriptUtil.java | 68 +-------- .../skriptdb/skript/EffExecuteStatement.java | 131 ++++++++++-------- .../java/com/btk5h/skriptdb/skript/Types.java | 2 +- 5 files changed, 82 insertions(+), 131 deletions(-) diff --git a/build.gradle b/build.gradle index 81d76a0..ac8bc75 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.github.jengelman.gradle.plugins:shadow:2.0.1' + classpath 'com.github.jengelman.gradle.plugins:shadow:4.0.2' } } @@ -24,14 +24,14 @@ repositories { url 'https://oss.sonatype.org/content/groups/public/' } maven { - url 'http://maven.njol.ch/repo/' + url 'http://jitpack.io/' } } dependencies { - shadow 'org.spigotmc:spigot-api:1.11-R0.1-SNAPSHOT' - shadow 'ch.njol:skript:2.2-SNAPSHOT' - compile 'com.zaxxer:HikariCP:2.6.2' + shadow 'org.spigotmc:spigot-api:1.13.2-R0.1-SNAPSHOT' + shadow 'com.github.SkriptLang:Skript:2.3.6' + compile 'com.zaxxer:HikariCP:3.3.1' } task buildReadme(type: Javadoc) { diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 3f744f9..4bcfde0 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-all.zip diff --git a/src/main/java/com/btk5h/skriptdb/SkriptUtil.java b/src/main/java/com/btk5h/skriptdb/SkriptUtil.java index 290094b..86075cb 100644 --- a/src/main/java/com/btk5h/skriptdb/SkriptUtil.java +++ b/src/main/java/com/btk5h/skriptdb/SkriptUtil.java @@ -1,25 +1,17 @@ package com.btk5h.skriptdb; -import org.bukkit.event.Event; +import ch.njol.skript.Skript; +import ch.njol.skript.lang.Expression; +import ch.njol.skript.lang.VariableString; import java.lang.reflect.Field; import java.util.Arrays; import java.util.Optional; -import java.util.Set; - -import ch.njol.skript.Skript; -import ch.njol.skript.effects.Delay; -import ch.njol.skript.lang.Expression; -import ch.njol.skript.lang.Variable; -import ch.njol.skript.lang.VariableString; public class SkriptUtil { private static final Field STRING; - private static final Field SIMPLE; - private static final Field DELAYED; private static final Field EXPR; - private static final Field VARIABLE_NAME; static { Field _FIELD = null; @@ -32,25 +24,6 @@ public class SkriptUtil { } STRING = _FIELD; - try { - _FIELD = VariableString.class.getDeclaredField("simple"); - _FIELD.setAccessible(true); - } catch (NoSuchFieldException e) { - Skript.error("Skript's 'simple' field could not be resolved."); - e.printStackTrace(); - } - SIMPLE = _FIELD; - - try { - _FIELD = Delay.class.getDeclaredField("delayed"); - _FIELD.setAccessible(true); - } catch (NoSuchFieldException e) { - e.printStackTrace(); - Skript.warning("Skript's 'delayed' method could not be resolved. Some Skript warnings may " + - "not be available."); - } - DELAYED = _FIELD; - try { Optional> expressionInfo = Arrays.stream(VariableString.class.getDeclaredClasses()) .filter(cls -> cls.getSimpleName().equals("ExpressionInfo")) @@ -67,33 +40,6 @@ public class SkriptUtil { Skript.error("Skript's 'expr' field could not be resolved."); } EXPR = _FIELD; - - try { - _FIELD = Variable.class.getDeclaredField("name"); - _FIELD.setAccessible(true); - } catch (NoSuchFieldException e) { - e.printStackTrace(); - Skript.error("Skript's 'variable name' method could not be resolved."); - } - VARIABLE_NAME = _FIELD; - } - - @SuppressWarnings("unchecked") - public static void delay(Event e) { - if (DELAYED != null) { - try { - ((Set) DELAYED.get(null)).add(e); - } catch (IllegalAccessException ignored) { - } - } - } - - public static String getSimpleString(VariableString vs) { - try { - return (String) SIMPLE.get(vs); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } } public static Object[] getTemplateString(VariableString vs) { @@ -112,12 +58,4 @@ public static Expression getExpressionFromInfo(Object o) { } } - public static VariableString getVariableName(Variable var) { - try { - return (VariableString) VARIABLE_NAME.get(var); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - return null; - } } diff --git a/src/main/java/com/btk5h/skriptdb/skript/EffExecuteStatement.java b/src/main/java/com/btk5h/skriptdb/skript/EffExecuteStatement.java index 5db4c7f..0cbc856 100644 --- a/src/main/java/com/btk5h/skriptdb/skript/EffExecuteStatement.java +++ b/src/main/java/com/btk5h/skriptdb/skript/EffExecuteStatement.java @@ -1,12 +1,14 @@ package com.btk5h.skriptdb.skript; +import ch.njol.skript.effects.Delay; +import ch.njol.skript.lang.*; +import ch.njol.util.Pair; import com.btk5h.skriptdb.SkriptDB; import com.btk5h.skriptdb.SkriptUtil; import com.zaxxer.hikari.HikariDataSource; import org.bukkit.Bukkit; import org.bukkit.event.Event; -import org.eclipse.jdt.annotation.Nullable; import java.sql.Connection; import java.sql.PreparedStatement; @@ -19,17 +21,13 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import javax.sql.DataSource; import javax.sql.rowset.CachedRowSet; import ch.njol.skript.Skript; -import ch.njol.skript.effects.Delay; -import ch.njol.skript.lang.Expression; -import ch.njol.skript.lang.SkriptParser; -import ch.njol.skript.lang.TriggerItem; -import ch.njol.skript.lang.Variable; -import ch.njol.skript.lang.VariableString; import ch.njol.skript.variables.Variables; import ch.njol.util.Kleenean; +import ch.njol.util.Pair; /** * Executes a statement on a database and optionally stores the result in a variable. Expressions @@ -68,8 +66,15 @@ public class EffExecuteStatement extends Delay { @Override protected void execute(Event e) { + DataSource ds = dataSource.getSingle(e); + Pair> query = parseQuery(e); + + if (ds == null) + return; + + Object locals = Variables.removeLocals(e); CompletableFuture sql = - CompletableFuture.supplyAsync(() -> executeStatement(e), threadPool); + CompletableFuture.supplyAsync(() -> executeStatement(e, ds, query), threadPool); sql.whenComplete((res, err) -> { if (err != null) { @@ -80,7 +85,10 @@ protected void execute(Event e) { lastError = res; if (getNext() != null) { + if (locals != null) + Variables.setLocalVariables(e, locals); TriggerItem.walk(getNext(), e); + Variables.removeLocals(e); } }); }); @@ -89,62 +97,24 @@ protected void execute(Event e) { @Override protected TriggerItem walk(Event e) { debug(e, true); - SkriptUtil.delay(e); + Delay.addDelayedEvent(e); execute(e); return null; } - private String executeStatement(Event e) { - HikariDataSource ds = dataSource.getSingle(e); - - if (ds == null) { - return "Data source is not set"; - } - - try (Connection conn = ds.getConnection(); - PreparedStatement stmt = createStatement(e, conn)) { - - boolean hasResultSet = stmt.execute(); - - if (var != null) { - String baseVariable = var.toString(e) - .toLowerCase(Locale.ENGLISH); - if (isList) { - baseVariable = baseVariable.substring(0, baseVariable.length() - 1); - } - - if (hasResultSet) { - CachedRowSet crs = SkriptDB.getRowSetFactory().createCachedRowSet(); - crs.populate(stmt.getResultSet()); - - if (isList) { - populateVariable(e, crs, baseVariable); - } else { - crs.last(); - setVariable(e, baseVariable, crs.getRow()); - } - } else if (!isList) { - setVariable(e, baseVariable, stmt.getUpdateCount()); - } - } - } catch (SQLException ex) { - return ex.getMessage(); - } - return null; - } - - private PreparedStatement createStatement(Event e, Connection conn) throws SQLException { + private Pair> parseQuery(Event e) { if (!(query instanceof VariableString)) { - return conn.prepareStatement(query.getSingle(e)); + return new Pair<>(query.getSingle(e), null); } - - if (((VariableString) query).isSimple()) { - return conn.prepareStatement(SkriptUtil.getSimpleString(((VariableString) query))); + VariableString q = (VariableString) query; + if (q.isSimple()) { + return new Pair<>(q.toString(e), null); } StringBuilder sb = new StringBuilder(); List parameters = new ArrayList<>(); - Object[] objects = SkriptUtil.getTemplateString(((VariableString) query)); + Object[] objects = SkriptUtil.getTemplateString(q); + for (int i = 0; i < objects.length; i++) { Object o = objects[i]; if (o instanceof String) { @@ -183,11 +153,54 @@ private PreparedStatement createStatement(Event e, Connection conn) throws SQLEx } } } + return new Pair<>(sb.toString(), parameters); + } + + private String executeStatement(Event e, DataSource ds, Pair> query) { + if (ds == null) { + return "Data source is not set"; + } + + try (Connection conn = ds.getConnection(); + PreparedStatement stmt = createStatement(conn, query)) { + + boolean hasResultSet = stmt.execute(); - PreparedStatement stmt = conn.prepareStatement(sb.toString()); + if (var != null) { + String baseVariable = var.toString(e) + .toLowerCase(Locale.ENGLISH); + if (isList) { + baseVariable = baseVariable.substring(0, baseVariable.length() - 1); + } - for (int i = 0; i < parameters.size(); i++) { - stmt.setObject(i + 1, parameters.get(i)); + if (hasResultSet) { + CachedRowSet crs = SkriptDB.getRowSetFactory().createCachedRowSet(); + crs.populate(stmt.getResultSet()); + + if (isList) { + populateVariable(e, crs, baseVariable); + } else { + crs.last(); + setVariable(e, baseVariable, crs.getRow()); + } + } else if (!isList) { + setVariable(e, baseVariable, stmt.getUpdateCount()); + } + } + } catch (SQLException ex) { + return ex.getMessage(); + } + return null; + } + + private PreparedStatement createStatement(Connection conn, Pair> query) throws SQLException { + PreparedStatement stmt = conn.prepareStatement(query.getFirst()); + List parameters = query.getSecond(); + + if (parameters != null) { + for (int i = 0; i < parameters.size(); i++) { + stmt.setObject(i + 1, parameters.get(i)); + } } return stmt; @@ -232,7 +245,7 @@ private void populateVariable(Event e, CachedRowSet crs, String baseVariable) } @Override - public String toString(@Nullable Event e, boolean debug) { + public String toString(Event e, boolean debug) { return "execute " + query.toString(e, debug) + " in " + dataSource.toString(e, debug); } @@ -253,7 +266,7 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye Expression expr = exprs[2]; if (expr instanceof Variable) { Variable varExpr = (Variable) expr; - var = SkriptUtil.getVariableName(varExpr); + var = varExpr.getName(); isLocal = varExpr.isLocal(); isList = varExpr.isList(); } else if (expr != null) { diff --git a/src/main/java/com/btk5h/skriptdb/skript/Types.java b/src/main/java/com/btk5h/skriptdb/skript/Types.java index d26610c..7a76cbe 100644 --- a/src/main/java/com/btk5h/skriptdb/skript/Types.java +++ b/src/main/java/com/btk5h/skriptdb/skript/Types.java @@ -64,7 +64,7 @@ public boolean mustSyncDeserialization() { } @Override - public boolean canBeInstantiated(Class c) { + protected boolean canBeInstantiated() { return false; } })); From 1796c22106a3f904dc6e51670c77371f27b373b2 Mon Sep 17 00:00:00 2001 From: FranKusmiruk Date: Fri, 22 Mar 2019 02:32:58 -0300 Subject: [PATCH 2/2] Hopefully fix the issues with local variables Whereas this fix isn't ideal, it does fix the issue with local variables, I honestly didn't think a lot about a better solution so I am open to suggestions. This commit also fixes a bug with the timeout feature throwing a NPE. --- build.gradle | 4 +- .../skriptdb/skript/EffExecuteStatement.java | 42 +++++++++---------- .../btk5h/skriptdb/skript/ExprDataSource.java | 2 +- 3 files changed, 23 insertions(+), 25 deletions(-) diff --git a/build.gradle b/build.gradle index ac8bc75..0bbd17f 100644 --- a/build.gradle +++ b/build.gradle @@ -30,7 +30,9 @@ repositories { dependencies { shadow 'org.spigotmc:spigot-api:1.13.2-R0.1-SNAPSHOT' - shadow 'com.github.SkriptLang:Skript:2.3.6' + shadow('com.github.SkriptLang:Skript:2.3.6') { + transitive = false + } compile 'com.zaxxer:HikariCP:3.3.1' } diff --git a/src/main/java/com/btk5h/skriptdb/skript/EffExecuteStatement.java b/src/main/java/com/btk5h/skriptdb/skript/EffExecuteStatement.java index 0cbc856..2adc842 100644 --- a/src/main/java/com/btk5h/skriptdb/skript/EffExecuteStatement.java +++ b/src/main/java/com/btk5h/skriptdb/skript/EffExecuteStatement.java @@ -1,34 +1,28 @@ package com.btk5h.skriptdb.skript; +import ch.njol.skript.Skript; import ch.njol.skript.effects.Delay; import ch.njol.skript.lang.*; +import ch.njol.skript.variables.Variables; +import ch.njol.util.Kleenean; import ch.njol.util.Pair; import com.btk5h.skriptdb.SkriptDB; import com.btk5h.skriptdb.SkriptUtil; import com.zaxxer.hikari.HikariDataSource; - import org.bukkit.Bukkit; import org.bukkit.event.Event; +import javax.sql.DataSource; +import javax.sql.rowset.CachedRowSet; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSetMetaData; import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; +import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import javax.sql.DataSource; -import javax.sql.rowset.CachedRowSet; - -import ch.njol.skript.Skript; -import ch.njol.skript.variables.Variables; -import ch.njol.util.Kleenean; -import ch.njol.util.Pair; - /** * Executes a statement on a database and optionally stores the result in a variable. Expressions * embedded in the query will be escaped to avoid SQL injection. @@ -63,18 +57,20 @@ public class EffExecuteStatement extends Delay { private VariableString var; private boolean isLocal; private boolean isList; + private Map doLater = new HashMap<>(); @Override protected void execute(Event e) { DataSource ds = dataSource.getSingle(e); Pair> query = parseQuery(e); + String baseVariable = var != null ? var.toString(e).toLowerCase(Locale.ENGLISH) : null; if (ds == null) return; Object locals = Variables.removeLocals(e); CompletableFuture sql = - CompletableFuture.supplyAsync(() -> executeStatement(e, ds, query), threadPool); + CompletableFuture.supplyAsync(() -> executeStatement(ds, baseVariable, query), threadPool); sql.whenComplete((res, err) -> { if (err != null) { @@ -87,6 +83,8 @@ protected void execute(Event e) { if (getNext() != null) { if (locals != null) Variables.setLocalVariables(e, locals); + doLater.forEach((name, value) -> setVariable(e, name, value)); + doLater.clear(); TriggerItem.walk(getNext(), e); Variables.removeLocals(e); } @@ -156,7 +154,7 @@ private Pair> parseQuery(Event e) { return new Pair<>(sb.toString(), parameters); } - private String executeStatement(Event e, DataSource ds, Pair> query) { + private String executeStatement(DataSource ds, String baseVariable, Pair> query) { if (ds == null) { return "Data source is not set"; } @@ -166,9 +164,7 @@ private String executeStatement(Event e, DataSource ds, Pair { static { Skript.registerExpression(ExprDataSource.class, HikariDataSource.class, ExpressionType.COMBINED, "[the] data(base|[ ]source) [(of|at)] %string% " + - "[with [a] [max[imum]] [connection] life[ ]time of %timespan%]"); + "[with [a] [max[imum]] [connection] life[ ]time of %-timespan%]"); } private static Map connectionCache = new HashMap<>();