1
0
mirror of https://github.com/Rogiel/l2jserver2 synced 2025-12-06 07:32:46 +00:00

Change-Id: Ia0d07d075e9feeb872124348948d8664364d1c8a

This commit is contained in:
rogiel
2011-04-30 11:18:01 -03:00
parent d76e80f9a0
commit 9a6c0233e9
46 changed files with 640 additions and 430 deletions

View File

@@ -4,8 +4,9 @@
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
<classpathentry excluding="mysql5/|db4o/" kind="src" path="src/dao"/>
<classpathentry kind="src" path="src/dao/mysql5"/>
<classpathentry kind="src" path="data/script"/>
<classpathentry kind="src" path="data/template"/>
<classpathentry kind="src" path="data/script/template"/>
<classpathentry kind="src" path="data/script/quest"/>
<classpathentry kind="src" path="data/script/ai"/>
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>

View File

@@ -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<Scriptable> {
@Override
public void load(Scriptable object) {
}
@Override
public void run() {
}
@Override
public void unload() {
}
@Override
public Scriptable getObject() {
return null;
}
}

View File

@@ -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
{
}

View File

@@ -0,0 +1,86 @@
package script.template;/*
* 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/>.
*/
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.<br>
* Template should be public, not abstract, not interface, must have default
* no-arg public constructor.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
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<? extends Template> template : getSuitableClasses(classes)) {
templateService.addTemplate(template);
System.out.println("Loading template: " + template);
}
}
@Override
public void unload(Class<?>[] classes) {
for (final Class<? extends Template> 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<Class<? extends Template>> getSuitableClasses(
Class<?>[] classes) {
final Set<Class<? extends Template>> 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<? extends Template>) clazz);
}
return suitable;
}
}

View File

@@ -0,0 +1,23 @@
<?xml version='1.0' encoding='UTF-8' ?>
<!--
~ 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 <http://www.gnu.org/licenses/>.
-->
<scriptlist xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../contexts.xsd">
<scriptinfo root="./data/script/template"/>
</scriptlist>

View File

@@ -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

View File

@@ -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;

View File

@@ -1,4 +1,4 @@
package script.dao.mysql5;
package com.l2jserver.db.dao.mysql5;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

View File

@@ -1,4 +1,4 @@
package script.dao.mysql5;
package com.l2jserver.db.dao.mysql5;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

16
src/dao/mysql5/mysql5.xml Normal file
View File

@@ -0,0 +1,16 @@
<?xml version='1.0' encoding='UTF-8' ?>
<!-- ~ 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 <http://www.gnu.org/licenses/>. -->
<scriptlist xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../contexts.xsd">
<scriptinfo root="./data/scripts/system/database" />
</scriptlist>

View File

@@ -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;

View File

@@ -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;
}
}

View File

@@ -0,0 +1,7 @@
package com.l2jserver.model.template;
import com.l2jserver.model.id.TemplateID;
public interface Template {
TemplateID getID();
}

View File

@@ -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<MethodInvocation, Object> cache = CollectionFactory
.newWeakMap(MethodInvocation.class, Object.class);
@Override
public void start() throws ServiceStartException {
// TODO Auto-generated method stub
}
@Override
public <T extends Cacheable> T decorate(final Class<T> 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;

View File

@@ -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...<br>
@@ -33,15 +33,15 @@ import com.l2jserver.service.game.scripting.metadata.OnClassUnload;
public interface ScriptContext {
/**
* Initializes script context. Calls the compilation task.<br>
* 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

View File

@@ -1,42 +0,0 @@
/*
* This file is part of l2jserver <l2jserver.com>.
*
* 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 <http://www.gnu.org/licenses/>.
*/
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 <a href="http://www.rogiel.com">Rogiel</a>
*/
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;
}
}

View File

@@ -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 <a href="http://www.rogiel.com">Rogiel</a>
*/
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<ScriptContext> load(File scriptDescriptor) throws Exception;
/**
* Returns unmodifiable set with script contexes
*
* @return unmodifiable set of script contexes
*/
Collection<ScriptContext> getScriptContexts();
/**
* Reloads all contexes
*/
void reload();
}

