diff --git a/.classpath b/.classpath index 4186b9f3d..87d14bd1a 100644 --- a/.classpath +++ b/.classpath @@ -4,8 +4,9 @@ - - + + + diff --git a/data/script/script/DummyScript.java b/data/script/script/DummyScript.java deleted file mode 100644 index 00b3078e9..000000000 --- a/data/script/script/DummyScript.java +++ /dev/null @@ -1,24 +0,0 @@ -package script; - -import com.l2jserver.model.world.capability.Scriptable; -import com.l2jserver.service.game.scripting.Script; - -public class DummyScript implements Script { - @Override - public void load(Scriptable object) { - } - - @Override - public void run() { - - } - - @Override - public void unload() { - } - - @Override - public Scriptable getObject() { - return null; - } -} diff --git a/data/script/template/script/template/DisabledTemplate.java b/data/script/template/script/template/DisabledTemplate.java new file mode 100644 index 000000000..4d6693097 --- /dev/null +++ b/data/script/template/script/template/DisabledTemplate.java @@ -0,0 +1,21 @@ +package script.template; + + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Documented; +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; + + +/** + * Marker annotation that is used to mark disabled DAO's so they will be ignored by {@link TemplateLoader} + * + * @author SoulKeeper + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface DisabledTemplate +{ +} diff --git a/data/script/template/script/template/TemplateLoader.java b/data/script/template/script/template/TemplateLoader.java new file mode 100644 index 000000000..6b80d7d77 --- /dev/null +++ b/data/script/template/script/template/TemplateLoader.java @@ -0,0 +1,86 @@ +package script.template;/* + * This file is part of aion-emu . + * + * 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 . + */ + +import java.lang.reflect.Modifier; +import java.util.Set; + +import com.google.inject.Inject; +import com.l2jserver.model.template.Template; +import com.l2jserver.service.game.scripting.classlistener.Loader; +import com.l2jserver.service.game.scripting.classlistener.Unloader; +import com.l2jserver.service.game.template.StaticTemplateService; +import com.l2jserver.service.game.template.TemplateService; +import com.l2jserver.util.ClassUtils; +import com.l2jserver.util.factory.CollectionFactory; + +/** + * Utility class that loads all Template's in classPath of this script context.
+ * Template should be public, not abstract, not interface, must have default + * no-arg public constructor. + * + * @author Rogiel + */ +public class TemplateLoader implements Loader, Unloader { + private final StaticTemplateService templateService; + + @Inject + public TemplateLoader(TemplateService templateService) { + this.templateService = (StaticTemplateService) templateService; + } + + @Override + public void load(Class[] classes) { + for (final Class template : getSuitableClasses(classes)) { + templateService.addTemplate(template); + System.out.println("Loading template: " + template); + } + } + + @Override + public void unload(Class[] classes) { + for (final Class template : getSuitableClasses(classes)) { + System.out.println("Unloading template: " + template); + } + } + + /** + * Returns list of suitable Template classes to load/unload + * + * @return list of Template classes to load/unload + */ + @SuppressWarnings({ "unchecked" }) + private static Set> getSuitableClasses( + Class[] classes) { + final Set> suitable = CollectionFactory + .newSet(null); + for (Class clazz : classes) { + if (!ClassUtils.isSubclass(clazz, Template.class)) + continue; + if (Modifier.isAbstract(clazz.getModifiers()) + || Modifier.isInterface(clazz.getModifiers())) + continue; + if (!Modifier.isPublic(clazz.getModifiers())) + continue; + if (clazz.isAnnotationPresent(DisabledTemplate.class)) + continue; + + suitable.add((Class) clazz); + } + + return suitable; + } +} diff --git a/data/template/script/template/armor/AbstractGradeAArmorTemplate.java b/data/script/template/script/template/armor/AbstractGradeAArmorTemplate.java similarity index 100% rename from data/template/script/template/armor/AbstractGradeAArmorTemplate.java rename to data/script/template/script/template/armor/AbstractGradeAArmorTemplate.java diff --git a/data/template/script/template/armor/AbstractNoGradeArmorTemplate.java b/data/script/template/script/template/armor/AbstractNoGradeArmorTemplate.java similarity index 100% rename from data/template/script/template/armor/AbstractNoGradeArmorTemplate.java rename to data/script/template/script/template/armor/AbstractNoGradeArmorTemplate.java diff --git a/data/template/script/template/armor/Dummy2ArmorTemplate.java b/data/script/template/script/template/armor/Dummy2ArmorTemplate.java similarity index 100% rename from data/template/script/template/armor/Dummy2ArmorTemplate.java rename to data/script/template/script/template/armor/Dummy2ArmorTemplate.java diff --git a/data/template/script/template/armor/DummyArmorTemplate.java b/data/script/template/script/template/armor/DummyArmorTemplate.java similarity index 100% rename from data/template/script/template/armor/DummyArmorTemplate.java rename to data/script/template/script/template/armor/DummyArmorTemplate.java diff --git a/data/template/script/template/item/AdenaItemTemplate.java b/data/script/template/script/template/item/AdenaItemTemplate.java similarity index 100% rename from data/template/script/template/item/AdenaItemTemplate.java rename to data/script/template/script/template/item/AdenaItemTemplate.java diff --git a/data/template/script/template/item/TestPotionTemplate.java b/data/script/template/script/template/item/TestPotionTemplate.java similarity index 100% rename from data/template/script/template/item/TestPotionTemplate.java rename to data/script/template/script/template/item/TestPotionTemplate.java diff --git a/data/template/script/template/skill/TestSkillTemplate.java b/data/script/template/script/template/skill/TestSkillTemplate.java similarity index 100% rename from data/template/script/template/skill/TestSkillTemplate.java rename to data/script/template/script/template/skill/TestSkillTemplate.java diff --git a/data/template/script/template/weapon/TestWeaponTemplate.java b/data/script/template/script/template/weapon/TestWeaponTemplate.java similarity index 100% rename from data/template/script/template/weapon/TestWeaponTemplate.java rename to data/script/template/script/template/weapon/TestWeaponTemplate.java diff --git a/data/script/template/template.xml b/data/script/template/template.xml new file mode 100644 index 000000000..da257b7b7 --- /dev/null +++ b/data/script/template/template.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/src/dao/mysql5/script/dao/mysql5/DAOModuleMySQL5.java b/src/dao/mysql5/com/l2jserver/db/dao/DAOModuleMySQL5.java similarity index 75% rename from src/dao/mysql5/script/dao/mysql5/DAOModuleMySQL5.java rename to src/dao/mysql5/com/l2jserver/db/dao/DAOModuleMySQL5.java index 2b9e9d432..6e5bc459a 100644 --- a/src/dao/mysql5/script/dao/mysql5/DAOModuleMySQL5.java +++ b/src/dao/mysql5/com/l2jserver/db/dao/DAOModuleMySQL5.java @@ -1,9 +1,11 @@ -package script.dao.mysql5; +package com.l2jserver.db.dao; import com.google.inject.AbstractModule; import com.google.inject.Scopes; import com.l2jserver.db.dao.CharacterDAO; import com.l2jserver.db.dao.ItemDAO; +import com.l2jserver.db.dao.mysql5.MySQL5CharacterDAO; +import com.l2jserver.db.dao.mysql5.MySQL5ItemDAO; public class DAOModuleMySQL5 extends AbstractModule { @Override diff --git a/src/dao/mysql5/script/dao/mysql5/AbstractMySQL5DAO.java b/src/dao/mysql5/com/l2jserver/db/dao/mysql5/AbstractMySQL5DAO.java similarity index 92% rename from src/dao/mysql5/script/dao/mysql5/AbstractMySQL5DAO.java rename to src/dao/mysql5/com/l2jserver/db/dao/mysql5/AbstractMySQL5DAO.java index 45776430d..a3cf638bc 100644 --- a/src/dao/mysql5/script/dao/mysql5/AbstractMySQL5DAO.java +++ b/src/dao/mysql5/com/l2jserver/db/dao/mysql5/AbstractMySQL5DAO.java @@ -1,4 +1,4 @@ -package script.dao.mysql5; +package com.l2jserver.db.dao.mysql5; import com.google.inject.Inject; import com.l2jserver.service.database.AbstractDAO; diff --git a/src/dao/mysql5/script/dao/mysql5/MySQL5CharacterDAO.java b/src/dao/mysql5/com/l2jserver/db/dao/mysql5/MySQL5CharacterDAO.java similarity index 98% rename from src/dao/mysql5/script/dao/mysql5/MySQL5CharacterDAO.java rename to src/dao/mysql5/com/l2jserver/db/dao/mysql5/MySQL5CharacterDAO.java index 85890dd89..dc123a810 100644 --- a/src/dao/mysql5/script/dao/mysql5/MySQL5CharacterDAO.java +++ b/src/dao/mysql5/com/l2jserver/db/dao/mysql5/MySQL5CharacterDAO.java @@ -1,4 +1,4 @@ -package script.dao.mysql5; +package com.l2jserver.db.dao.mysql5; import java.sql.PreparedStatement; import java.sql.ResultSet; diff --git a/src/dao/mysql5/script/dao/mysql5/MySQL5ItemDAO.java b/src/dao/mysql5/com/l2jserver/db/dao/mysql5/MySQL5ItemDAO.java similarity index 98% rename from src/dao/mysql5/script/dao/mysql5/MySQL5ItemDAO.java rename to src/dao/mysql5/com/l2jserver/db/dao/mysql5/MySQL5ItemDAO.java index d4cf1ac68..ddc1aed1f 100644 --- a/src/dao/mysql5/script/dao/mysql5/MySQL5ItemDAO.java +++ b/src/dao/mysql5/com/l2jserver/db/dao/mysql5/MySQL5ItemDAO.java @@ -1,4 +1,4 @@ -package script.dao.mysql5; +package com.l2jserver.db.dao.mysql5; import java.sql.PreparedStatement; import java.sql.ResultSet; diff --git a/src/dao/mysql5/mysql5.xml b/src/dao/mysql5/mysql5.xml new file mode 100644 index 000000000..961c08bbe --- /dev/null +++ b/src/dao/mysql5/mysql5.xml @@ -0,0 +1,16 @@ + + + + + + + \ No newline at end of file diff --git a/src/main/java/com/l2jserver/GameServerModule.java b/src/main/java/com/l2jserver/GameServerModule.java index 7a9439c9c..18b345d7e 100644 --- a/src/main/java/com/l2jserver/GameServerModule.java +++ b/src/main/java/com/l2jserver/GameServerModule.java @@ -1,8 +1,8 @@ package com.l2jserver; -import script.dao.mysql5.DAOModuleMySQL5; import com.google.inject.AbstractModule; +import com.l2jserver.db.dao.DAOModuleMySQL5; import com.l2jserver.model.id.factory.IDFactoryModule; import com.l2jserver.routines.GameServerInitializationRoutine; import com.l2jserver.service.BasicServiceModule; diff --git a/src/main/java/com/l2jserver/model/template/AbstractTemplate.java b/src/main/java/com/l2jserver/model/template/AbstractTemplate.java index d065b8acf..721bd0202 100644 --- a/src/main/java/com/l2jserver/model/template/AbstractTemplate.java +++ b/src/main/java/com/l2jserver/model/template/AbstractTemplate.java @@ -2,7 +2,7 @@ package com.l2jserver.model.template; import com.l2jserver.model.id.TemplateID; -public class AbstractTemplate { +public class AbstractTemplate implements Template { private final TemplateID id; public AbstractTemplate(TemplateID id) { @@ -10,7 +10,8 @@ public class AbstractTemplate { this.id = id; } - public TemplateID getId() { + @Override + public TemplateID getID() { return id; } } diff --git a/src/main/java/com/l2jserver/model/template/Template.java b/src/main/java/com/l2jserver/model/template/Template.java new file mode 100644 index 000000000..650b379c1 --- /dev/null +++ b/src/main/java/com/l2jserver/model/template/Template.java @@ -0,0 +1,7 @@ +package com.l2jserver.model.template; + +import com.l2jserver.model.id.TemplateID; + +public interface Template { + TemplateID getID(); +} diff --git a/src/main/java/com/l2jserver/service/cache/SimpleCacheService.java b/src/main/java/com/l2jserver/service/cache/SimpleCacheService.java index 98c18d5aa..a5275517d 100644 --- a/src/main/java/com/l2jserver/service/cache/SimpleCacheService.java +++ b/src/main/java/com/l2jserver/service/cache/SimpleCacheService.java @@ -6,20 +6,13 @@ import java.lang.reflect.Proxy; import java.util.Arrays; import java.util.Map; -import com.l2jserver.service.ServiceStartException; -import com.l2jserver.service.ServiceStopException; +import com.l2jserver.service.AbstractService; import com.l2jserver.util.factory.CollectionFactory; -public class SimpleCacheService implements CacheService { +public class SimpleCacheService extends AbstractService implements CacheService { private final Map cache = CollectionFactory .newWeakMap(MethodInvocation.class, Object.class); - @Override - public void start() throws ServiceStartException { - // TODO Auto-generated method stub - - } - @Override public T decorate(final Class interfaceType, final T instance) { @@ -47,12 +40,6 @@ public class SimpleCacheService implements CacheService { return proxy; } - @Override - public void stop() throws ServiceStopException { - // TODO Auto-generated method stub - - } - private class MethodInvocation { private final Method method; private final Object[] args; diff --git a/src/main/java/com/l2jserver/service/game/scripting/ScriptContext.java b/src/main/java/com/l2jserver/service/game/scripting/ScriptContext.java index 66669d87e..29261d48f 100644 --- a/src/main/java/com/l2jserver/service/game/scripting/ScriptContext.java +++ b/src/main/java/com/l2jserver/service/game/scripting/ScriptContext.java @@ -22,8 +22,8 @@ import java.util.Collection; import com.l2jserver.service.game.scripting.classlistener.ClassListener; import com.l2jserver.service.game.scripting.classlistener.DefaultClassListener; -import com.l2jserver.service.game.scripting.metadata.OnClassLoad; -import com.l2jserver.service.game.scripting.metadata.OnClassUnload; +import com.l2jserver.service.game.scripting.classlistener.Loader; +import com.l2jserver.service.game.scripting.classlistener.Unloader; /** * This class represents script context that can be loaded, unloaded, etc...
@@ -33,15 +33,15 @@ import com.l2jserver.service.game.scripting.metadata.OnClassUnload; public interface ScriptContext { /** * Initializes script context. Calls the compilation task.
- * After compilation static methods marked with {@link OnClassLoad} are - * invoked + * After compilation classes implementing with {@link Loader#load(Class[])} + * are invoked */ void init(); /** * Notifies all script classes that they must save their data and release - * resources to prevent memory leaks. It's done via static methods with - * {@link OnClassUnload} annotation + * resources to prevent memory leaks. It's done via classes implementing + * with {@link Unloader#unload(Class[])} */ void shutdown(); @@ -148,6 +148,13 @@ public interface ScriptContext { */ String getCompilerClassName(); + /** + * Returns script class loader + * + * @return the class loader used in this script context + */ + ScriptClassLoader getClassLoader(); + /** * Tests if this ScriptContext is equal to another ScriptContext. * Comparation is done by comparing root files and parent contexts (if there diff --git a/src/main/java/com/l2jserver/service/game/scripting/ScriptContextFactory.java b/src/main/java/com/l2jserver/service/game/scripting/ScriptContextFactory.java deleted file mode 100644 index 925271ebd..000000000 --- a/src/main/java/com/l2jserver/service/game/scripting/ScriptContextFactory.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * This file is part of l2jserver . - * - * l2jserver 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. - * - * l2jserver 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 l2jserver. If not, see . - */ - -package com.l2jserver.service.game.scripting; - -import java.io.File; - -import com.l2jserver.service.game.scripting.impl.ScriptContextImpl; - -/** - * This class is script context provider. We can switch to any other - * ScriptContext implementation later, so it's good to have factory class - * - * @author Rogiel - */ -public final class ScriptContextFactory { - public static ScriptContext getScriptContext(File root, ScriptContext parent) - throws InstantiationException { - ScriptContextImpl ctx; - if (parent == null) { - ctx = new ScriptContextImpl(root); - } else { - ctx = new ScriptContextImpl(root, parent); - parent.addChildScriptContext(ctx); - } - return ctx; - } -} diff --git a/src/main/java/com/l2jserver/service/game/scripting/ScriptingService.java b/src/main/java/com/l2jserver/service/game/scripting/ScriptingService.java index 59ecd6706..b65ee37fd 100644 --- a/src/main/java/com/l2jserver/service/game/scripting/ScriptingService.java +++ b/src/main/java/com/l2jserver/service/game/scripting/ScriptingService.java @@ -1,22 +1,37 @@ package com.l2jserver.service.game.scripting; import java.io.File; +import java.util.Collection; +import java.util.List; import com.l2jserver.service.Service; +/** + * This service is capable of loading raw .java files, compile them and add to + * runtime. + * + * @author Rogiel + */ public interface ScriptingService extends Service { /** - * Creates script context, sets the root context. Adds child context if - * needed + * Loads script contexes from descriptor * - * @param root - * file that will be threated as root for compiler - * @param parent - * parent of new ScriptContext - * @return ScriptContext with presetted root file - * @throws InstantiationException - * if java compiler is not aviable + * @param scriptDescriptor + * xml file that describes contexes + * @throws Exception + * if can't load file */ - ScriptContext getScriptContext(File root, ScriptContext parent) - throws InstantiationException; + List load(File scriptDescriptor) throws Exception; + + /** + * Returns unmodifiable set with script contexes + * + * @return unmodifiable set of script contexes + */ + Collection getScriptContexts(); + + /** + * Reloads all contexes + */ + void reload(); } diff --git a/src/main/java/com/l2jserver/service/game/scripting/ScriptingServiceImpl.java b/src/main/java/com/l2jserver/service/game/scripting/ScriptingServiceImpl.java index 9643b73a8..b9e108a6a 100644 --- a/src/main/java/com/l2jserver/service/game/scripting/ScriptingServiceImpl.java +++ b/src/main/java/com/l2jserver/service/game/scripting/ScriptingServiceImpl.java @@ -1,32 +1,158 @@ package com.l2jserver.service.game.scripting; import java.io.File; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.Unmarshaller; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.inject.Inject; +import com.google.inject.Injector; +import com.l2jserver.service.AbstractService; import com.l2jserver.service.ServiceStartException; import com.l2jserver.service.ServiceStopException; import com.l2jserver.service.game.scripting.impl.ScriptContextImpl; +import com.l2jserver.service.game.scripting.scriptmanager.ScriptInfo; +import com.l2jserver.service.game.scripting.scriptmanager.ScriptList; +import com.l2jserver.util.factory.CollectionFactory; -public class ScriptingServiceImpl implements ScriptingService { - @Override - public void start() throws ServiceStartException { - +public class ScriptingServiceImpl extends AbstractService implements + ScriptingService { + /** + * Logger for script context + */ + private static final Logger log = LoggerFactory + .getLogger(ScriptingServiceImpl.class); + + private final Injector injector; + + /** + * Collection of script contexts + */ + private final Set contexts = new HashSet(); + + @Inject + public ScriptingServiceImpl(Injector injector) { + this.injector = injector; } @Override - public ScriptContext getScriptContext(File root, ScriptContext parent) + public void start() throws ServiceStartException { + for (ScriptContext context : contexts) { + context.shutdown(); + } + } + + /** + * Loads script contexes from descriptor + * + * @param scriptDescriptor + * xml file that describes contexes + * @throws Exception + * if can't load file + */ + @Override + public synchronized List load(File scriptDescriptor) + throws Exception { + final JAXBContext c = JAXBContext.newInstance(ScriptInfo.class, + ScriptList.class); + final Unmarshaller u = c.createUnmarshaller(); + final ScriptList list = (ScriptList) u.unmarshal(scriptDescriptor); + + final List contexts = CollectionFactory + .newList(ScriptContext.class); + + for (ScriptInfo si : list.getScriptInfos()) { + final ScriptContext context = createContext(si, null); + if (context != null) { + this.contexts.add(context); + context.init(); + contexts.add(context); + } + } + return contexts; + } + + /** + * 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 + */ + private ScriptContext createContext(ScriptInfo si, ScriptContext parent) + throws Exception { + ScriptContext context = 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); + } + } + + return context; + } + + @Override + public synchronized Collection getScriptContexts() { + return Collections.unmodifiableSet(contexts); + } + + /** + * Creates script context, sets the root context. Adds child context if + * needed + * + * @param root + * file that will be threated as root for compiler + * @param parent + * parent of new ScriptContext + * @return ScriptContext with presetted root file + * @throws InstantiationException + * if java compiler is not aviable + */ + private ScriptContext getScriptContext(File root, ScriptContext parent) throws InstantiationException { ScriptContextImpl ctx; if (parent == null) { - ctx = new ScriptContextImpl(root); + ctx = new ScriptContextImpl(injector, root); } else { - ctx = new ScriptContextImpl(root, parent); + ctx = new ScriptContextImpl(injector, root, parent); parent.addChildScriptContext(ctx); } return ctx; } + @Override + public void reload() { + for (ScriptContext context : contexts) { + context.reload(); + } + } + @Override public void stop() throws ServiceStopException { - + for (ScriptContext context : contexts) { + context.shutdown(); + } + contexts.clear(); } } diff --git a/src/main/java/com/l2jserver/service/game/scripting/classlistener/DefaultClassListener.java b/src/main/java/com/l2jserver/service/game/scripting/classlistener/DefaultClassListener.java index 792b4f6ee..ae10326e2 100644 --- a/src/main/java/com/l2jserver/service/game/scripting/classlistener/DefaultClassListener.java +++ b/src/main/java/com/l2jserver/service/game/scripting/classlistener/DefaultClassListener.java @@ -17,72 +17,64 @@ package com.l2jserver.service.game.scripting.classlistener; -import java.lang.annotation.Annotation; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.l2jserver.service.game.scripting.metadata.OnClassLoad; -import com.l2jserver.service.game.scripting.metadata.OnClassUnload; +import com.google.inject.Injector; +import com.l2jserver.util.ClassUtils; /** * @author Rogiel */ public class DefaultClassListener implements ClassListener { + private final Injector injector; - private static final Logger log = LoggerFactory - .getLogger(DefaultClassListener.class); + public DefaultClassListener(Injector injector) { + this.injector = injector; + } @Override public void postLoad(Class... classes) { - for (Class c : classes) { - doMethodInvoke(c.getDeclaredMethods(), OnClassLoad.class); - } + doMethodInvokeLoad(classes); } @Override public void preUnload(Class... classes) { - for (Class c : classes) { - doMethodInvoke(c.getDeclaredMethods(), OnClassUnload.class); + doMethodInvokeUnload(classes); + } + + /** + * Actually invokes method where given interface class is present. + * + * @param classes + * Classes to scan for interface + */ + private void doMethodInvokeLoad(Class[] classes) { + for (final Class clazz : classes) { + if (!ClassUtils.isSubclass(clazz, Loader.class)) + continue; + if (Modifier.isAbstract(clazz.getModifiers()) + || Modifier.isInterface(clazz.getModifiers())) + continue; + final Loader loader = (Loader) injector.getInstance(clazz); + loader.load(classes); } } /** - * Actually invokes method where given annotation class is present. Only - * static methods can be invoked + * Actually invokes method where given interface class is present. * - * @param methods - * Methods to scan for annotations - * @param annotationClass - * class of annotation to search for + * @param classes + * Classes to scan for interface */ - static void doMethodInvoke(Method[] methods, - Class annotationClass) { - for (Method m : methods) { - - if (!Modifier.isStatic(m.getModifiers())) { + private void doMethodInvokeUnload(Class[] classes) { + for (final Class clazz : classes) { + if (!ClassUtils.isSubclass(clazz, Unloader.class)) continue; - } - - boolean accessible = m.isAccessible(); - m.setAccessible(true); - - if (m.getAnnotation(annotationClass) != null) { - try { - m.invoke(null); - } catch (IllegalAccessException e) { - log.error("Can't access method " + m.getName() - + " of class " + m.getDeclaringClass().getName(), e); - } catch (InvocationTargetException e) { - log.error("Can't invoke method " + m.getName() - + " of class " + m.getDeclaringClass().getName(), e); - } - } - - m.setAccessible(accessible); + if (Modifier.isAbstract(clazz.getModifiers()) + || Modifier.isInterface(clazz.getModifiers())) + continue; + final Unloader unloader = (Unloader) injector.getInstance(clazz); + unloader.unload(classes); } } } diff --git a/src/main/java/com/l2jserver/service/game/scripting/classlistener/Loader.java b/src/main/java/com/l2jserver/service/game/scripting/classlistener/Loader.java new file mode 100644 index 000000000..8a21e0840 --- /dev/null +++ b/src/main/java/com/l2jserver/service/game/scripting/classlistener/Loader.java @@ -0,0 +1,5 @@ +package com.l2jserver.service.game.scripting.classlistener; + +public interface Loader { + void load(Class[] classes); +} diff --git a/src/main/java/com/l2jserver/service/game/scripting/classlistener/Unloader.java b/src/main/java/com/l2jserver/service/game/scripting/classlistener/Unloader.java new file mode 100644 index 000000000..4d4ee7e51 --- /dev/null +++ b/src/main/java/com/l2jserver/service/game/scripting/classlistener/Unloader.java @@ -0,0 +1,5 @@ +package com.l2jserver.service.game.scripting.classlistener; + +public interface Unloader { + void unload(Class[] classes); +} diff --git a/src/main/java/com/l2jserver/service/game/scripting/impl/ScriptContextImpl.java b/src/main/java/com/l2jserver/service/game/scripting/impl/ScriptContextImpl.java index b501b9e8f..37d47a4d8 100644 --- a/src/main/java/com/l2jserver/service/game/scripting/impl/ScriptContextImpl.java +++ b/src/main/java/com/l2jserver/service/game/scripting/impl/ScriptContextImpl.java @@ -26,7 +26,9 @@ import org.apache.commons.io.FileUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.inject.Injector; import com.l2jserver.service.game.scripting.CompilationResult; +import com.l2jserver.service.game.scripting.ScriptClassLoader; import com.l2jserver.service.game.scripting.ScriptCompiler; import com.l2jserver.service.game.scripting.ScriptContext; import com.l2jserver.service.game.scripting.classlistener.ClassListener; @@ -44,6 +46,8 @@ public class ScriptContextImpl implements ScriptContext { private static final Logger log = LoggerFactory .getLogger(ScriptContextImpl.class); + private final Injector injector; + /** * Script context that is parent for this script context */ @@ -90,8 +94,8 @@ public class ScriptContextImpl implements ScriptContext { * @throws IllegalArgumentException * if root directory doesn't exists or is not a directory */ - public ScriptContextImpl(File root) { - this(root, null); + public ScriptContextImpl(Injector injector, File root) { + this(injector, root, null); } /** @@ -108,16 +112,14 @@ public class ScriptContextImpl implements ScriptContext { * @throws IllegalArgumentException * if root directory doesn't exists or is not a directory */ - public ScriptContextImpl(File root, ScriptContext parent) { - if (root == null) { + public ScriptContextImpl(Injector injector, File root, ScriptContext parent) { + if (root == null) throw new NullPointerException("Root file must be specified"); - } - - if (!root.exists() || !root.isDirectory()) { + if (!root.exists() || !root.isDirectory()) throw new IllegalArgumentException( "Root directory not exists or is not a directory"); - } + this.injector = injector; this.root = root; this.parentScriptContext = parent; } @@ -247,7 +249,7 @@ public class ScriptContextImpl implements ScriptContext { public ClassListener getClassListener() { if (classListener == null) { if (getParentScriptContext() == null) { - setClassListener(new DefaultClassListener()); + setClassListener(new DefaultClassListener(injector)); return classListener; } else { return getParentScriptContext().getClassListener(); @@ -267,6 +269,11 @@ public class ScriptContextImpl implements ScriptContext { return this.compilerClassName; } + @Override + public ScriptClassLoader getClassLoader() { + return compilationResult.getClassLoader(); + } + /** * Creates new instance of ScriptCompiler that should be used with this * ScriptContext diff --git a/src/main/java/com/l2jserver/service/game/scripting/metadata/OnClassLoad.java b/src/main/java/com/l2jserver/service/game/scripting/metadata/OnClassLoad.java deleted file mode 100644 index 674bb3b18..000000000 --- a/src/main/java/com/l2jserver/service/game/scripting/metadata/OnClassLoad.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * This file is part of l2jserver . - * - * l2jserver 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. - * - * l2jserver 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 l2jserver. If not, see . - */ - -package com.l2jserver.service.game.scripting.metadata; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import com.l2jserver.service.game.scripting.ScriptContext; -import com.l2jserver.service.game.scripting.classlistener.DefaultClassListener; - -/** - * Method marked as {@link OnClassLoad} will be called when class was loaded by - * script.
- * It's more useful alternative for - * - *
- * static {
- * 	...
- * }
- * 
- * - * block.
- *
- * Only static methods with no arguments can be marked with this annotation.
- * - * This is only used if - * {@link ScriptContext#getClassListener()} - * returns - * {@link DefaultClassListener} - * instance. - * - * @author Rogiel - */ -@Documented -@Target(ElementType.METHOD) -@Retention(RetentionPolicy.RUNTIME) -public @interface OnClassLoad { -} diff --git a/src/main/java/com/l2jserver/service/game/scripting/metadata/OnClassUnload.java b/src/main/java/com/l2jserver/service/game/scripting/metadata/OnClassUnload.java deleted file mode 100644 index a8547b964..000000000 --- a/src/main/java/com/l2jserver/service/game/scripting/metadata/OnClassUnload.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * This file is part of l2jserver . - * - * l2jserver 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. - * - * l2jserver 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 l2jserver. If not, see . - */ - -package com.l2jserver.service.game.scripting.metadata; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import com.l2jserver.service.game.scripting.ScriptContext; -import com.l2jserver.service.game.scripting.classlistener.DefaultClassListener; - -/** - * Method marked as {@link OnClassUnload} will be called when there is a script - * reload or shutdown.
- * Only static methods with no arguments can be marked with this annotation.
- * - * This is only used if - * {@link ScriptContext#getClassListener()} - * returns - * {@link DefaultClassListener} - * instance. - * - * @author Rogiel - */ -@Documented -@Target(ElementType.METHOD) -@Retention(RetentionPolicy.RUNTIME) -public @interface OnClassUnload { -} diff --git a/src/main/java/com/l2jserver/service/game/scripting/scriptmanager/ScriptManager.java b/src/main/java/com/l2jserver/service/game/scripting/scriptmanager/ScriptManager.java deleted file mode 100644 index bd0cd29e9..000000000 --- a/src/main/java/com/l2jserver/service/game/scripting/scriptmanager/ScriptManager.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * This file is part of l2jserver . - * - * l2jserver 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. - * - * l2jserver 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 l2jserver. If not, see . - */ - -package com.l2jserver.service.game.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.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.l2jserver.service.game.scripting.ScriptContext; -import com.l2jserver.service.game.scripting.ScriptContextFactory; - -/** - * 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. - * - * Example: - * - *
- *      ScriptManager sm = new ScriptManager();
- *      sm.load(new File("st/contexts.xml"));
- *      ...
- *      sm.shutdown();
- * 
- * - * @author Rogiel - */ -public class ScriptManager { - /** - * Logger for script context - */ - private static final Logger log = LoggerFactory - .getLogger(ScriptManager.class); - - /** - * Collection of script contexts - */ - private Set contexts = new HashSet(); - - /** - * 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 - */ - private 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); - } - } - - return context; - } - - /** - * Initializes shutdown on all contexes - */ - public synchronized void shutdown() { - for (ScriptContext context : contexts) { - context.shutdown(); - } - - contexts.clear(); - } - - /** - * Reloads all contexes - */ - public synchronized void reload() { - for (ScriptContext context : contexts) { - context.reload(); - } - } - - /** - * Returns unmodifiable set with script contexes - * - * @return unmodifiable set of script contexes - */ - public synchronized Collection getScriptContexts() { - return Collections.unmodifiableSet(contexts); - } -} diff --git a/src/main/java/com/l2jserver/service/game/template/StaticTemplateService.java b/src/main/java/com/l2jserver/service/game/template/StaticTemplateService.java new file mode 100644 index 000000000..82b5cf2f7 --- /dev/null +++ b/src/main/java/com/l2jserver/service/game/template/StaticTemplateService.java @@ -0,0 +1,80 @@ +package com.l2jserver.service.game.template; + +import java.util.Map; + +import com.google.inject.Inject; +import com.google.inject.Injector; +import com.l2jserver.model.id.TemplateID; +import com.l2jserver.model.template.Template; +import com.l2jserver.service.AbstractService; +import com.l2jserver.service.ServiceStartException; +import com.l2jserver.service.ServiceStopException; +import com.l2jserver.service.configuration.ConfigurationService; +import com.l2jserver.service.game.scripting.ScriptContext; +import com.l2jserver.service.game.scripting.ScriptingService; +import com.l2jserver.util.factory.CollectionFactory; + +public class StaticTemplateService extends AbstractService implements + TemplateService { + private final ScriptingService scriptingService; + private final StaticTemplateServiceConfiguration config; + private final Injector injector; + + private ScriptContext context; + + private Map templates = CollectionFactory.newMap( + TemplateID.class, Template.class); + + @Inject + public StaticTemplateService(ScriptingService scriptingService, + ConfigurationService configService, Injector injector) { + this.scriptingService = scriptingService; + this.injector = injector; + this.config = configService + .get(StaticTemplateServiceConfiguration.class); + } + + @Override + public void start() throws ServiceStartException { + if (context == null) { + try { + context = scriptingService.load(config.getTemplateDescriptor()) + .get(0); + } catch (Exception e) { + throw new ServiceStartException(e); + } + return; + } + if (context.isInitialized()) + context.shutdown(); + context.init(); + } + + @Override + public Template getTemplate(TemplateID id) { + return templates.get(id); + } + + public void addTemplate(Class t) { + final Template template = injector.getInstance(t); + System.out.println(template.getID() + " -> " + template); + if (template.getID() != null) + templates.put(template.getID(), template); + } + + public void removeTemplate(Template t) { + // TODO templates.remove(t); + } + + @Override + public void reload() { + context.reload(); + } + + @Override + public void stop() throws ServiceStopException { + if (context.isInitialized()) + context.shutdown(); + context = null; + } +} diff --git a/src/main/java/com/l2jserver/service/game/template/StaticTemplateServiceConfiguration.java b/src/main/java/com/l2jserver/service/game/template/StaticTemplateServiceConfiguration.java new file mode 100644 index 000000000..42f2937c1 --- /dev/null +++ b/src/main/java/com/l2jserver/service/game/template/StaticTemplateServiceConfiguration.java @@ -0,0 +1,14 @@ +package com.l2jserver.service.game.template; + +import java.io.File; + +import com.l2jserver.service.configuration.Configuration; +import com.l2jserver.service.configuration.Configuration.ConfigurationName; + +@ConfigurationName("template") +public interface StaticTemplateServiceConfiguration extends Configuration { + @ConfigurationPropertyGetter(name = "template.descriptor", defaultValue = "data/script/template/template.xml") + File getTemplateDescriptor(); + @ConfigurationPropertySetter(name = "template.descriptor") + void setTemplateDescriptor(File file); +} diff --git a/src/main/java/com/l2jserver/service/game/template/TemplateService.java b/src/main/java/com/l2jserver/service/game/template/TemplateService.java index d04b2f31f..6d7fb8bdc 100644 --- a/src/main/java/com/l2jserver/service/game/template/TemplateService.java +++ b/src/main/java/com/l2jserver/service/game/template/TemplateService.java @@ -1,7 +1,7 @@ package com.l2jserver.service.game.template; import com.l2jserver.model.id.TemplateID; -import com.l2jserver.model.template.AbstractTemplate; +import com.l2jserver.model.template.Template; import com.l2jserver.service.Service; public interface TemplateService extends Service { @@ -12,14 +12,10 @@ public interface TemplateService extends Service { * the template id * @return the template matching the id */ - AbstractTemplate getTemplate(TemplateID id); + Template getTemplate(TemplateID id); /** - * Recompile the template with id id. This can be used to reload - * the template. - * - * @param id - * the template id + * Reload the template list. */ - void recompile(TemplateID id); + void reload(); } diff --git a/src/main/java/com/l2jserver/service/game/world/WorldServiceImpl.java b/src/main/java/com/l2jserver/service/game/world/WorldServiceImpl.java index f50c2c1d5..c73972658 100644 --- a/src/main/java/com/l2jserver/service/game/world/WorldServiceImpl.java +++ b/src/main/java/com/l2jserver/service/game/world/WorldServiceImpl.java @@ -9,11 +9,12 @@ import com.l2jserver.model.world.WorldObject; import com.l2jserver.model.world.filter.WorldObjectFilter; import com.l2jserver.model.world.filter.impl.InstanceFilter; import com.l2jserver.model.world.iterator.FilterIterator; +import com.l2jserver.service.AbstractService; import com.l2jserver.service.ServiceStartException; import com.l2jserver.service.ServiceStopException; import com.l2jserver.util.factory.CollectionFactory; -public class WorldServiceImpl implements WorldService { +public class WorldServiceImpl extends AbstractService implements WorldService { private final Set objects = CollectionFactory .newSet(WorldObject.class); private final WorldEventDispatcher dispatcher; diff --git a/src/main/java/com/l2jserver/service/network/NettyNetworkService.java b/src/main/java/com/l2jserver/service/network/NettyNetworkService.java index 111cae205..6124ac02d 100644 --- a/src/main/java/com/l2jserver/service/network/NettyNetworkService.java +++ b/src/main/java/com/l2jserver/service/network/NettyNetworkService.java @@ -9,9 +9,10 @@ import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory; import com.google.inject.Inject; import com.google.inject.Injector; import com.l2jserver.game.net.Lineage2PipelineFactory; +import com.l2jserver.service.AbstractService; import com.l2jserver.service.configuration.ConfigurationService; -public class NettyNetworkService implements NetworkService { +public class NettyNetworkService extends AbstractService implements NetworkService { private final NetworkConfiguration config; private final Injector injector; private ServerBootstrap server; diff --git a/src/test/java/com/l2jserver/model/id/factory/IDFactoryTest.java b/src/test/java/com/l2jserver/model/id/factory/IDFactoryTest.java index 3d1676996..6c817727b 100644 --- a/src/test/java/com/l2jserver/model/id/factory/IDFactoryTest.java +++ b/src/test/java/com/l2jserver/model/id/factory/IDFactoryTest.java @@ -4,10 +4,10 @@ import junit.framework.Assert; import org.junit.Test; -import script.dao.mysql5.DAOModuleMySQL5; import com.google.inject.Guice; import com.google.inject.Injector; +import com.l2jserver.db.dao.DAOModuleMySQL5; import com.l2jserver.model.id.CharacterID; import com.l2jserver.model.id.ID; import com.l2jserver.model.world.L2Character; diff --git a/src/test/java/com/l2jserver/service/game/scripting/ScriptingServiceImplTest.java b/src/test/java/com/l2jserver/service/game/scripting/ScriptingServiceImplTest.java new file mode 100644 index 000000000..a492b94bb --- /dev/null +++ b/src/test/java/com/l2jserver/service/game/scripting/ScriptingServiceImplTest.java @@ -0,0 +1,44 @@ +package com.l2jserver.service.game.scripting; + +import java.io.File; +import java.util.List; + +import junit.framework.Assert; + +import org.junit.Test; + +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.Scopes; + +public class ScriptingServiceImplTest { + private final Injector injector = Guice + .createInjector(new AbstractModule() { + @Override + protected void configure() { + bind(ScriptingService.class).to(ScriptingServiceImpl.class) + .in(Scopes.SINGLETON); + } + }); + private final ScriptingService service = injector + .getInstance(ScriptingService.class); + + @Test + public void testLoading() throws Exception { + final List contexts = service.load(new File( + "src/test/resources/scripting/testcase.xml")); + Assert.assertEquals(1, contexts.size()); + } + + @Test + public void testCreatingInstance() throws Exception { + final List contexts = service.load(new File( + "src/test/resources/scripting/testcase.xml")); + Assert.assertEquals(1, contexts.size()); + final ScriptContext context = contexts.get(0); + Class clazz = context.getClassLoader().loadClass("test.ScriptingCompilerTest"); + Assert.assertNotNull(clazz); + Assert.assertEquals("ScriptingCompilerTest", clazz.getSimpleName()); + } +} diff --git a/src/test/java/com/l2jserver/service/game/template/StaticTemplateServiceTest.java b/src/test/java/com/l2jserver/service/game/template/StaticTemplateServiceTest.java new file mode 100644 index 000000000..0a9c31f66 --- /dev/null +++ b/src/test/java/com/l2jserver/service/game/template/StaticTemplateServiceTest.java @@ -0,0 +1,35 @@ +package com.l2jserver.service.game.template; + +import org.junit.Test; + +import script.template.item.AdenaItemTemplate; + +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.Scopes; +import com.l2jserver.service.BasicServiceModule; +import com.l2jserver.service.ServiceStartException; +import com.l2jserver.service.game.scripting.ScriptingService; +import com.l2jserver.service.game.scripting.ScriptingServiceImpl; + +public class StaticTemplateServiceTest { + private final Injector injector = Guice + .createInjector(new BasicServiceModule(), new AbstractModule() { + @Override + protected void configure() { + bind(ScriptingService.class).to(ScriptingServiceImpl.class) + .in(Scopes.SINGLETON); + bind(TemplateService.class).to(StaticTemplateService.class) + .in(Scopes.SINGLETON); + } + }); + private final TemplateService service = injector + .getInstance(TemplateService.class); + + @Test + public void testAdena() throws ServiceStartException { + service.start(); + System.out.println(service.getTemplate(AdenaItemTemplate.ID)); + } +} diff --git a/src/test/java/com/l2jserver/service/world/WorldEventDispatcherImplTest.java b/src/test/java/com/l2jserver/service/world/WorldEventDispatcherImplTest.java index 416f0fbad..84535d43e 100644 --- a/src/test/java/com/l2jserver/service/world/WorldEventDispatcherImplTest.java +++ b/src/test/java/com/l2jserver/service/world/WorldEventDispatcherImplTest.java @@ -7,12 +7,12 @@ import junit.framework.Assert; import org.junit.Before; import org.junit.Test; -import script.dao.mysql5.DAOModuleMySQL5; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Scopes; +import com.l2jserver.db.dao.DAOModuleMySQL5; import com.l2jserver.model.id.factory.CharacterIDFactory; import com.l2jserver.model.id.factory.IDFactoryModule; import com.l2jserver.model.id.factory.ItemIDFactory; diff --git a/src/test/resources/scripting/ScriptingCompilerTest.java b/src/test/resources/scripting/ScriptingCompilerTest.java new file mode 100644 index 000000000..4bf6a2a7b --- /dev/null +++ b/src/test/resources/scripting/ScriptingCompilerTest.java @@ -0,0 +1,4 @@ +package test; + +public class ScriptingCompilerTest { +} diff --git a/src/test/resources/scripting/testcase.xml b/src/test/resources/scripting/testcase.xml new file mode 100644 index 000000000..a54b1de9b --- /dev/null +++ b/src/test/resources/scripting/testcase.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/target/test-classes/scripting/ScriptingCompilerTest.java b/target/test-classes/scripting/ScriptingCompilerTest.java new file mode 100644 index 000000000..4bf6a2a7b --- /dev/null +++ b/target/test-classes/scripting/ScriptingCompilerTest.java @@ -0,0 +1,4 @@ +package test; + +public class ScriptingCompilerTest { +} diff --git a/target/test-classes/scripting/testcase.xml b/target/test-classes/scripting/testcase.xml new file mode 100644 index 000000000..a54b1de9b --- /dev/null +++ b/target/test-classes/scripting/testcase.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file