/* * This file is part of aion-emu <aion-emu.com>. * * aion-emu 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. * * aion-emu 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 aion-emu. If not, see <http://www.gnu.org/licenses/>. */ package com.aionemu.commons.scripting.scriptmanager; import java.io.File; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Set; import javax.xml.bind.JAXBContext; import javax.xml.bind.Unmarshaller; import org.apache.log4j.Logger; import com.aionemu.commons.callbacks.Enhancable; import com.aionemu.commons.scripting.ScriptContext; import com.aionemu.commons.scripting.ScriptContextFactory; import com.aionemu.commons.scripting.classlistener.ClassListener; import com.aionemu.commons.scripting.scriptmanager.listener.ContextCreationListener; import com.aionemu.commons.scripting.scriptmanager.listener.ContextReloadListener; import com.aionemu.commons.scripting.scriptmanager.listener.ReloadListener; /** * Class that represents managers of script contexes. It loads, reloads and unload script contexes. In the future it may * be extended to support programatic manipulation of contexes, but for now it's not needed. <br /> * Example: * * <pre> * ScriptManager sm = new ScriptManager(); * sm.load(new File("st/contexts.xml")); * ... * sm.shutdown(); * </pre> * * {@link ScriptContext} object creation listener can be added by using * {@link com.aionemu.commons.scripting.scriptmanager.listener.ContextCreationListener} {@link ScriptContext} object * reload listener can be added by using * {@link com.aionemu.commons.scripting.scriptmanager.listener.ContextReloadListener} {@link ScriptManager} reload * listener can be added by using {@link com.aionemu.commons.scripting.scriptmanager.listener.ReloadListener} * * @author SoulKeeper, Aquanox */ public class ScriptManager { /** * Logger for script context */ private static final Logger log = Logger.getLogger(ScriptManager.class); /** * Collection of script contexts */ private Set<ScriptContext> contexts = new HashSet<ScriptContext>(); /** * Global ClassListener instance. Autocatically setted for each new context. Fires after each successful * compilation. */ private ClassListener globalClassListener; /** * Loads script contexes from descriptor * * @param scriptDescriptor * xml file that describes contexes * @throws Exception * if can't load file */ public synchronized void load(File scriptDescriptor) throws Exception { JAXBContext c = JAXBContext.newInstance(ScriptInfo.class, ScriptList.class); Unmarshaller u = c.createUnmarshaller(); ScriptList list = (ScriptList) u.unmarshal(scriptDescriptor); for(ScriptInfo si : list.getScriptInfos()) { ScriptContext context = createContext(si, null); if(context != null) { contexts.add(context); context.init(); } } } /** * Creates new context and checks to not produce copies * * @param si * script context descriptor * @param parent * parent script context * @return created script context * @throws Exception * if can't create context */ @Enhancable(callback = ContextCreationListener.class) public ScriptContext createContext(ScriptInfo si, ScriptContext parent) throws Exception { ScriptContext context = ScriptContextFactory.getScriptContext(si.getRoot(), parent); context.setLibraries(si.getLibraries()); context.setCompilerClassName(si.getCompilerClass()); if(parent == null && contexts.contains(context)) { log.warn("Double root script context definition: " + si.getRoot().getAbsolutePath()); return null; } if(si.getScriptInfos() != null && !si.getScriptInfos().isEmpty()) { for(ScriptInfo child : si.getScriptInfos()) { createContext(child, context); } } if(parent == null && globalClassListener != null) context.setClassListener(globalClassListener); return context; } /** * Initializes shutdown on all contexes */ public synchronized void shutdown() { for(ScriptContext context : contexts) { context.shutdown(); } contexts.clear(); } /** * Reloads all contexes */ @Enhancable(callback = ReloadListener.class) public synchronized void reload() { for(ScriptContext context : contexts) { reloadContext(context); } } /** * Reloads specified context. * * @param ctx * Script context instance. */ @Enhancable(callback = ContextReloadListener.class) public void reloadContext(ScriptContext ctx) { ctx.reload(); } /** * Returns unmodifiable set with script contexes * * @return unmodifiable set of script contexes */ public synchronized Collection<ScriptContext> getScriptContexts() { return Collections.unmodifiableSet(contexts); } /** * Set Global class listener instance. * * @param instance * listener instance. */ public void setGlobalClassListener(ClassListener instance) { this.globalClassListener = instance; } }