View File

@@ -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<ScriptContext> contexts = new HashSet<ScriptContext>();
@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<ScriptContext> 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<ScriptContext> 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<ScriptContext> 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();
}
}

View File

@@ -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 <a href="http://www.rogiel.com">Rogiel</a>
*/
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<? extends Annotation> 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);
}
}
}

View File

@@ -0,0 +1,5 @@
package com.l2jserver.service.game.scripting.classlistener;
public interface Loader {
void load(Class<?>[] classes);
}

View File

@@ -0,0 +1,5 @@
package com.l2jserver.service.game.scripting.classlistener;
public interface Unloader {
void unload(Class<?>[] classes);
}

View File

@@ -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

View File

@@ -1,56 +0,0 @@
/*
* This file is part of l2jserver <l2jserver.com>.
*
* 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 <http://www.gnu.org/licenses/>.
*/
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.<br>
* It's more useful alternative for
*
* <pre>
* static {
* ...
* }
* </pre>
*
* block.<br>
* <br>
* Only static methods with no arguments can be marked with this annotation.<br>
*
* This is only used if
* {@link ScriptContext#getClassListener()}
* returns
* {@link DefaultClassListener}
* instance.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface OnClassLoad {
}

View File

@@ -1,46 +0,0 @@
/*
* This file is part of l2jserver <l2jserver.com>.
*
* 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 <http://www.gnu.org/licenses/>.
*/
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.<br>
* Only static methods with no arguments can be marked with this annotation.<br>
*
* This is only used if
* {@link ScriptContext#getClassListener()}
* returns
* {@link DefaultClassListener}
* instance.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface OnClassUnload {
}

View File

@@ -1,148 +0,0 @@
/*
* This file is part of l2jserver <l2jserver.com>.
*
* 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 <http://www.gnu.org/licenses/>.
*/
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:
*
* <pre>
* ScriptManager sm = new ScriptManager();
* sm.load(new File(&quot;st/contexts.xml&quot;));
* ...
* sm.shutdown();
* </pre>
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public class ScriptManager {
/**
* Logger for script context
*/
private static final Logger log = LoggerFactory
.getLogger(ScriptManager.class);
/**
* Collection of script contexts
*/
private Set<ScriptContext> contexts = new HashSet<ScriptContext>();
/**
* 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<ScriptContext> getScriptContexts() {
return Collections.unmodifiableSet(contexts);
}
}

View File

@@ -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<TemplateID, Template> 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<? extends Template> 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;
}
}

View File

@@ -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);
}

View File

@@ -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 <tt>id</tt>. This can be used to reload
* the template.
*
* @param id
* the template id
* Reload the template list.
*/
void recompile(TemplateID id);
void reload();
}

View File

@@ -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<WorldObject> objects = CollectionFactory
.newSet(WorldObject.class);
private final WorldEventDispatcher dispatcher;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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<ScriptContext> contexts = service.load(new File(
"src/test/resources/scripting/testcase.xml"));
Assert.assertEquals(1, contexts.size());
}
@Test
public void testCreatingInstance() throws Exception {
final List<ScriptContext> 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());
}
}

View File

@@ -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));
}
}

View File

@@ -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;

View File

@@ -0,0 +1,4 @@
package test;
public class ScriptingCompilerTest {
}

View File

@@ -0,0 +1,23 @@
<?xml version='1.0' encoding='UTF-8' ?>
<!--
~ 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 <http://www.gnu.org/licenses/>.
-->
<scriptlist xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../contexts.xsd">
<scriptinfo root="./src/test/resources/scripting"/>
</scriptlist>

View File

@@ -0,0 +1,4 @@
package test;
public class ScriptingCompilerTest {
}

View File

@@ -0,0 +1,23 @@
<?xml version='1.0' encoding='UTF-8' ?>
<!--
~ 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 <http://www.gnu.org/licenses/>.
-->
<scriptlist xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../contexts.xsd">
<scriptinfo root="./src/test/resources/scripting"/>
</scriptlist>