/** * Copyright (C) 2013-2014 Project-Vethrfolnir * * 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.vethrfolnir.game.services; import groovy.util.GroovyScriptEngine; import java.io.File; import java.lang.reflect.Field; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import com.vethrfolnir.logging.MuLogger; import corvus.corax.config.CorvusConfig; /** * @author Vlad * * GroovyScriptEngine is basically a handler for GroovyClassLoader, we should * make our system around GroovyClassLoader than GroovyScriptEngine */ public class ScriptingService { private static final MuLogger log = MuLogger.getLogger(ScriptingService.class); public static final File ScriptDir = new File(CorvusConfig.WorkingDirectory, "system/scripts"); private final GroovyScriptEngine engine; private Field ScriptEngineRoots; public ScriptingService() { engine = new GroovyScriptEngine(getPackageURLs()); try { // so bad ScriptEngineRoots = engine.getClass().getDeclaredField("roots"); ScriptEngineRoots.setAccessible(true); } catch (Exception e) { log.warn("Failed getting Script engine roots field, new paths wont be added at runtime.", e); } log.info("Ready."); } public void loadScripts() { reparsePackages(); try { ArrayList<File> files = listScriptFiles(ScriptDir); for (int i = 0; i < files.size(); i++) { File l = files.get(i); engine.loadScriptByName(l.getName()); } engine.run("MasterScript.groovy", ""); } catch (Exception e) { log.fatal("Failed loading master script!", e); } } /** * @return the engine */ public GroovyScriptEngine getEngine() { return engine; } public void reparsePackages() { URL[] urls = getPackageURLs(); try { ScriptEngineRoots.set(engine, urls); } catch (Exception e) { log.warn("Hm..", e); } for(URL url : urls) { if(!isUsed(url)) { engine.getGroovyClassLoader().addURL(url); } } } private boolean isUsed(URL url) { URL[] usedURLS = engine.getGroovyClassLoader().getURLs(); for(URL link : usedURLS) { if(link.equals(url)) { return true; } } return false; } public static URL[] getPackageURLs() { ArrayList<File> files = listDirectories(ScriptDir); URL[] urls = new URL[files.size()]; for (int i = 0; i < urls.length; i++) { File dir = files.get(i); try { urls[i] = dir.toURI().toURL(); } catch (MalformedURLException e) { log.fatal("Failed converting[File="+dir+"] to url.", e); } } return urls; } public static ArrayList<File> listDirectories(File file) { ArrayList<File> files = new ArrayList<File>(); File[] fs = file.listFiles(); for (int i = 0; i < fs.length; i++) { File dir = fs[i]; if(dir.isDirectory()) { files.add(dir); files.addAll(listDirectories(dir)); } } return files; } private static ArrayList<File> listScriptFiles(File dir) { ArrayList<File> files = new ArrayList<File>(); File[] fs = dir.listFiles(); for (int i = 0; i < fs.length; i++) { File file = fs[i]; if(file.isDirectory()) { files.addAll(listScriptFiles(file)); } else if (file.getName().endsWith("groovy") || file.getName().endsWith("java")){ files.add(file); } } return files; } }