actual freya branch
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* 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 com.l2jserver.gameserver.scripting;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.script.Compilable;
|
||||
import javax.script.CompiledScript;
|
||||
import javax.script.ScriptEngine;
|
||||
import javax.script.ScriptException;
|
||||
|
||||
import javolution.util.FastMap;
|
||||
|
||||
import com.l2jserver.Config;
|
||||
|
||||
/**
|
||||
* Cache of Compiled Scripts
|
||||
* @author KenM
|
||||
*/
|
||||
public class CompiledScriptCache implements Serializable
|
||||
{
|
||||
/**
|
||||
* Version 1
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(CompiledScriptCache.class.getName());
|
||||
|
||||
private final Map<String, CompiledScriptHolder> _compiledScriptCache = new FastMap<>();
|
||||
private transient boolean _modified = false;
|
||||
|
||||
public CompiledScript loadCompiledScript(ScriptEngine engine, File file) throws FileNotFoundException, ScriptException
|
||||
{
|
||||
int len = L2ScriptEngineManager.SCRIPT_FOLDER.getPath().length() + 1;
|
||||
String relativeName = file.getPath().substring(len);
|
||||
|
||||
CompiledScriptHolder csh = _compiledScriptCache.get(relativeName);
|
||||
if ((csh != null) && csh.matches(file))
|
||||
{
|
||||
if (Config.DEBUG)
|
||||
{
|
||||
LOG.fine("Reusing cached compiled script: " + file);
|
||||
}
|
||||
return csh.getCompiledScript();
|
||||
}
|
||||
|
||||
if (Config.DEBUG)
|
||||
{
|
||||
LOG.info("Compiling script: " + file);
|
||||
}
|
||||
Compilable eng = (Compilable) engine;
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
|
||||
|
||||
// TODO lock file
|
||||
CompiledScript cs = eng.compile(reader);
|
||||
if (cs instanceof Serializable)
|
||||
{
|
||||
synchronized (_compiledScriptCache)
|
||||
{
|
||||
_compiledScriptCache.put(relativeName, new CompiledScriptHolder(cs, file));
|
||||
_modified = true;
|
||||
}
|
||||
}
|
||||
|
||||
return cs;
|
||||
}
|
||||
|
||||
public boolean isModified()
|
||||
{
|
||||
return _modified;
|
||||
}
|
||||
|
||||
public void purge()
|
||||
{
|
||||
synchronized (_compiledScriptCache)
|
||||
{
|
||||
for (String path : _compiledScriptCache.keySet())
|
||||
{
|
||||
File file = new File(L2ScriptEngineManager.SCRIPT_FOLDER, path);
|
||||
if (!file.isFile())
|
||||
{
|
||||
_compiledScriptCache.remove(path);
|
||||
_modified = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void save() throws FileNotFoundException, IOException
|
||||
{
|
||||
synchronized (_compiledScriptCache)
|
||||
{
|
||||
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File(L2ScriptEngineManager.SCRIPT_FOLDER, "CompiledScripts.cache"))))
|
||||
{
|
||||
oos.writeObject(this);
|
||||
}
|
||||
_modified = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* 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 com.l2jserver.gameserver.scripting;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.script.CompiledScript;
|
||||
|
||||
/**
|
||||
* @author KenM
|
||||
*/
|
||||
public class CompiledScriptHolder implements Serializable
|
||||
{
|
||||
/**
|
||||
* Version 1
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private long _lastModified;
|
||||
private long _size;
|
||||
private CompiledScript _compiledScript;
|
||||
|
||||
/**
|
||||
* @param compiledScript
|
||||
* @param lastModified
|
||||
* @param size
|
||||
*/
|
||||
public CompiledScriptHolder(CompiledScript compiledScript, long lastModified, long size)
|
||||
{
|
||||
_compiledScript = compiledScript;
|
||||
_lastModified = lastModified;
|
||||
_size = size;
|
||||
}
|
||||
|
||||
public CompiledScriptHolder(CompiledScript compiledScript, File scriptFile)
|
||||
{
|
||||
this(compiledScript, scriptFile.lastModified(), scriptFile.length());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the lastModified.
|
||||
*/
|
||||
public long getLastModified()
|
||||
{
|
||||
return _lastModified;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param lastModified The lastModified to set.
|
||||
*/
|
||||
public void setLastModified(long lastModified)
|
||||
{
|
||||
_lastModified = lastModified;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the size.
|
||||
*/
|
||||
public long getSize()
|
||||
{
|
||||
return _size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param size The size to set.
|
||||
*/
|
||||
public void setSize(long size)
|
||||
{
|
||||
_size = size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the compiledScript.
|
||||
*/
|
||||
public CompiledScript getCompiledScript()
|
||||
{
|
||||
return _compiledScript;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param compiledScript The compiledScript to set.
|
||||
*/
|
||||
public void setCompiledScript(CompiledScript compiledScript)
|
||||
{
|
||||
_compiledScript = compiledScript;
|
||||
}
|
||||
|
||||
public boolean matches(File f)
|
||||
{
|
||||
return (f.lastModified() == getLastModified()) && (f.length() == getSize());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,619 @@
|
||||
/*
|
||||
* 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 com.l2jserver.gameserver.scripting;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.InvalidClassException;
|
||||
import java.io.LineNumberReader;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.script.Compilable;
|
||||
import javax.script.CompiledScript;
|
||||
import javax.script.ScriptContext;
|
||||
import javax.script.ScriptEngine;
|
||||
import javax.script.ScriptEngineFactory;
|
||||
import javax.script.ScriptEngineManager;
|
||||
import javax.script.ScriptException;
|
||||
import javax.script.SimpleScriptContext;
|
||||
|
||||
import javolution.util.FastMap;
|
||||
|
||||
import com.l2jserver.Config;
|
||||
import com.l2jserver.script.jython.JythonScriptEngine;
|
||||
|
||||
/**
|
||||
* Caches script engines and provides funcionality for executing and managing scripts.<BR>
|
||||
* @author KenM
|
||||
*/
|
||||
public final class L2ScriptEngineManager
|
||||
{
|
||||
private static final Logger _log = Logger.getLogger(L2ScriptEngineManager.class.getName());
|
||||
|
||||
public final static File SCRIPT_FOLDER = new File(Config.DATAPACK_ROOT.getAbsolutePath(), "data/scripts");
|
||||
|
||||
public static L2ScriptEngineManager getInstance()
|
||||
{
|
||||
return SingletonHolder._instance;
|
||||
}
|
||||
|
||||
private final Map<String, ScriptEngine> _nameEngines = new FastMap<>();
|
||||
private final Map<String, ScriptEngine> _extEngines = new FastMap<>();
|
||||
private final List<ScriptManager<?>> _scriptManagers = new LinkedList<>();
|
||||
|
||||
private final CompiledScriptCache _cache;
|
||||
|
||||
private File _currentLoadingScript;
|
||||
|
||||
// Configs
|
||||
// TODO move to config file
|
||||
/**
|
||||
* Informs(logs) the scripts being loaded.<BR>
|
||||
* Apply only when executing script from files.<BR>
|
||||
*/
|
||||
private final boolean VERBOSE_LOADING = false;
|
||||
|
||||
/**
|
||||
* If the script engine supports compilation the script is compiled before execution.<BR>
|
||||
*/
|
||||
private final boolean ATTEMPT_COMPILATION = true;
|
||||
|
||||
/**
|
||||
* Use Compiled Scripts Cache.<BR>
|
||||
* Only works if ATTEMPT_COMPILATION is true.<BR>
|
||||
* DISABLED DUE ISSUES (if a superclass file changes subclasses are not recompiled where they should)
|
||||
*/
|
||||
private final boolean USE_COMPILED_CACHE = false;
|
||||
|
||||
/**
|
||||
* Clean an previous error log(if such exists) for the script being loaded before trying to load.<BR>
|
||||
* Apply only when executing script from files.<BR>
|
||||
*/
|
||||
private final boolean PURGE_ERROR_LOG = true;
|
||||
|
||||
private L2ScriptEngineManager()
|
||||
{
|
||||
ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
|
||||
List<ScriptEngineFactory> factories = scriptEngineManager.getEngineFactories();
|
||||
if (USE_COMPILED_CACHE)
|
||||
{
|
||||
_cache = loadCompiledScriptCache();
|
||||
}
|
||||
else
|
||||
{
|
||||
_cache = null;
|
||||
}
|
||||
_log.info("Initializing Script Engine Manager");
|
||||
|
||||
for (ScriptEngineFactory factory : factories)
|
||||
{
|
||||
try
|
||||
{
|
||||
ScriptEngine engine = factory.getScriptEngine();
|
||||
boolean reg = false;
|
||||
for (String name : factory.getNames())
|
||||
{
|
||||
ScriptEngine existentEngine = _nameEngines.get(name);
|
||||
|
||||
if (existentEngine != null)
|
||||
{
|
||||
double engineVer = Double.parseDouble(factory.getEngineVersion());
|
||||
double existentEngVer = Double.parseDouble(existentEngine.getFactory().getEngineVersion());
|
||||
|
||||
if (engineVer <= existentEngVer)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
reg = true;
|
||||
_nameEngines.put(name, engine);
|
||||
}
|
||||
|
||||
if (reg)
|
||||
{
|
||||
_log.info("Script Engine: " + factory.getEngineName() + " " + factory.getEngineVersion() + " - Language: " + factory.getLanguageName() + " - Language Version: " + factory.getLanguageVersion());
|
||||
}
|
||||
|
||||
for (String ext : factory.getExtensions())
|
||||
{
|
||||
if (!ext.equals("java") || factory.getLanguageName().equals("java"))
|
||||
{
|
||||
_extEngines.put(ext, engine);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.log(Level.WARNING, "Failed initializing factory: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
preConfigure();
|
||||
}
|
||||
|
||||
private void preConfigure()
|
||||
{
|
||||
// java class path
|
||||
|
||||
// Jython sys.path
|
||||
String dataPackDirForwardSlashes = SCRIPT_FOLDER.getPath().replaceAll("\\\\", "/");
|
||||
String configScript = "import sys;sys.path.insert(0,'" + dataPackDirForwardSlashes + "');";
|
||||
try
|
||||
{
|
||||
this.eval("jython", configScript);
|
||||
}
|
||||
catch (ScriptException e)
|
||||
{
|
||||
_log.severe("Failed preconfiguring jython: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private ScriptEngine getEngineByName(String name)
|
||||
{
|
||||
return _nameEngines.get(name);
|
||||
}
|
||||
|
||||
private ScriptEngine getEngineByExtension(String ext)
|
||||
{
|
||||
return _extEngines.get(ext);
|
||||
}
|
||||
|
||||
public void executeScriptList(File list) throws IOException
|
||||
{
|
||||
File file;
|
||||
|
||||
if (!Config.ALT_DEV_NO_HANDLERS && Config.ALT_DEV_NO_QUESTS)
|
||||
{
|
||||
file = new File(SCRIPT_FOLDER, "handlers/MasterHandler.java");
|
||||
|
||||
try
|
||||
{
|
||||
this.executeScript(file);
|
||||
_log.info("Handlers loaded, all other scripts skipped");
|
||||
return;
|
||||
}
|
||||
catch (ScriptException se)
|
||||
{
|
||||
_log.log(Level.WARNING, "", se);
|
||||
}
|
||||
}
|
||||
|
||||
if (Config.ALT_DEV_NO_QUESTS)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (list.isFile())
|
||||
{
|
||||
LineNumberReader lnr = new LineNumberReader(new InputStreamReader(new FileInputStream(list)));
|
||||
String line;
|
||||
|
||||
while ((line = lnr.readLine()) != null)
|
||||
{
|
||||
if (Config.ALT_DEV_NO_HANDLERS && line.contains("MasterHandler.java"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
String[] parts = line.trim().split("#");
|
||||
|
||||
if ((parts.length > 0) && !parts[0].startsWith("#") && (parts[0].length() > 0))
|
||||
{
|
||||
line = parts[0];
|
||||
|
||||
if (line.endsWith("/**"))
|
||||
{
|
||||
line = line.substring(0, line.length() - 3);
|
||||
}
|
||||
else if (line.endsWith("/*"))
|
||||
{
|
||||
line = line.substring(0, line.length() - 2);
|
||||
}
|
||||
|
||||
file = new File(SCRIPT_FOLDER, line);
|
||||
|
||||
if (file.isDirectory() && parts[0].endsWith("/**"))
|
||||
{
|
||||
this.executeAllScriptsInDirectory(file, true, 32);
|
||||
}
|
||||
else if (file.isDirectory() && parts[0].endsWith("/*"))
|
||||
{
|
||||
this.executeAllScriptsInDirectory(file);
|
||||
}
|
||||
else if (file.isFile())
|
||||
{
|
||||
try
|
||||
{
|
||||
this.executeScript(file);
|
||||
}
|
||||
catch (ScriptException e)
|
||||
{
|
||||
reportScriptFileError(file, e);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_log.warning("Failed loading: (" + file.getCanonicalPath() + ") @ " + list.getName() + ":" + lnr.getLineNumber() + " - Reason: doesnt exists or is not a file.");
|
||||
}
|
||||
}
|
||||
}
|
||||
lnr.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException("Argument must be an file containing a list of scripts to be loaded");
|
||||
}
|
||||
}
|
||||
|
||||
public void executeAllScriptsInDirectory(File dir)
|
||||
{
|
||||
this.executeAllScriptsInDirectory(dir, false, 0);
|
||||
}
|
||||
|
||||
public void executeAllScriptsInDirectory(File dir, boolean recurseDown, int maxDepth)
|
||||
{
|
||||
this.executeAllScriptsInDirectory(dir, recurseDown, maxDepth, 0);
|
||||
}
|
||||
|
||||
private void executeAllScriptsInDirectory(File dir, boolean recurseDown, int maxDepth, int currentDepth)
|
||||
{
|
||||
if (dir.isDirectory())
|
||||
{
|
||||
for (File file : dir.listFiles())
|
||||
{
|
||||
if (file.isDirectory() && recurseDown && (maxDepth > currentDepth))
|
||||
{
|
||||
if (VERBOSE_LOADING)
|
||||
{
|
||||
_log.info("Entering folder: " + file.getName());
|
||||
}
|
||||
this.executeAllScriptsInDirectory(file, recurseDown, maxDepth, currentDepth + 1);
|
||||
}
|
||||
else if (file.isFile())
|
||||
{
|
||||
try
|
||||
{
|
||||
String name = file.getName();
|
||||
int lastIndex = name.lastIndexOf('.');
|
||||
String extension;
|
||||
if (lastIndex != -1)
|
||||
{
|
||||
extension = name.substring(lastIndex + 1);
|
||||
ScriptEngine engine = getEngineByExtension(extension);
|
||||
if (engine != null)
|
||||
{
|
||||
this.executeScript(engine, file);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
// should never happen
|
||||
_log.log(Level.WARNING, "", e);
|
||||
}
|
||||
catch (ScriptException e)
|
||||
{
|
||||
reportScriptFileError(file, e);
|
||||
// _log.log(Level.WARNING, "", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException("The argument directory either doesnt exists or is not an directory.");
|
||||
}
|
||||
}
|
||||
|
||||
public CompiledScriptCache getCompiledScriptCache()
|
||||
{
|
||||
return _cache;
|
||||
}
|
||||
|
||||
public CompiledScriptCache loadCompiledScriptCache()
|
||||
{
|
||||
if (USE_COMPILED_CACHE)
|
||||
{
|
||||
File file = new File(SCRIPT_FOLDER, "CompiledScripts.cache");
|
||||
if (file.isFile())
|
||||
{
|
||||
ObjectInputStream ois = null;
|
||||
try
|
||||
{
|
||||
ois = new ObjectInputStream(new FileInputStream(file));
|
||||
CompiledScriptCache cache = (CompiledScriptCache) ois.readObject();
|
||||
return cache;
|
||||
}
|
||||
catch (InvalidClassException e)
|
||||
{
|
||||
_log.log(Level.SEVERE, "Failed loading Compiled Scripts Cache, invalid class (Possibly outdated).", e);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
_log.log(Level.SEVERE, "Failed loading Compiled Scripts Cache from file.", e);
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
_log.log(Level.SEVERE, "Failed loading Compiled Scripts Cache, class not found.", e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
ois.close();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
}
|
||||
}
|
||||
return new CompiledScriptCache();
|
||||
}
|
||||
return new CompiledScriptCache();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void executeScript(File file) throws ScriptException, FileNotFoundException
|
||||
{
|
||||
String name = file.getName();
|
||||
int lastIndex = name.lastIndexOf('.');
|
||||
String extension;
|
||||
if (lastIndex != -1)
|
||||
{
|
||||
extension = name.substring(lastIndex + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ScriptException("Script file (" + name + ") doesnt has an extension that identifies the ScriptEngine to be used.");
|
||||
}
|
||||
|
||||
ScriptEngine engine = getEngineByExtension(extension);
|
||||
if (engine == null)
|
||||
{
|
||||
throw new ScriptException("No engine registered for extension (" + extension + ")");
|
||||
}
|
||||
executeScript(engine, file);
|
||||
}
|
||||
|
||||
public void executeScript(String engineName, File file) throws FileNotFoundException, ScriptException
|
||||
{
|
||||
ScriptEngine engine = getEngineByName(engineName);
|
||||
if (engine == null)
|
||||
{
|
||||
throw new ScriptException("No engine registered with name (" + engineName + ")");
|
||||
}
|
||||
executeScript(engine, file);
|
||||
}
|
||||
|
||||
public void executeScript(ScriptEngine engine, File file) throws FileNotFoundException, ScriptException
|
||||
{
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
|
||||
|
||||
if (VERBOSE_LOADING)
|
||||
{
|
||||
_log.info("Loading Script: " + file.getAbsolutePath());
|
||||
}
|
||||
|
||||
if (PURGE_ERROR_LOG)
|
||||
{
|
||||
String name = file.getAbsolutePath() + ".error.log";
|
||||
File errorLog = new File(name);
|
||||
if (errorLog.isFile())
|
||||
{
|
||||
errorLog.delete();
|
||||
}
|
||||
}
|
||||
|
||||
if ((engine instanceof Compilable) && ATTEMPT_COMPILATION)
|
||||
{
|
||||
ScriptContext context = new SimpleScriptContext();
|
||||
context.setAttribute("mainClass", getClassForFile(file).replace('/', '.').replace('\\', '.'), ScriptContext.ENGINE_SCOPE);
|
||||
context.setAttribute(ScriptEngine.FILENAME, file.getName(), ScriptContext.ENGINE_SCOPE);
|
||||
context.setAttribute("classpath", SCRIPT_FOLDER.getAbsolutePath(), ScriptContext.ENGINE_SCOPE);
|
||||
context.setAttribute("sourcepath", SCRIPT_FOLDER.getAbsolutePath(), ScriptContext.ENGINE_SCOPE);
|
||||
context.setAttribute(JythonScriptEngine.JYTHON_ENGINE_INSTANCE, engine, ScriptContext.ENGINE_SCOPE);
|
||||
|
||||
setCurrentLoadingScript(file);
|
||||
ScriptContext ctx = engine.getContext();
|
||||
try
|
||||
{
|
||||
engine.setContext(context);
|
||||
if (USE_COMPILED_CACHE)
|
||||
{
|
||||
CompiledScript cs = _cache.loadCompiledScript(engine, file);
|
||||
cs.eval(context);
|
||||
}
|
||||
else
|
||||
{
|
||||
Compilable eng = (Compilable) engine;
|
||||
CompiledScript cs = eng.compile(reader);
|
||||
cs.eval(context);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
engine.setContext(ctx);
|
||||
setCurrentLoadingScript(null);
|
||||
context.removeAttribute(ScriptEngine.FILENAME, ScriptContext.ENGINE_SCOPE);
|
||||
context.removeAttribute("mainClass", ScriptContext.ENGINE_SCOPE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ScriptContext context = new SimpleScriptContext();
|
||||
context.setAttribute("mainClass", getClassForFile(file).replace('/', '.').replace('\\', '.'), ScriptContext.ENGINE_SCOPE);
|
||||
context.setAttribute(ScriptEngine.FILENAME, file.getName(), ScriptContext.ENGINE_SCOPE);
|
||||
context.setAttribute("classpath", SCRIPT_FOLDER.getAbsolutePath(), ScriptContext.ENGINE_SCOPE);
|
||||
context.setAttribute("sourcepath", SCRIPT_FOLDER.getAbsolutePath(), ScriptContext.ENGINE_SCOPE);
|
||||
setCurrentLoadingScript(file);
|
||||
try
|
||||
{
|
||||
engine.eval(reader, context);
|
||||
}
|
||||
finally
|
||||
{
|
||||
setCurrentLoadingScript(null);
|
||||
engine.getContext().removeAttribute(ScriptEngine.FILENAME, ScriptContext.ENGINE_SCOPE);
|
||||
engine.getContext().removeAttribute("mainClass", ScriptContext.ENGINE_SCOPE);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static String getClassForFile(File script)
|
||||
{
|
||||
String path = script.getAbsolutePath();
|
||||
String scpPath = SCRIPT_FOLDER.getAbsolutePath();
|
||||
if (path.startsWith(scpPath))
|
||||
{
|
||||
int idx = path.lastIndexOf('.');
|
||||
return path.substring(scpPath.length() + 1, idx);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public ScriptContext getScriptContext(ScriptEngine engine)
|
||||
{
|
||||
return engine.getContext();
|
||||
}
|
||||
|
||||
public ScriptContext getScriptContext(String engineName)
|
||||
{
|
||||
ScriptEngine engine = getEngineByName(engineName);
|
||||
if (engine == null)
|
||||
{
|
||||
throw new IllegalStateException("No engine registered with name (" + engineName + ")");
|
||||
}
|
||||
return getScriptContext(engine);
|
||||
}
|
||||
|
||||
public Object eval(ScriptEngine engine, String script, ScriptContext context) throws ScriptException
|
||||
{
|
||||
if ((engine instanceof Compilable) && ATTEMPT_COMPILATION)
|
||||
{
|
||||
Compilable eng = (Compilable) engine;
|
||||
CompiledScript cs = eng.compile(script);
|
||||
return context != null ? cs.eval(context) : cs.eval();
|
||||
}
|
||||
return context != null ? engine.eval(script, context) : engine.eval(script);
|
||||
}
|
||||
|
||||
public Object eval(String engineName, String script) throws ScriptException
|
||||
{
|
||||
return this.eval(engineName, script, null);
|
||||
}
|
||||
|
||||
public Object eval(String engineName, String script, ScriptContext context) throws ScriptException
|
||||
{
|
||||
ScriptEngine engine = getEngineByName(engineName);
|
||||
if (engine == null)
|
||||
{
|
||||
throw new ScriptException("No engine registered with name (" + engineName + ")");
|
||||
}
|
||||
return eval(engine, script, context);
|
||||
}
|
||||
|
||||
public Object eval(ScriptEngine engine, String script) throws ScriptException
|
||||
{
|
||||
return eval(engine, script, null);
|
||||
}
|
||||
|
||||
public void reportScriptFileError(File script, ScriptException e)
|
||||
{
|
||||
String dir = script.getParent();
|
||||
String name = script.getName() + ".error.log";
|
||||
if (dir != null)
|
||||
{
|
||||
File file = new File(dir + "/" + name);
|
||||
if (!file.exists())
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
file.createNewFile();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
try (FileOutputStream fos = new FileOutputStream(file))
|
||||
{
|
||||
String errorHeader = "Error on: " + file.getCanonicalPath() + "\r\nLine: " + e.getLineNumber() + " - Column: " + e.getColumnNumber() + "\r\n\r\n";
|
||||
fos.write(errorHeader.getBytes());
|
||||
fos.write(e.getMessage().getBytes());
|
||||
_log.warning("Failed executing script: " + script.getAbsolutePath() + ". See " + file.getName() + " for details.");
|
||||
}
|
||||
catch (IOException ioe)
|
||||
{
|
||||
_log.log(Level.WARNING, "Failed executing script: " + script.getAbsolutePath() + "\r\n" + e.getMessage() + "Additionally failed when trying to write an error report on script directory. Reason: " + ioe.getMessage(), ioe);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_log.log(Level.WARNING, "Failed executing script: " + script.getAbsolutePath() + "\r\n" + e.getMessage() + "Additionally failed when trying to write an error report on script directory.", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void registerScriptManager(ScriptManager<?> manager)
|
||||
{
|
||||
_scriptManagers.add(manager);
|
||||
}
|
||||
|
||||
public void removeScriptManager(ScriptManager<?> manager)
|
||||
{
|
||||
_scriptManagers.remove(manager);
|
||||
}
|
||||
|
||||
public List<ScriptManager<?>> getScriptManagers()
|
||||
{
|
||||
return _scriptManagers;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param currentLoadingScript The currentLoadingScript to set.
|
||||
*/
|
||||
protected void setCurrentLoadingScript(File currentLoadingScript)
|
||||
{
|
||||
_currentLoadingScript = currentLoadingScript;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the currentLoadingScript.
|
||||
*/
|
||||
protected File getCurrentLoadingScript()
|
||||
{
|
||||
return _currentLoadingScript;
|
||||
}
|
||||
|
||||
@SuppressWarnings("synthetic-access")
|
||||
private static class SingletonHolder
|
||||
{
|
||||
protected static final L2ScriptEngineManager _instance = new L2ScriptEngineManager();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* 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 com.l2jserver.gameserver.scripting;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
|
||||
import javax.script.ScriptException;
|
||||
|
||||
/**
|
||||
* Abstract class for classes that are meant to be implemented by scripts.<BR>
|
||||
* @author KenM
|
||||
*/
|
||||
public abstract class ManagedScript
|
||||
{
|
||||
private final File _scriptFile;
|
||||
private long _lastLoadTime;
|
||||
private boolean _isActive;
|
||||
|
||||
public ManagedScript()
|
||||
{
|
||||
_scriptFile = L2ScriptEngineManager.getInstance().getCurrentLoadingScript();
|
||||
setLastLoadTime(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to reload this script and to refresh the necessary bindings with it ScriptControler.<BR>
|
||||
* Subclasses of this class should override this method to properly refresh their bindings when necessary.
|
||||
* @return true if and only if the scrip was reloaded, false otherwise.
|
||||
*/
|
||||
public boolean reload()
|
||||
{
|
||||
try
|
||||
{
|
||||
L2ScriptEngineManager.getInstance().executeScript(getScriptFile());
|
||||
return true;
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
catch (ScriptException e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract boolean unload();
|
||||
|
||||
public void setActive(boolean status)
|
||||
{
|
||||
_isActive = status;
|
||||
}
|
||||
|
||||
public boolean isActive()
|
||||
{
|
||||
return _isActive;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the scriptFile.
|
||||
*/
|
||||
public File getScriptFile()
|
||||
{
|
||||
return _scriptFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param lastLoadTime The lastLoadTime to set.
|
||||
*/
|
||||
protected void setLastLoadTime(long lastLoadTime)
|
||||
{
|
||||
_lastLoadTime = lastLoadTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the lastLoadTime.
|
||||
*/
|
||||
protected long getLastLoadTime()
|
||||
{
|
||||
return _lastLoadTime;
|
||||
}
|
||||
|
||||
public abstract String getScriptName();
|
||||
|
||||
public abstract ScriptManager<?> getScriptManager();
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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 com.l2jserver.gameserver.scripting;
|
||||
|
||||
/**
|
||||
* @author KenM
|
||||
*/
|
||||
public abstract class ScriptManager<S extends ManagedScript>
|
||||
{
|
||||
public abstract Iterable<S> getAllManagedScripts();
|
||||
|
||||
public boolean reload(S ms)
|
||||
{
|
||||
return ms.reload();
|
||||
}
|
||||
|
||||
public boolean unload(S ms)
|
||||
{
|
||||
return ms.unload();
|
||||
}
|
||||
|
||||
public void setActive(S ms, boolean status)
|
||||
{
|
||||
ms.setActive(status);
|
||||
}
|
||||
|
||||
public abstract String getScriptManagerName();
|
||||
}
|
||||
Reference in New Issue
Block a user