Updated the Rules Manager
This commit is contained in:
parent
3a4964f24b
commit
e895642a45
@ -18,9 +18,9 @@
|
||||
</classpathentry>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
|
||||
<attributes>
|
||||
<attribute name="test" value="true"/>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
<attribute name="test" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -11,6 +11,7 @@ Thumbs.db
|
||||
font_easter.png
|
||||
font_easter.rft
|
||||
font_fu32.rft
|
||||
math-rules-cache.zip
|
||||
|
||||
/target/
|
||||
/backups/
|
||||
|
Binary file not shown.
18
pom.xml
18
pom.xml
@ -80,17 +80,15 @@
|
||||
<version>2.1.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.openhft</groupId>
|
||||
<artifactId>compiler</artifactId>
|
||||
<version>2.3.0</version>
|
||||
<groupId>org.eclipse.jdt.core.compiler</groupId>
|
||||
<artifactId>ecj</artifactId>
|
||||
<version>4.6.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.lingala.zip4j</groupId>
|
||||
<artifactId>zip4j</artifactId>
|
||||
<version>1.3.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>jdk.tools</groupId>
|
||||
<artifactId>jdk.tools</artifactId>
|
||||
<version>jdk1.8.0</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${project.basedir}/libs/tools.jar</systemPath>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<properties>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
|
@ -61,6 +61,9 @@ import org.warp.picalculator.math.functions.equations.EquationsSystemPart;
|
||||
import com.jogamp.common.util.IOUtil;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
import net.lingala.zip4j.core.ZipFile;
|
||||
import net.lingala.zip4j.model.ZipParameters;
|
||||
import net.lingala.zip4j.util.Zip4jConstants;
|
||||
|
||||
public class Utils {
|
||||
|
||||
@ -880,4 +883,48 @@ public class Utils {
|
||||
return buffer.lines().collect(Collectors.joining("\n"));
|
||||
}
|
||||
}
|
||||
|
||||
public static void zip(String targetPath, String destinationFilePath, String password) {
|
||||
try {
|
||||
ZipParameters parameters = new ZipParameters();
|
||||
parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
|
||||
parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
|
||||
|
||||
if(password.length()>0){
|
||||
parameters.setEncryptFiles(true);
|
||||
parameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_AES);
|
||||
parameters.setAesKeyStrength(Zip4jConstants.AES_STRENGTH_256);
|
||||
parameters.setPassword(password);
|
||||
}
|
||||
|
||||
ZipFile zipFile = new ZipFile(destinationFilePath);
|
||||
|
||||
File targetFile = new File(targetPath);
|
||||
if(targetFile.isFile()){
|
||||
zipFile.addFile(targetFile, parameters);
|
||||
}else if(targetFile.isDirectory()){
|
||||
zipFile.addFolder(targetFile, parameters);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void unzip(String targetZipFilePath, String destinationFolderPath, String password) {
|
||||
try {
|
||||
ZipFile zipFile = new ZipFile(targetZipFilePath);
|
||||
if (zipFile.isEncrypted()) {
|
||||
zipFile.setPassword(password);
|
||||
}
|
||||
zipFile.extractAll(destinationFolderPath);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static Path getJarDirectory() {
|
||||
return Paths.get("").toAbsolutePath();
|
||||
}
|
||||
}
|
||||
|
@ -10,12 +10,15 @@ import java.io.InputStreamReader;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.OpenOption;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
@ -23,6 +26,7 @@ import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import javax.script.Bindings;
|
||||
import javax.script.Compilable;
|
||||
@ -32,6 +36,7 @@ import javax.script.ScriptEngine;
|
||||
import javax.script.ScriptEngineManager;
|
||||
import javax.script.ScriptException;
|
||||
|
||||
import org.eclipse.jdt.core.JDTCompilerAdapter;
|
||||
import org.warp.picalculator.Error;
|
||||
import org.warp.picalculator.StaticVars;
|
||||
import org.warp.picalculator.Utils;
|
||||
@ -45,8 +50,9 @@ import org.warp.picalculator.math.functions.Variable;
|
||||
import org.warp.picalculator.math.functions.Variable.V_TYPE;
|
||||
import org.warp.picalculator.math.solver.MathSolver;
|
||||
|
||||
import com.jogamp.common.util.IOUtil;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
import net.openhft.compiler.CompilerUtils;
|
||||
|
||||
public class RulesManager {
|
||||
|
||||
@ -57,95 +63,131 @@ public class RulesManager {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void initialize() {
|
||||
Utils.out.println(Utils.OUTPUTLEVEL_NODEBUG, "RulesManager", "Loading the rules");
|
||||
rules = new ObjectArrayList[RuleType.values().length];
|
||||
for (RuleType val : RuleType.values()) {
|
||||
rules[val.ordinal()] = new ObjectArrayList<Rule>();
|
||||
}
|
||||
try {
|
||||
final Path rulesPath = Utils.getResource("/math-rules.csv");
|
||||
final Path rulesPath = Utils.getResource("/rules.csv");
|
||||
if (!Files.exists(rulesPath)) {
|
||||
throw new FileNotFoundException("math-rules.csv not found!");
|
||||
throw new FileNotFoundException("rules.csv not found!");
|
||||
}
|
||||
ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
|
||||
List<String> ruleLines = Files.readAllLines(rulesPath);
|
||||
ruleLines.remove(0); //Remove the headers
|
||||
|
||||
boolean useCache = false;
|
||||
Path tDir = Paths.get(System.getProperty("java.io.tmpdir"), "WarpPi-Calculator").resolve("rules-rt");
|
||||
Path cacheFilePath = Paths.get(Utils.getJarDirectory().toString()).resolve("math-rules-cache.zip").toAbsolutePath();
|
||||
if (cacheFilePath.toFile().exists()) {
|
||||
try {
|
||||
if (tDir.toFile().exists()) {
|
||||
tDir.toFile().delete();
|
||||
}
|
||||
Utils.unzip(cacheFilePath.toString(), tDir.getParent().toString(), "");
|
||||
useCache = !StaticVars.debugOn;
|
||||
cacheFilePath.toFile().delete();
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
for (String rulesLine : ruleLines) {
|
||||
if (rulesLine.length() > 0) {
|
||||
String[] ruleDetails = rulesLine.split(",", 1);
|
||||
String ruleName = ruleDetails[0];
|
||||
String ruleNameEscaped = ruleName.replace(".", "_");
|
||||
Utils.out.println("Evaluating /rules/" + ruleNameEscaped + ".java");
|
||||
Utils.out.println(Utils.OUTPUTLEVEL_NODEBUG, "RulesManager", "Evaluating /rules/" + ruleNameEscaped + ".java");
|
||||
String pathWithoutExtension = "/rules/" + ruleNameEscaped;
|
||||
String compiledFile = ruleNameEscaped + ".ser";
|
||||
InputStream compiledResourcePath = Utils.getResourceStreamSafe(compiledFile);
|
||||
String scriptFile = pathWithoutExtension + ".java";
|
||||
InputStream resourcePath = Utils.getResourceStream(scriptFile);
|
||||
if (resourcePath == null) {
|
||||
System.err.println(new FileNotFoundException("/rules/" + ruleName + ".java not found!"));
|
||||
} else {
|
||||
boolean loadedFromCache = false;
|
||||
if (compiledResourcePath != null) {
|
||||
if (Files.readAttributes(Paths.get(compiledFile), BasicFileAttributes.class).creationTime().compareTo(Files.readAttributes(Paths.get(scriptFile), BasicFileAttributes.class).creationTime()) < 0) {
|
||||
//The cached file is older than the source file. Deleting it.
|
||||
try {
|
||||
Files.deleteIfExists(Paths.get(compiledFile));
|
||||
} catch (Exception ex2) {
|
||||
ex2.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
//Trying to read the compiled script
|
||||
ObjectInputStream ois = new ObjectInputStream(compiledResourcePath);
|
||||
RulesManager.addRule((Rule) ois.readObject());
|
||||
loadedFromCache = true;
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
try {
|
||||
Files.deleteIfExists(Paths.get(compiledFile));
|
||||
} catch (Exception ex2) {
|
||||
ex2.printStackTrace();
|
||||
}
|
||||
Rule r = null;
|
||||
if (useCache) {
|
||||
try {
|
||||
Utils.out.println(Utils.OUTPUTLEVEL_DEBUG_MIN, "RulesManager", ruleName, "Trying to load cached rule");
|
||||
r = loadClassRuleFromSourceFile(scriptFile, tDir);
|
||||
if (r != null) {
|
||||
Utils.out.println(Utils.OUTPUTLEVEL_DEBUG_MIN, "RulesManager", ruleName, "Loaded cached rule");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Utils.out.println(Utils.OUTPUTLEVEL_NODEBUG, "RulesManager", ruleName, "Can't load the rule!");
|
||||
}
|
||||
}
|
||||
if (!loadedFromCache) {
|
||||
Rule r = null;
|
||||
if (r == null || !useCache) {
|
||||
Utils.out.println(Utils.OUTPUTLEVEL_DEBUG_MIN, "RulesManager", ruleName, "This rule is not cached. Compiling");
|
||||
try {
|
||||
r = compileJavaRule(scriptFile);
|
||||
RulesManager.addRule(r);
|
||||
|
||||
Path p = Paths.get(compiledFile.replace("/", "_")).toAbsolutePath();
|
||||
System.out.println(p);
|
||||
p.toFile().createNewFile();
|
||||
OutputStream fout = Files.newOutputStream(p, StandardOpenOption.CREATE);
|
||||
ObjectOutputStream oos = new ObjectOutputStream(fout);
|
||||
oos.writeObject(r);
|
||||
r = compileJavaRule(scriptFile, tDir);
|
||||
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
RulesManager.addRule(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
Utils.out.println(Utils.OUTPUTLEVEL_NODEBUG, "RulesManager", "Loaded all the rules successfully");
|
||||
Utils.zip(tDir.toString(), cacheFilePath.toString(), "");
|
||||
Utils.out.println(Utils.OUTPUTLEVEL_NODEBUG, "RulesManager", "Cached the compiled rules");
|
||||
} catch (URISyntaxException | IOException e) {
|
||||
e.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
public static Rule compileJavaRule(String scriptFile) throws IOException, URISyntaxException, InstantiationException, IllegalAccessException, ClassNotFoundException {
|
||||
// dynamically you can call
|
||||
public static Rule compileJavaRule(String scriptFile, Path tDir) throws IOException, URISyntaxException, InstantiationException, IllegalAccessException, ClassNotFoundException {
|
||||
InputStream resource = Utils.getResourceStream(scriptFile);
|
||||
|
||||
String scriptFileRelative = scriptFile.substring(1);
|
||||
String text = Utils.read(resource);
|
||||
String[] textArray = text.split("\\n", 2);
|
||||
String javaClassName = textArray[0].substring(2, textArray[0].length() - 2);
|
||||
String javaCode = textArray[1];
|
||||
Class aClass = CompilerUtils.CACHED_COMPILER.loadFromJava(javaClassName, javaCode);
|
||||
Rule rule = (Rule) aClass.newInstance();
|
||||
return rule;
|
||||
String[] textArray = text.split("\\n", 5);
|
||||
String javaClassName = textArray[2].substring(6);
|
||||
String javaClassNameAndPath = new StringBuilder("org.warp.picalculator.math.rules.").append(javaClassName).toString();
|
||||
final int extIndex = javaClassNameAndPath.lastIndexOf('.');
|
||||
String javaCode = new StringBuilder("package ").append(javaClassNameAndPath.substring(0, extIndex >= 0 ? extIndex : javaClassNameAndPath.length())).append(";\n")
|
||||
.append(textArray[4]).toString();
|
||||
Path tDirPath = tDir.resolve(javaClassNameAndPath.replace('.', File.separatorChar)).getParent();
|
||||
Path tFileJava = tDirPath.resolve(javaClassName + ".java");
|
||||
Path tFileClass = tDirPath.resolve(javaClassName + ".class");
|
||||
if (!tDirPath.toFile().exists()) {
|
||||
Files.createDirectories(tDirPath);
|
||||
}
|
||||
Files.write(tFileJava, javaCode.getBytes("UTF-8"), StandardOpenOption.WRITE, StandardOpenOption.CREATE);
|
||||
boolean compiled = org.eclipse.jdt.internal.compiler.batch.Main.compile(new String[] {"-nowarn", "-1.8", tFileJava.toString()}, new PrintWriter(System.out), new PrintWriter(System.err), null);
|
||||
if (StaticVars.debugOn) {
|
||||
tFileJava.toFile().deleteOnExit();
|
||||
} else {
|
||||
tFileJava.toFile().delete();
|
||||
}
|
||||
if (compiled) {
|
||||
tFileClass.toFile().deleteOnExit();
|
||||
return loadClassRuleDirectly(javaClassNameAndPath, tDir);
|
||||
} else {
|
||||
throw new IOException("Can't build script file '" + scriptFile + "'");
|
||||
}
|
||||
}
|
||||
|
||||
public static Rule loadClassRuleFromSourceFile(String scriptFile, Path tDir) throws IOException, URISyntaxException, InstantiationException, IllegalAccessException, ClassNotFoundException {
|
||||
InputStream resource = Utils.getResourceStream(scriptFile);
|
||||
String text = Utils.read(resource);
|
||||
String[] textArray = text.split("\\n", 5);
|
||||
String javaClassName = textArray[2].substring(6);
|
||||
String javaClassNameAndPath = new StringBuilder("org.warp.picalculator.math.rules.").append(javaClassName).toString();
|
||||
try {
|
||||
return loadClassRuleDirectly(javaClassNameAndPath, tDir);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Rule loadClassRuleDirectly(String javaClassNameAndPath, Path tDir) throws IOException, URISyntaxException, InstantiationException, IllegalAccessException, ClassNotFoundException {
|
||||
URLClassLoader cl = new URLClassLoader(new URL[] {tDir.toUri().toURL()});
|
||||
Class<?> aClass = cl.loadClass(javaClassNameAndPath);
|
||||
cl.close();
|
||||
return (Rule) aClass.newInstance();
|
||||
}
|
||||
|
||||
public static void warmUp() {
|
||||
@ -184,6 +226,6 @@ public class RulesManager {
|
||||
|
||||
public static void addRule(Rule rule) {
|
||||
rules[rule.getRuleType().ordinal()].add(rule);
|
||||
Utils.out.println(Utils.OUTPUTLEVEL_NODEBUG, "Loaded rule " + rule.getRuleName() + " as " + rule.getRuleType() + " rule.");
|
||||
Utils.out.println(Utils.OUTPUTLEVEL_NODEBUG, "RulesManager", rule.getRuleName(), "Loaded as " + rule.getRuleType() + " rule");
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
/*org.warp.picalculator.math.rules.FractionsRule2*/
|
||||
package org.warp.picalculator.math.rules;
|
||||
/*
|
||||
SETTINGS: (please don't move this part)
|
||||
PATH=FractionsRule2
|
||||
*/
|
||||
|
||||
//Imports
|
||||
import org.warp.picalculator.Error;
|
||||
@ -22,9 +24,11 @@ import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
*/
|
||||
public class FractionsRule2 implements Rule {
|
||||
|
||||
public static final long serialVersionUID = 11239034890L;
|
||||
|
||||
@Override
|
||||
public String getRuleName() {
|
||||
return "FractionsRule1";
|
||||
return "FractionsRule2";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
Loading…
Reference in New Issue
Block a user