mirror of
https://github.com/Rogiel/l2jserver2
synced 2025-12-05 23:22:47 +00:00
Scripting engine
Change-Id: I5d6df6fd0d76cc07fd2631b5589f5200d9e50000
This commit is contained in:
@@ -4,12 +4,11 @@
|
||||
<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="src/dao/db4o"/>
|
||||
<classpathentry kind="src" path="data/scripts"/>
|
||||
<classpathentry kind="src" path="data/script"/>
|
||||
<classpathentry kind="src" path="data/template"/>
|
||||
<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/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
||||
|
||||
36
data/contexts.xsd
Normal file
36
data/contexts.xsd
Normal file
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<!--
|
||||
~ 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/>.
|
||||
-->
|
||||
<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:element name="scriptinfo" type="scriptInfo"/>
|
||||
|
||||
<xs:element name="scriptlist" type="scriptList"/>
|
||||
|
||||
<xs:complexType name="scriptList">
|
||||
<xs:sequence>
|
||||
<xs:element ref="scriptinfo" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="scriptInfo">
|
||||
<xs:sequence>
|
||||
<xs:element ref="scriptinfo" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<xs:element name="library" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="root" type="xs:string" use="required"/>
|
||||
</xs:complexType>
|
||||
</xs:schema>
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.l2jserver.script;
|
||||
package script;
|
||||
|
||||
import com.l2jserver.model.world.capability.Scriptable;
|
||||
import com.l2jserver.service.game.script.Script;
|
||||
import com.l2jserver.service.game.scripting.Script;
|
||||
|
||||
public class DummyScript implements Script<Scriptable> {
|
||||
@Override
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.l2jserver.model.template.armor;
|
||||
package script.template.armor;
|
||||
|
||||
import com.l2jserver.model.id.TemplateID;
|
||||
import com.l2jserver.model.template.ArmorTemplate;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.l2jserver.model.template.armor;
|
||||
package script.template.armor;
|
||||
|
||||
import com.l2jserver.model.id.TemplateID;
|
||||
import com.l2jserver.model.template.ArmorTemplate;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.l2jserver.model.template.armor;
|
||||
package script.template.armor;
|
||||
|
||||
import com.l2jserver.model.world.capability.Attackable;
|
||||
import com.l2jserver.model.world.capability.Attacker;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.l2jserver.model.template.armor;
|
||||
package script.template.armor;
|
||||
|
||||
import com.l2jserver.model.world.capability.Attackable;
|
||||
import com.l2jserver.model.world.capability.Attacker;
|
||||
12
data/template/script/template/item/AdenaItemTemplate.java
Normal file
12
data/template/script/template/item/AdenaItemTemplate.java
Normal file
@@ -0,0 +1,12 @@
|
||||
package script.template.item;
|
||||
|
||||
import com.l2jserver.model.id.TemplateID;
|
||||
import com.l2jserver.model.template.ItemTemplate;
|
||||
|
||||
public class AdenaItemTemplate extends ItemTemplate {
|
||||
public static final TemplateID ID = new TemplateID(57);
|
||||
|
||||
public AdenaItemTemplate() {
|
||||
super(ID);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.l2jserver.model.template.item;
|
||||
package script.template.item;
|
||||
|
||||
import com.l2jserver.model.template.PotionTemplate;
|
||||
import com.l2jserver.model.world.capability.Attackable;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.l2jserver.model.template.skill;
|
||||
package script.template.skill;
|
||||
|
||||
import com.l2jserver.model.template.SkillTemplate;
|
||||
import com.l2jserver.model.world.capability.Castable;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.l2jserver.model.template.weapon;
|
||||
package script.template.weapon;
|
||||
|
||||
import com.l2jserver.model.template.WeaponTemplate;
|
||||
import com.l2jserver.model.world.capability.Attackable;
|
||||
@@ -1,15 +0,0 @@
|
||||
package com.l2jserver.db.dao.db4o;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.l2jserver.service.database.AbstractDAO;
|
||||
import com.l2jserver.service.database.DB4ODatabaseService;
|
||||
|
||||
public class AbstractDB4ODAO<T> extends AbstractDAO<T> implements BD4ODAO {
|
||||
protected final DB4ODatabaseService database;
|
||||
|
||||
@Inject
|
||||
protected AbstractDB4ODAO(DB4ODatabaseService database) {
|
||||
super(database);
|
||||
this.database = database;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
package com.l2jserver.db.dao.db4o;
|
||||
|
||||
public interface BD4ODAO {
|
||||
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package com.l2jserver.db.dao.db4o;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.l2jserver.db.dao.CharacterDAO;
|
||||
import com.l2jserver.model.id.CharacterID;
|
||||
import com.l2jserver.model.world.L2Character;
|
||||
import com.l2jserver.service.database.DB4ODatabaseService;
|
||||
|
||||
public class DB4OCharacterDAO extends AbstractDB4ODAO<L2Character> implements CharacterDAO {
|
||||
@Inject
|
||||
protected DB4OCharacterDAO(DB4ODatabaseService database) {
|
||||
super(database);
|
||||
}
|
||||
|
||||
@Override
|
||||
public L2Character load(CharacterID id) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean save(L2Character character) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CharacterID> listIDs() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.l2jserver.db.dao.mysql5;
|
||||
package script.dao.mysql5;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.l2jserver.service.database.AbstractDAO;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.l2jserver.db.dao.mysql5;
|
||||
package script.dao.mysql5;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Scopes;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.l2jserver.db.dao.mysql5;
|
||||
package script.dao.mysql5;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.l2jserver.db.dao.mysql5;
|
||||
package script.dao.mysql5;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
@@ -1,7 +1,8 @@
|
||||
package com.l2jserver;
|
||||
|
||||
import script.dao.mysql5.DAOModuleMySQL5;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.l2jserver.db.dao.mysql5.DAOModuleMySQL5;
|
||||
import com.l2jserver.model.id.factory.IDFactoryModule;
|
||||
import com.l2jserver.routines.GameServerInitializationRoutine;
|
||||
import com.l2jserver.service.BasicServiceModule;
|
||||
|
||||
@@ -9,14 +9,13 @@ import org.jboss.netty.logging.InternalLogLevel;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Injector;
|
||||
import com.l2jserver.game.net.codec.Lineage2FrameDecoder;
|
||||
import com.l2jserver.game.net.codec.Lineage2Decrypter;
|
||||
import com.l2jserver.game.net.codec.Lineage2FrameEncoder;
|
||||
import com.l2jserver.game.net.codec.Lineage2Encrypter;
|
||||
import com.l2jserver.game.net.codec.Lineage2FrameDecoder;
|
||||
import com.l2jserver.game.net.codec.Lineage2FrameEncoder;
|
||||
import com.l2jserver.game.net.codec.Lineage2PacketReader;
|
||||
import com.l2jserver.game.net.codec.Lineage2PacketWriter;
|
||||
import com.l2jserver.game.net.handler.Lineage2PacketHandler;
|
||||
import com.l2jserver.service.logging.LoggingService;
|
||||
|
||||
public class Lineage2PipelineFactory implements ChannelPipelineFactory {
|
||||
private final Injector injector;
|
||||
@@ -39,8 +38,7 @@ public class Lineage2PipelineFactory implements ChannelPipelineFactory {
|
||||
new Lineage2Decrypter());
|
||||
|
||||
pipeline.addLast("packet.writer", new Lineage2PacketWriter());
|
||||
pipeline.addLast("packet.reader", new Lineage2PacketReader(injector,
|
||||
injector.getInstance(LoggingService.class)));
|
||||
pipeline.addLast("packet.reader", new Lineage2PacketReader(injector));
|
||||
|
||||
pipeline.addLast("packet.handler", new Lineage2PacketHandler());
|
||||
|
||||
|
||||
@@ -4,23 +4,23 @@ import org.jboss.netty.buffer.ChannelBuffer;
|
||||
import org.jboss.netty.channel.Channel;
|
||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||
import org.jboss.netty.handler.codec.oneone.OneToOneDecoder;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Injector;
|
||||
import com.l2jserver.game.net.packet.ClientPacket;
|
||||
import com.l2jserver.game.net.packet.client.AuthLoginPacket;
|
||||
import com.l2jserver.game.net.packet.client.ProtocolVersionPacket;
|
||||
import com.l2jserver.service.logging.Logger;
|
||||
import com.l2jserver.service.logging.LoggingService;
|
||||
|
||||
public class Lineage2PacketReader extends OneToOneDecoder {
|
||||
private final Injector injector;
|
||||
private final Logger logger;
|
||||
private final Logger logger = LoggerFactory
|
||||
.getLogger(Lineage2PacketReader.class);
|
||||
|
||||
@Inject
|
||||
public Lineage2PacketReader(Injector injector, LoggingService logging) {
|
||||
public Lineage2PacketReader(Injector injector) {
|
||||
this.injector = injector;
|
||||
this.logger = logging.getLogger(Lineage2PacketReader.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -3,20 +3,20 @@ package com.l2jserver.game.net.packet.client;
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
import org.jboss.netty.channel.ChannelFuture;
|
||||
import org.jboss.netty.channel.ChannelFutureListener;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.l2jserver.L2JConstants;
|
||||
import com.l2jserver.game.net.Lineage2Connection;
|
||||
import com.l2jserver.game.net.packet.AbstractClientPacket;
|
||||
import com.l2jserver.game.net.packet.server.KeyPacket;
|
||||
import com.l2jserver.service.logging.Logger;
|
||||
import com.l2jserver.service.logging.guice.InjectLogger;
|
||||
|
||||
public class ProtocolVersionPacket extends AbstractClientPacket {
|
||||
public static final int OPCODE = 0x0e;
|
||||
|
||||
// services
|
||||
@InjectLogger
|
||||
private final Logger logger = null;
|
||||
private final Logger logger = LoggerFactory
|
||||
.getLogger(ProtocolVersionPacket.class);
|
||||
|
||||
// packet
|
||||
private long version;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.l2jserver.model.world.capability;
|
||||
|
||||
import com.l2jserver.model.world.AbstractObject;
|
||||
import com.l2jserver.service.game.script.Script;
|
||||
import com.l2jserver.service.game.scripting.Script;
|
||||
|
||||
/**
|
||||
* Defines an {@link AbstractObject} that can be controller by an {@link Script}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
package com.l2jserver.service.compiler;
|
||||
|
||||
import com.l2jserver.service.Service;
|
||||
|
||||
public interface CompilerService extends Service {
|
||||
Class<?> compile(byte[] clazz);
|
||||
ClassLoader getClassLoader();
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package com.l2jserver.service.compiler;
|
||||
|
||||
public class DynamicClassLoader extends ClassLoader {
|
||||
public DynamicClassLoader() {
|
||||
super();
|
||||
}
|
||||
|
||||
public DynamicClassLoader(ClassLoader parent) {
|
||||
super(parent);
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package com.l2jserver.service.compiler;
|
||||
|
||||
import com.l2jserver.service.ServiceStartException;
|
||||
import com.l2jserver.service.ServiceStopException;
|
||||
|
||||
public class JavacCompilerService implements CompilerService {
|
||||
@Override
|
||||
public void start() throws ServiceStartException {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> compile(byte[] clazz) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassLoader getClassLoader() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() throws ServiceStopException {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package com.l2jserver.service.game.script;
|
||||
|
||||
import com.l2jserver.service.Service;
|
||||
|
||||
public interface ScriptingService extends Service {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* This class represents compilation result of script context
|
||||
*
|
||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||
*/
|
||||
public class CompilationResult {
|
||||
/**
|
||||
* List of classes that were compiled by compiler
|
||||
*/
|
||||
private final Class<?>[] compiledClasses;
|
||||
|
||||
/**
|
||||
* Classloader that was used to load classes
|
||||
*/
|
||||
private final ScriptClassLoader classLoader;
|
||||
|
||||
/**
|
||||
* Creates new instance of CompilationResult with classes that has to be
|
||||
* parsed and classloader that was used to load classes
|
||||
*
|
||||
* @param compiledClasses
|
||||
* classes compiled by compiler
|
||||
* @param classLoader
|
||||
* classloader that was used by compiler
|
||||
*/
|
||||
public CompilationResult(Class<?>[] compiledClasses,
|
||||
ScriptClassLoader classLoader) {
|
||||
this.compiledClasses = compiledClasses;
|
||||
this.classLoader = classLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns classLoader that was used by compiler
|
||||
*
|
||||
* @return classloader that was used by compiler
|
||||
*/
|
||||
public ScriptClassLoader getClassLoader() {
|
||||
return classLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retunrs list of classes that were compiled
|
||||
*
|
||||
* @return list of classes that were compiled
|
||||
*/
|
||||
public Class<?>[] getCompiledClasses() {
|
||||
return compiledClasses;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.l2jserver.service.game.script;
|
||||
package com.l2jserver.service.game.scripting;
|
||||
|
||||
import com.l2jserver.model.world.capability.Scriptable;
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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 java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.net.URLStreamHandlerFactory;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* Abstract class loader that should be extended by child classloaders. If
|
||||
* needed, this class should wrap another classloader.
|
||||
*
|
||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||
*/
|
||||
public abstract class ScriptClassLoader extends URLClassLoader {
|
||||
|
||||
/**
|
||||
* Just for compatibility with {@link URLClassLoader}
|
||||
*
|
||||
* @param urls
|
||||
* list of urls
|
||||
* @param parent
|
||||
* parent classloader
|
||||
*/
|
||||
public ScriptClassLoader(URL[] urls, ClassLoader parent) {
|
||||
super(urls, parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Just for compatibility with {@link URLClassLoader}
|
||||
*
|
||||
* @param urls
|
||||
* list of urls
|
||||
*/
|
||||
public ScriptClassLoader(URL[] urls) {
|
||||
super(urls);
|
||||
}
|
||||
|
||||
/**
|
||||
* Just for compatibility with {@link URLClassLoader}
|
||||
*
|
||||
* @param urls
|
||||
* list of urls
|
||||
* @param parent
|
||||
* parent classloader
|
||||
* @param factory
|
||||
* {@link java.net.URLStreamHandlerFactory}
|
||||
*/
|
||||
public ScriptClassLoader(URL[] urls, ClassLoader parent,
|
||||
URLStreamHandlerFactory factory) {
|
||||
super(urls, parent, factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds library to this classloader, it shuould be jar file
|
||||
*
|
||||
* @param file
|
||||
* jar file
|
||||
* @throws IOException
|
||||
* if can't add library
|
||||
*/
|
||||
public abstract void addLibrary(File file) throws IOException;
|
||||
|
||||
/**
|
||||
* Returns unmodifiable set of class names that were loaded from libraries
|
||||
*
|
||||
* @return unmodifiable set of class names that were loaded from libraries
|
||||
*/
|
||||
public abstract Set<String> getLibraryClasses();
|
||||
|
||||
/**
|
||||
* Retuns unmodifiable set of class names that were compiled
|
||||
*
|
||||
* @return unmodifiable set of class names that were compiled
|
||||
*/
|
||||
public abstract Set<String> getCompiledClasses();
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* This interface reperesents common functionality list that should be available
|
||||
* for any commpiler that is going to be used with scripting engine. For
|
||||
* instance, groovy can be used, hoever it produces by far not the best bytecode
|
||||
* so by default javac from sun is used.
|
||||
*
|
||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||
*/
|
||||
public interface ScriptCompiler {
|
||||
/**
|
||||
* Sets parent class loader for this compiler.<br>
|
||||
* <br>
|
||||
* <font color="red">Warning, for now only</font>
|
||||
*
|
||||
* @param classLoader
|
||||
* ScriptClassLoader that will be used as parent
|
||||
*/
|
||||
void setParentClassLoader(ScriptClassLoader classLoader);
|
||||
|
||||
/**
|
||||
* List of jar files that are required for compilation
|
||||
*
|
||||
* @param files
|
||||
* list of jar files
|
||||
*/
|
||||
void setLibraires(Iterable<File> files);
|
||||
|
||||
/**
|
||||
* Compiles single class that is represented as string
|
||||
*
|
||||
* @param className
|
||||
* class name
|
||||
* @param sourceCode
|
||||
* class sourse code
|
||||
* @return {@link CompilationResult}
|
||||
*/
|
||||
CompilationResult compile(String className, String sourceCode);
|
||||
|
||||
/**
|
||||
* Compiles classes that are represented as strings
|
||||
*
|
||||
* @param className
|
||||
* class names
|
||||
* @param sourceCode
|
||||
* class sources
|
||||
* @return {@link CompilationResult}
|
||||
* @throws IllegalArgumentException
|
||||
* if number of class names != number of sources
|
||||
*/
|
||||
CompilationResult compile(String[] className, String[] sourceCode)
|
||||
throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Compiles list of files
|
||||
*
|
||||
* @param compilationUnits
|
||||
* list of files
|
||||
* @return {@link CompilationResult}
|
||||
*/
|
||||
CompilationResult compile(Iterable<File> compilationUnits);
|
||||
|
||||
/**
|
||||
* Returns array of supported file types. This files will be threated as
|
||||
* source files.
|
||||
*
|
||||
* @return array of supported file types.
|
||||
*/
|
||||
String[] getSupportedFileTypes();
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* 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 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;
|
||||
|
||||
/**
|
||||
* This class represents script context that can be loaded, unloaded, etc...<br>
|
||||
*
|
||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||
*/
|
||||
public interface ScriptContext {
|
||||
/**
|
||||
* Initializes script context. Calls the compilation task.<br>
|
||||
* After compilation static methods marked with {@link OnClassLoad} 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
|
||||
*/
|
||||
void shutdown();
|
||||
|
||||
/**
|
||||
* Invokes {@link #shutdown()}, after that invokes {@link #init()}. Root
|
||||
* folder remains the same, but new compiler and classloader are used.
|
||||
*/
|
||||
void reload();
|
||||
|
||||
/**
|
||||
* Returns the root directory for script engine. Only one script engine per
|
||||
* root directory is allowed.
|
||||
*
|
||||
* @return root directory for script engine
|
||||
*/
|
||||
File getRoot();
|
||||
|
||||
/**
|
||||
* Returns compilation result of this script context
|
||||
*
|
||||
* @return compilation result
|
||||
*/
|
||||
CompilationResult getCompilationResult();
|
||||
|
||||
/**
|
||||
* Returns true if this script context is loaded
|
||||
*
|
||||
* @return true if context is initialized
|
||||
*/
|
||||
boolean isInitialized();
|
||||
|
||||
/**
|
||||
* Sets files that represents jar files, they will be used as libraries
|
||||
*
|
||||
* @param files
|
||||
* that points to jar file, will be used as libraries
|
||||
*/
|
||||
void setLibraries(Iterable<File> files);
|
||||
|
||||
/**
|
||||
* Returns list of files that are used as libraries for this script context
|
||||
*
|
||||
* @return list of libraries
|
||||
*/
|
||||
Iterable<File> getLibraries();
|
||||
|
||||
/**
|
||||
* Returns parent script context of this context. Returns null if none.
|
||||
*
|
||||
* @return parent Script context of this context or null
|
||||
*/
|
||||
ScriptContext getParentScriptContext();
|
||||
|
||||
/**
|
||||
* Returns list of child contexts or null if no contextes present
|
||||
*
|
||||
* @return list of child contexts or null
|
||||
*/
|
||||
Collection<ScriptContext> getChildScriptContexts();
|
||||
|
||||
/**
|
||||
* Adds child contexts to this context. If this context is initialized -
|
||||
* chiled context will be initialized immideatly. In other case child
|
||||
* context will be just added and initialized when {@link #init()} would be
|
||||
* called. Duplicated child contexts are not allowed, in such case child
|
||||
* will be ignored
|
||||
*
|
||||
* @param context
|
||||
* child context
|
||||
*/
|
||||
void addChildScriptContext(ScriptContext context);
|
||||
|
||||
/**
|
||||
* Sets the class listener for this script context.
|
||||
*
|
||||
* @param cl
|
||||
* class listener
|
||||
*/
|
||||
void setClassListener(ClassListener cl);
|
||||
|
||||
/**
|
||||
* Returns class listener associated with this ScriptContext.<br>
|
||||
* If it's null - returns parent classListener.<br>
|
||||
* If parent is null and classListener is null - it will set
|
||||
* {@link DefaultClassListener} as class listener and return it
|
||||
*
|
||||
* @return Associated class listener
|
||||
*/
|
||||
ClassListener getClassListener();
|
||||
|
||||
/**
|
||||
* Sets compiler class name for this script context.<br>
|
||||
* Compiler is not inherrited by children.<br>
|
||||
*
|
||||
* @param className
|
||||
* compiler class name
|
||||
*/
|
||||
void setCompilerClassName(String className);
|
||||
|
||||
/**
|
||||
* Returns compiler class name that will be used for this script context.
|
||||
*
|
||||
* @return compiler class name that will be used for tis script context
|
||||
*/
|
||||
String getCompilerClassName();
|
||||
|
||||
/**
|
||||
* Tests if this ScriptContext is equal to another ScriptContext.
|
||||
* Comparation is done by comparing root files and parent contexts (if there
|
||||
* is any parent)
|
||||
*
|
||||
* @param obj
|
||||
* object to compare with
|
||||
* @return result of comparation
|
||||
*/
|
||||
@Override
|
||||
boolean equals(Object obj);
|
||||
|
||||
/**
|
||||
* Returns hashCoded of this ScriptContext. Hashcode is calculated using
|
||||
* root file and parent context(if available)
|
||||
*
|
||||
* @return hashcode
|
||||
*/
|
||||
@Override
|
||||
int hashCode();
|
||||
|
||||
/**
|
||||
* This method overrides finalization to ensure that active script context
|
||||
* will not be collected by GC. If such situation happens -
|
||||
* {@link #shutdown()} is called to ensure that resources were released.
|
||||
*
|
||||
* @throws Throwable
|
||||
* if something goes wrong during finalization
|
||||
*/
|
||||
void finalize() throws Throwable;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.l2jserver.service.game.scripting;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import com.l2jserver.service.Service;
|
||||
|
||||
public interface ScriptingService extends Service {
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
ScriptContext getScriptContext(File root, ScriptContext parent)
|
||||
throws InstantiationException;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.l2jserver.service.game.scripting;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import com.l2jserver.service.ServiceStartException;
|
||||
import com.l2jserver.service.ServiceStopException;
|
||||
import com.l2jserver.service.game.scripting.impl.ScriptContextImpl;
|
||||
|
||||
public class ScriptingServiceImpl implements ScriptingService {
|
||||
@Override
|
||||
public void start() throws ServiceStartException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public 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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() throws ServiceStopException {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.classlistener;
|
||||
|
||||
/**
|
||||
* This interface implements listener that is called post class load/before
|
||||
* class unload.<br>
|
||||
* Default implementation is: {@link DefaultClassListener}
|
||||
*
|
||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||
*/
|
||||
public interface ClassListener {
|
||||
|
||||
/**
|
||||
* This method is invoked after classes were loaded. As areguments are
|
||||
* passes all loaded classes
|
||||
*
|
||||
* @param classes
|
||||
* classes that were loaded
|
||||
*/
|
||||
public void postLoad(Class<?>... classes);
|
||||
|
||||
/**
|
||||
* This method is invoked before class unloading. As argument are passes all
|
||||
* loaded classes
|
||||
*
|
||||
* @param classes
|
||||
* classes that were loaded
|
||||
*/
|
||||
public void preUnload(Class<?>... classes);
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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.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;
|
||||
|
||||
/**
|
||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||
*/
|
||||
public class DefaultClassListener implements ClassListener {
|
||||
|
||||
private static final Logger log = LoggerFactory
|
||||
.getLogger(DefaultClassListener.class);
|
||||
|
||||
@Override
|
||||
public void postLoad(Class<?>... classes) {
|
||||
for (Class<?> c : classes) {
|
||||
doMethodInvoke(c.getDeclaredMethods(), OnClassLoad.class);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preUnload(Class<?>... classes) {
|
||||
for (Class<?> c : classes) {
|
||||
doMethodInvoke(c.getDeclaredMethods(), OnClassUnload.class);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Actually invokes method where given annotation class is present. Only
|
||||
* static methods can be invoked
|
||||
*
|
||||
* @param methods
|
||||
* Methods to scan for annotations
|
||||
* @param annotationClass
|
||||
* class of annotation to search for
|
||||
*/
|
||||
static void doMethodInvoke(Method[] methods,
|
||||
Class<? extends Annotation> annotationClass) {
|
||||
for (Method m : methods) {
|
||||
|
||||
if (!Modifier.isStatic(m.getModifiers())) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,337 @@
|
||||
/*
|
||||
* 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.impl;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.l2jserver.service.game.scripting.CompilationResult;
|
||||
import com.l2jserver.service.game.scripting.ScriptCompiler;
|
||||
import com.l2jserver.service.game.scripting.ScriptContext;
|
||||
import com.l2jserver.service.game.scripting.classlistener.ClassListener;
|
||||
import com.l2jserver.service.game.scripting.classlistener.DefaultClassListener;
|
||||
|
||||
/**
|
||||
* This class is actual implementation of {@link ScriptContext}
|
||||
*
|
||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||
*/
|
||||
public class ScriptContextImpl implements ScriptContext {
|
||||
/**
|
||||
* logger for this class
|
||||
*/
|
||||
private static final Logger log = LoggerFactory
|
||||
.getLogger(ScriptContextImpl.class);
|
||||
|
||||
/**
|
||||
* Script context that is parent for this script context
|
||||
*/
|
||||
private final ScriptContext parentScriptContext;
|
||||
|
||||
/**
|
||||
* Libraries (list of jar files) that have to be loaded class loader
|
||||
*/
|
||||
private Iterable<File> libraries;
|
||||
|
||||
/**
|
||||
* Root directory of this script context. It and it's subdirectories will be
|
||||
* scanned for .java files.
|
||||
*/
|
||||
private final File root;
|
||||
|
||||
/**
|
||||
* Result of compilation of script context
|
||||
*/
|
||||
private CompilationResult compilationResult;
|
||||
|
||||
/**
|
||||
* List of child script contexts
|
||||
*/
|
||||
private Set<ScriptContext> childScriptContexts;
|
||||
|
||||
/**
|
||||
* Classlistener for this script context
|
||||
*/
|
||||
private ClassListener classListener;
|
||||
|
||||
/**
|
||||
* Class name of the compiler that will be used to compile sources
|
||||
*/
|
||||
private String compilerClassName;
|
||||
|
||||
/**
|
||||
* Creates new scriptcontext with given root file
|
||||
*
|
||||
* @param root
|
||||
* file that represents root directory of this script context
|
||||
* @throws NullPointerException
|
||||
* if root is null
|
||||
* @throws IllegalArgumentException
|
||||
* if root directory doesn't exists or is not a directory
|
||||
*/
|
||||
public ScriptContextImpl(File root) {
|
||||
this(root, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new ScriptContext with given file as root and another
|
||||
* ScriptContext as parent
|
||||
*
|
||||
* @param root
|
||||
* file that represents root directory of this script context
|
||||
* @param parent
|
||||
* parent ScriptContex. It's classes and libraries will be
|
||||
* accessible for this script context
|
||||
* @throws NullPointerException
|
||||
* if root is null
|
||||
* @throws IllegalArgumentException
|
||||
* if root directory doesn't exists or is not a directory
|
||||
*/
|
||||
public ScriptContextImpl(File root, ScriptContext parent) {
|
||||
if (root == null) {
|
||||
throw new NullPointerException("Root file must be specified");
|
||||
}
|
||||
|
||||
if (!root.exists() || !root.isDirectory()) {
|
||||
throw new IllegalArgumentException(
|
||||
"Root directory not exists or is not a directory");
|
||||
}
|
||||
|
||||
this.root = root;
|
||||
this.parentScriptContext = parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void init() {
|
||||
|
||||
if (compilationResult != null) {
|
||||
log.error("", new Exception(
|
||||
"Init request on initialized ScriptContext"));
|
||||
return;
|
||||
}
|
||||
|
||||
ScriptCompiler scriptCompiler = instantiateCompiler();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Collection<File> files = FileUtils.listFiles(root,
|
||||
scriptCompiler.getSupportedFileTypes(), true);
|
||||
|
||||
if (parentScriptContext != null) {
|
||||
scriptCompiler.setParentClassLoader(parentScriptContext
|
||||
.getCompilationResult().getClassLoader());
|
||||
}
|
||||
|
||||
scriptCompiler.setLibraires(libraries);
|
||||
compilationResult = scriptCompiler.compile(files);
|
||||
|
||||
getClassListener().postLoad(compilationResult.getCompiledClasses());
|
||||
|
||||
if (childScriptContexts != null) {
|
||||
for (ScriptContext context : childScriptContexts) {
|
||||
context.init();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void shutdown() {
|
||||
|
||||
if (compilationResult == null) {
|
||||
log.error("Shutdown of not initialized stript context",
|
||||
new Exception());
|
||||
return;
|
||||
}
|
||||
|
||||
if (childScriptContexts != null) {
|
||||
for (ScriptContext child : childScriptContexts) {
|
||||
child.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
getClassListener().preUnload(compilationResult.getCompiledClasses());
|
||||
compilationResult = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
shutdown();
|
||||
init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getRoot() {
|
||||
return root;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompilationResult getCompilationResult() {
|
||||
return compilationResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean isInitialized() {
|
||||
return compilationResult != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLibraries(Iterable<File> files) {
|
||||
this.libraries = files;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<File> getLibraries() {
|
||||
return libraries;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScriptContext getParentScriptContext() {
|
||||
return parentScriptContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ScriptContext> getChildScriptContexts() {
|
||||
return childScriptContexts;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void addChildScriptContext(ScriptContext context) {
|
||||
synchronized (this) {
|
||||
if (childScriptContexts == null) {
|
||||
childScriptContexts = new HashSet<ScriptContext>();
|
||||
}
|
||||
|
||||
if (childScriptContexts.contains(context)) {
|
||||
log.error("Double child definition, root: "
|
||||
+ root.getAbsolutePath() + ", child: "
|
||||
+ context.getRoot().getAbsolutePath());
|
||||
return;
|
||||
}
|
||||
|
||||
if (isInitialized()) {
|
||||
context.init();
|
||||
}
|
||||
}
|
||||
childScriptContexts.add(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setClassListener(ClassListener cl) {
|
||||
classListener = cl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassListener getClassListener() {
|
||||
if (classListener == null) {
|
||||
if (getParentScriptContext() == null) {
|
||||
setClassListener(new DefaultClassListener());
|
||||
return classListener;
|
||||
} else {
|
||||
return getParentScriptContext().getClassListener();
|
||||
}
|
||||
} else {
|
||||
return classListener;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCompilerClassName(String className) {
|
||||
this.compilerClassName = className;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCompilerClassName() {
|
||||
return this.compilerClassName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new instance of ScriptCompiler that should be used with this
|
||||
* ScriptContext
|
||||
*
|
||||
* @return instance of ScriptCompiler
|
||||
* @throws RuntimeException
|
||||
* if failed to create instance
|
||||
*/
|
||||
protected ScriptCompiler instantiateCompiler() throws RuntimeException {
|
||||
ClassLoader cl = getClass().getClassLoader();
|
||||
if (getParentScriptContext() != null) {
|
||||
cl = getParentScriptContext().getCompilationResult()
|
||||
.getClassLoader();
|
||||
}
|
||||
|
||||
ScriptCompiler sc;
|
||||
try {
|
||||
sc = (ScriptCompiler) Class.forName(getCompilerClassName(), true,
|
||||
cl).newInstance();
|
||||
} catch (Exception e) {
|
||||
RuntimeException e1 = new RuntimeException(
|
||||
"Can't create instance of compiler", e);
|
||||
log.error("Compiler exception", e1);
|
||||
throw e1;
|
||||
}
|
||||
|
||||
return sc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof ScriptContextImpl)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ScriptContextImpl another = (ScriptContextImpl) obj;
|
||||
|
||||
if (parentScriptContext == null) {
|
||||
return another.getRoot().equals(root);
|
||||
} else {
|
||||
return another.getRoot().equals(root)
|
||||
&& parentScriptContext.equals(another.parentScriptContext);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = parentScriptContext != null ? parentScriptContext
|
||||
.hashCode() : 0;
|
||||
result = 31 * result + root.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void finalize() throws Throwable {
|
||||
if (compilationResult != null) {
|
||||
log.error("Finalization of initialized ScriptContext. Forcing context shutdown.");
|
||||
shutdown();
|
||||
}
|
||||
super.finalize();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
/*
|
||||
* 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.impl.javacc;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
import java.net.URI;
|
||||
|
||||
import javax.lang.model.element.Modifier;
|
||||
import javax.lang.model.element.NestingKind;
|
||||
import javax.tools.JavaFileObject;
|
||||
|
||||
/**
|
||||
* This class is just a hack to make javac compiler work with classes loaded by
|
||||
* prevoius classloader. Also it's used as container for loaded class
|
||||
*
|
||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||
*/
|
||||
public class BinaryClass implements JavaFileObject {
|
||||
/**
|
||||
* ClassName
|
||||
*/
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
* Class data will be written here
|
||||
*/
|
||||
private final ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
|
||||
/**
|
||||
* Locaded class will be set here
|
||||
*/
|
||||
private Class<?> definedClass;
|
||||
|
||||
/**
|
||||
* Constructor that accepts class name as parameter
|
||||
*
|
||||
* @param name
|
||||
* class name
|
||||
*/
|
||||
protected BinaryClass(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws {@link UnsupportedOperationException}
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
@Override
|
||||
public URI toUri() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns name of this class with ".class" suffix
|
||||
*
|
||||
* @return name of this class with ".class" suffix
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return name + ".class";
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new ByteArrayInputStream, it just wraps class binary data
|
||||
*
|
||||
* @return input stream for class data
|
||||
* @throws IOException
|
||||
* never thrown
|
||||
*/
|
||||
@Override
|
||||
public InputStream openInputStream() throws IOException {
|
||||
return new ByteArrayInputStream(baos.toByteArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens ByteArrayOutputStream for class data
|
||||
*
|
||||
* @return output stream
|
||||
* @throws IOException
|
||||
* never thrown
|
||||
*/
|
||||
@Override
|
||||
public OutputStream openOutputStream() throws IOException {
|
||||
return baos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws {@link UnsupportedOperationException}
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
@Override
|
||||
public CharSequence getCharContent(boolean ignoreEncodingErrors)
|
||||
throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws {@link UnsupportedOperationException}
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
@Override
|
||||
public Writer openWriter() throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsupported operation, always reutrns 0
|
||||
*
|
||||
* @return 0
|
||||
*/
|
||||
@Override
|
||||
public long getLastModified() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsupported operation, returns false
|
||||
*
|
||||
* @return false
|
||||
*/
|
||||
@Override
|
||||
public boolean delete() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if {@link javax.tools.JavaFileObject.Kind#CLASS}
|
||||
*
|
||||
* @param simpleName
|
||||
* doesn't matter
|
||||
* @param kind
|
||||
* kind to compare
|
||||
* @return true if Kind is {@link javax.tools.JavaFileObject.Kind#CLASS}
|
||||
*/
|
||||
@Override
|
||||
public boolean isNameCompatible(String simpleName, Kind kind) {
|
||||
return Kind.CLASS.equals(kind);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns bytes of class
|
||||
*
|
||||
* @return bytes of class
|
||||
*/
|
||||
public byte[] getBytes() {
|
||||
return baos.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns class that was loaded from binary data of this object
|
||||
*
|
||||
* @return loaded class
|
||||
*/
|
||||
public Class<?> getDefinedClass() {
|
||||
return definedClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets class that was loaded by this object
|
||||
*
|
||||
* @param definedClass
|
||||
* class that was loaded
|
||||
*/
|
||||
public void setDefinedClass(Class<?> definedClass) {
|
||||
this.definedClass = definedClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
|
||||
return new InputStreamReader(new ByteArrayInputStream(getBytes()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Modifier getAccessLevel() {
|
||||
return Modifier.PUBLIC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Kind getKind() {
|
||||
return Kind.CLASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NestingKind getNestingKind() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
* 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.impl.javacc;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.tools.DiagnosticListener;
|
||||
import javax.tools.FileObject;
|
||||
import javax.tools.ForwardingJavaFileManager;
|
||||
import javax.tools.JavaCompiler;
|
||||
import javax.tools.JavaFileManager;
|
||||
import javax.tools.JavaFileObject;
|
||||
import javax.tools.JavaFileObject.Kind;
|
||||
import javax.tools.StandardLocation;
|
||||
|
||||
import com.l2jserver.service.game.scripting.ScriptClassLoader;
|
||||
import com.l2jserver.util.factory.CollectionFactory;
|
||||
|
||||
/**
|
||||
* This class extends manages loaded classes. It is also responsible for
|
||||
* tricking compiler. Unfortunally compiler doen't work with classloaders, so we
|
||||
* have to pass class data manually for each compilation.
|
||||
*
|
||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||
*/
|
||||
public class ClassFileManager extends
|
||||
ForwardingJavaFileManager<JavaFileManager> {
|
||||
|
||||
/**
|
||||
* This map contains classes compiled for this classloader
|
||||
*/
|
||||
private final Map<String, BinaryClass> compiledClasses = CollectionFactory
|
||||
.newMap(String.class, BinaryClass.class);
|
||||
|
||||
/**
|
||||
* Classloader that will be used to load compiled classes
|
||||
*/
|
||||
protected ScriptClassLoaderImpl loader;
|
||||
|
||||
/**
|
||||
* Parent classloader for loader
|
||||
*/
|
||||
protected ScriptClassLoader parentClassLoader;
|
||||
|
||||
/**
|
||||
* Creates new ClassFileManager.
|
||||
*
|
||||
* @param compiler
|
||||
* that will be used
|
||||
* @param listener
|
||||
* class that will report compilation errors
|
||||
*/
|
||||
public ClassFileManager(JavaCompiler compiler,
|
||||
DiagnosticListener<? super JavaFileObject> listener) {
|
||||
super(compiler.getStandardFileManager(listener, null, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns JavaFileObject that will be used to write class data into it by
|
||||
* compiler
|
||||
*
|
||||
* @param location
|
||||
* not used
|
||||
* @param className
|
||||
* JavaFileObject will have this className
|
||||
* @param kind
|
||||
* not used
|
||||
* @param sibling
|
||||
* not used
|
||||
* @return JavaFileObject that will be uesd to store compiled class data
|
||||
* @throws IOException
|
||||
* never thrown
|
||||
*/
|
||||
@Override
|
||||
public JavaFileObject getJavaFileForOutput(Location location,
|
||||
String className, Kind kind, FileObject sibling) throws IOException {
|
||||
BinaryClass co = new BinaryClass(className);
|
||||
compiledClasses.put(className, co);
|
||||
return co;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns classloaded of this ClassFileManager. If not exists, creates new
|
||||
*
|
||||
* @param location
|
||||
* not used
|
||||
* @return classLoader of this ClassFileManager
|
||||
*/
|
||||
@Override
|
||||
public synchronized ScriptClassLoaderImpl getClassLoader(Location location) {
|
||||
if (loader == null) {
|
||||
if (parentClassLoader != null) {
|
||||
loader = new ScriptClassLoaderImpl(this, parentClassLoader);
|
||||
} else {
|
||||
loader = new ScriptClassLoaderImpl(this);
|
||||
}
|
||||
}
|
||||
return loader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets paraentClassLoader for this classLoader
|
||||
*
|
||||
* @param classLoader
|
||||
* parent class loader
|
||||
*/
|
||||
public void setParentClassLoader(ScriptClassLoader classLoader) {
|
||||
this.parentClassLoader = classLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds library file. Library file must be a .jar archieve
|
||||
*
|
||||
* @param file
|
||||
* link to jar archieve
|
||||
* @throws IOException
|
||||
* if something goes wrong
|
||||
*/
|
||||
public void addLibrary(File file) throws IOException {
|
||||
ScriptClassLoaderImpl classLoader = getClassLoader(null);
|
||||
classLoader.addLibrary(file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds list of files as libraries. Files must be jar archieves
|
||||
*
|
||||
* @param files
|
||||
* list of jar archives
|
||||
* @throws IOException
|
||||
* if some5thing goes wrong
|
||||
*/
|
||||
public void addLibraries(Iterable<File> files) throws IOException {
|
||||
for (File f : files) {
|
||||
addLibrary(f);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns list of classes that were compiled by conpiler related to this
|
||||
* ClassFileManager
|
||||
*
|
||||
* @return list of classes
|
||||
*/
|
||||
public Map<String, BinaryClass> getCompiledClasses() {
|
||||
return compiledClasses;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method overrides class resolving procedure for compiler. It uses
|
||||
* classloaders to resolve classes that compiler may need during
|
||||
* compilation.
|
||||
*
|
||||
* Compiler by itself can't detect them. So we have to use this hack here.
|
||||
*
|
||||
* Hack is used only if compiler requests for classes in classpath.
|
||||
*
|
||||
* @param location
|
||||
* Location to search classes
|
||||
* @param packageName
|
||||
* package to scan for classes
|
||||
* @param kinds
|
||||
* FileTypes to search
|
||||
* @param recurse
|
||||
* not used
|
||||
* @return list of requered files
|
||||
* @throws IOException
|
||||
* if something foes wrong
|
||||
*/
|
||||
@Override
|
||||
public Iterable<JavaFileObject> list(Location location, String packageName,
|
||||
Set<Kind> kinds, boolean recurse) throws IOException {
|
||||
Iterable<JavaFileObject> objects = super.list(location, packageName,
|
||||
kinds, recurse);
|
||||
|
||||
if (StandardLocation.CLASS_PATH.equals(location)
|
||||
&& kinds.contains(Kind.CLASS)) {
|
||||
List<JavaFileObject> temp = new ArrayList<JavaFileObject>();
|
||||
for (JavaFileObject object : objects) {
|
||||
temp.add(object);
|
||||
}
|
||||
|
||||
temp.addAll(loader.getClassesForPackage(packageName));
|
||||
objects = temp;
|
||||
}
|
||||
|
||||
return objects;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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.impl.javacc;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.tools.Diagnostic;
|
||||
import javax.tools.DiagnosticListener;
|
||||
import javax.tools.JavaFileObject;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* This class is simple compiler error listener that forwards errors to log4j
|
||||
* logger
|
||||
*
|
||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||
*/
|
||||
public class ErrorListener implements DiagnosticListener<JavaFileObject> {
|
||||
|
||||
/**
|
||||
* Logger for this class
|
||||
*/
|
||||
private static final Logger log = LoggerFactory
|
||||
.getLogger(ErrorListener.class);
|
||||
|
||||
/**
|
||||
* Reports compilation errors to log4j
|
||||
*
|
||||
* @param diagnostic
|
||||
* compiler errors
|
||||
*/
|
||||
@Override
|
||||
public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append("Compier Error Report Start").append("\n");
|
||||
buffer.append("errcode:").append(diagnostic.getCode()).append("\n");
|
||||
buffer.append("line :").append(diagnostic.getLineNumber())
|
||||
.append("\n");
|
||||
buffer.append("column :").append(diagnostic.getColumnNumber())
|
||||
.append("\n");
|
||||
buffer.append("message:")
|
||||
.append(diagnostic.getMessage(Locale.getDefault()))
|
||||
.append("\n");
|
||||
buffer.append("Compier Error Report End");
|
||||
log.error(buffer.toString());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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.impl.javacc;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.tools.SimpleJavaFileObject;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
/**
|
||||
* This class is simple wrapper for SimpleJavaFileObject that load class source
|
||||
* from file sytem
|
||||
*
|
||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||
*/
|
||||
public class JavaSourceFromFile extends SimpleJavaFileObject {
|
||||
|
||||
/**
|
||||
* Construct a JavaFileObject of the given kind and with the given File.
|
||||
*
|
||||
* @param file
|
||||
* the file with source of this file object
|
||||
* @param kind
|
||||
* the kind of this file object
|
||||
*/
|
||||
public JavaSourceFromFile(File file, Kind kind) {
|
||||
super(file.toURI(), kind);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns class source represented as string.
|
||||
*
|
||||
* @param ignoreEncodingErrors
|
||||
* not used
|
||||
* @return class source
|
||||
* @throws IOException
|
||||
* if something goes wrong
|
||||
*/
|
||||
@Override
|
||||
public CharSequence getCharContent(boolean ignoreEncodingErrors)
|
||||
throws IOException {
|
||||
return FileUtils.readFileToString(new File(this.toUri()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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.impl.javacc;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import javax.tools.JavaFileObject;
|
||||
import javax.tools.SimpleJavaFileObject;
|
||||
|
||||
/**
|
||||
* This class allows us to compile sources that are located only in memory.
|
||||
*
|
||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||
*/
|
||||
public class JavaSourceFromString extends SimpleJavaFileObject {
|
||||
/**
|
||||
* Source code of the class
|
||||
*/
|
||||
private final String code;
|
||||
|
||||
/**
|
||||
* Creates new object that contains sources of java class
|
||||
*
|
||||
* @param className
|
||||
* class name of class
|
||||
* @param code
|
||||
* source code of class
|
||||
*/
|
||||
public JavaSourceFromString(String className, String code) {
|
||||
super(URI.create("string:///" + className.replace('.', '/')
|
||||
+ JavaFileObject.Kind.SOURCE.extension),
|
||||
JavaFileObject.Kind.SOURCE);
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns class source code
|
||||
*
|
||||
* @param ignoreEncodingErrors
|
||||
* not used
|
||||
* @return class source code
|
||||
*/
|
||||
@Override
|
||||
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,289 @@
|
||||
/*
|
||||
* 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.impl.javacc;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
import javax.tools.JavaFileObject;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.l2jserver.service.game.scripting.ScriptClassLoader;
|
||||
import com.l2jserver.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* This classloader is used to load script classes. <br>
|
||||
* <br>
|
||||
* Due to JavaCompiler limitations we have to keep list of available classes
|
||||
* here.
|
||||
*
|
||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||
*/
|
||||
public class ScriptClassLoaderImpl extends ScriptClassLoader {
|
||||
|
||||
/**
|
||||
* Logger
|
||||
*/
|
||||
private static final Logger log = LoggerFactory
|
||||
.getLogger(ScriptClassLoaderImpl.class);
|
||||
|
||||
/**
|
||||
* URL Stream handler to allow valid url generation by
|
||||
* {@link #getResource(String)}
|
||||
*/
|
||||
private final VirtualClassURLStreamHandler urlStreamHandler = new VirtualClassURLStreamHandler(
|
||||
this);
|
||||
|
||||
/**
|
||||
* ClassFileManager that is related to this ClassLoader
|
||||
*/
|
||||
private final ClassFileManager classFileManager;
|
||||
|
||||
/**
|
||||
* Classes that were loaded from libraries. They are no parsed for any
|
||||
* annotations, but they are needed by JavaCompiler to perform valid
|
||||
* compilation
|
||||
*/
|
||||
private Set<String> libraryClasses = new HashSet<String>();
|
||||
|
||||
/**
|
||||
* Creates new ScriptClassLoader with given ClassFileManger
|
||||
*
|
||||
* @param classFileManager
|
||||
* classFileManager of this classLoader
|
||||
*/
|
||||
ScriptClassLoaderImpl(ClassFileManager classFileManager) {
|
||||
super(new URL[] {});
|
||||
this.classFileManager = classFileManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new ScriptClassLoader with given ClassFileManger and another
|
||||
* classLoader as parent
|
||||
*
|
||||
* @param classFileManager
|
||||
* classFileManager of this classLoader
|
||||
* @param parent
|
||||
* parent classLoader
|
||||
*/
|
||||
ScriptClassLoaderImpl(ClassFileManager classFileManager, ClassLoader parent) {
|
||||
super(new URL[] {}, parent);
|
||||
this.classFileManager = classFileManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns ClassFileManager that is related to this ClassLoader
|
||||
*
|
||||
* @return classFileManager of this classLoader
|
||||
*/
|
||||
public ClassFileManager getClassFileManager() {
|
||||
return classFileManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* AddsLibrary jar
|
||||
*
|
||||
* @param file
|
||||
* jar file to add
|
||||
* @throws IOException
|
||||
*/
|
||||
@Override
|
||||
public void addLibrary(File file) throws IOException {
|
||||
URL fileURL = file.toURI().toURL();
|
||||
addURL(fileURL);
|
||||
|
||||
JarFile jarFile = new JarFile(file);
|
||||
|
||||
Enumeration<JarEntry> entries = jarFile.entries();
|
||||
while (entries.hasMoreElements()) {
|
||||
JarEntry entry = entries.nextElement();
|
||||
|
||||
String name = entry.getName();
|
||||
if (name.endsWith(".class")) {
|
||||
name = name.substring(0, name.length() - 6);
|
||||
name = name.replace('/', '.');
|
||||
libraryClasses.add(name);
|
||||
}
|
||||
}
|
||||
|
||||
jarFile.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads class from library, parent or compiled
|
||||
*
|
||||
* @param name
|
||||
* class to load
|
||||
* @return loaded class
|
||||
* @throws ClassNotFoundException
|
||||
* if class not found
|
||||
*/
|
||||
@Override
|
||||
public Class<?> loadClass(String name) throws ClassNotFoundException {
|
||||
BinaryClass bc = classFileManager.getCompiledClasses().get(name);
|
||||
if (bc == null) {
|
||||
return super.loadClass(name, true);
|
||||
}
|
||||
|
||||
Class<?> c = bc.getDefinedClass();
|
||||
if (c == null) {
|
||||
byte[] b = bc.getBytes();
|
||||
c = super.defineClass(name, b, 0, b.length);
|
||||
bc.setDefinedClass(c);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public URL getResource(String name) {
|
||||
|
||||
if (!name.endsWith(".class")) {
|
||||
return super.getResource(name);
|
||||
} else {
|
||||
String newName = name.substring(0, name.length() - 6);
|
||||
newName = newName.replace('/', '.');
|
||||
if (classFileManager.getCompiledClasses().containsKey(newName)) {
|
||||
try {
|
||||
return new URL(null,
|
||||
VirtualClassURLStreamHandler.HANDLER_PROTOCOL
|
||||
+ newName, urlStreamHandler);
|
||||
} catch (MalformedURLException e) {
|
||||
log.error("Can't create url for compiled class", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return super.getResource(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Set<String> getLibraryClasses() {
|
||||
return Collections.unmodifiableSet(libraryClasses);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Set<String> getCompiledClasses() {
|
||||
Set<String> compiledClasses = classFileManager.getCompiledClasses()
|
||||
.keySet();
|
||||
return Collections.unmodifiableSet(compiledClasses);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns list of classes that are members of a package
|
||||
*
|
||||
* @param packageName
|
||||
* package to search for classes
|
||||
* @return list of classes that are package members
|
||||
* @throws IOException
|
||||
* if was unable to load class
|
||||
*/
|
||||
public Set<JavaFileObject> getClassesForPackage(String packageName)
|
||||
throws IOException {
|
||||
Set<JavaFileObject> result = new HashSet<JavaFileObject>();
|
||||
|
||||
// load parent
|
||||
ClassLoader parent = getParent();
|
||||
if (parent instanceof ScriptClassLoaderImpl) {
|
||||
ScriptClassLoaderImpl pscl = (ScriptClassLoaderImpl) parent;
|
||||
result.addAll(pscl.getClassesForPackage(packageName));
|
||||
}
|
||||
|
||||
// load current classloader compiled classes
|
||||
for (String cn : classFileManager.getCompiledClasses().keySet()) {
|
||||
if (ClassUtils.isPackageMember(cn, packageName)) {
|
||||
BinaryClass bc = classFileManager.getCompiledClasses().get(cn);
|
||||
result.add(bc);
|
||||
}
|
||||
}
|
||||
|
||||
// load libraries
|
||||
for (String cn : libraryClasses) {
|
||||
if (ClassUtils.isPackageMember(cn, packageName)) {
|
||||
BinaryClass bc = new BinaryClass(cn);
|
||||
try {
|
||||
byte[] data = getRawClassByName(cn);
|
||||
OutputStream os = bc.openOutputStream();
|
||||
os.write(data);
|
||||
} catch (IOException e) {
|
||||
log.error("Error while loading class from package "
|
||||
+ packageName, e);
|
||||
throw e;
|
||||
}
|
||||
result.add(bc);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds class with the specified name from the URL search path. Any URLs
|
||||
* referring to JAR files are loaded and opened as needed until the class is
|
||||
* found.
|
||||
*
|
||||
* @param name
|
||||
* the name of the class
|
||||
* @return the resulting class data
|
||||
* @throws IOException
|
||||
* if the class could not be found
|
||||
*/
|
||||
protected byte[] getRawClassByName(String name) throws IOException {
|
||||
URL resource = findResource(name.replace('.', '/').concat(".class"));
|
||||
InputStream is = null;
|
||||
byte[] clazz = null;
|
||||
|
||||
try {
|
||||
is = resource.openStream();
|
||||
clazz = IOUtils.toByteArray(is);
|
||||
} catch (IOException e) {
|
||||
log.error("Error while loading class data", e);
|
||||
throw e;
|
||||
} finally {
|
||||
if (is != null) {
|
||||
try {
|
||||
is.close();
|
||||
} catch (IOException e) {
|
||||
log.error("Error while closing stream", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return clazz;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
* 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.impl.javacc;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import javax.tools.DiagnosticListener;
|
||||
import javax.tools.JavaCompiler;
|
||||
import javax.tools.JavaFileObject;
|
||||
import javax.tools.ToolProvider;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.l2jserver.service.game.scripting.CompilationResult;
|
||||
import com.l2jserver.service.game.scripting.ScriptClassLoader;
|
||||
import com.l2jserver.service.game.scripting.ScriptCompiler;
|
||||
|
||||
/**
|
||||
* Wrapper for JavaCompiler api
|
||||
*
|
||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||
*/
|
||||
public class ScriptCompilerImpl implements ScriptCompiler {
|
||||
|
||||
/**
|
||||
* Logger for this class
|
||||
*/
|
||||
private static final Logger log = LoggerFactory
|
||||
.getLogger(ScriptCompilerImpl.class);
|
||||
|
||||
/**
|
||||
* Instance of JavaCompiler that will be used to compile classes
|
||||
*/
|
||||
protected final JavaCompiler javaCompiler;
|
||||
|
||||
/**
|
||||
* List of jar files
|
||||
*/
|
||||
protected Iterable<File> libraries;
|
||||
|
||||
/**
|
||||
* Parent classloader that has to be used for this compiler
|
||||
*/
|
||||
protected ScriptClassLoader parentClassLoader;
|
||||
|
||||
/**
|
||||
* Creates new instance of JavaCompilerImpl. If system compiler is not
|
||||
* available - throws RuntimeExcetion
|
||||
*
|
||||
* @throws RuntimeException
|
||||
* if compiler is not available
|
||||
*/
|
||||
public ScriptCompilerImpl() {
|
||||
this.javaCompiler = ToolProvider.getSystemJavaCompiler();
|
||||
|
||||
if (javaCompiler == null) {
|
||||
if (ToolProvider.getSystemJavaCompiler() != null) {
|
||||
throw new RuntimeException(new InstantiationException(
|
||||
"JavaCompiler is not aviable."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets parent classLoader for this JavaCompilerImpl
|
||||
*
|
||||
* @param classLoader
|
||||
* parent classloader
|
||||
*/
|
||||
@Override
|
||||
public void setParentClassLoader(ScriptClassLoader classLoader) {
|
||||
this.parentClassLoader = classLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets jar files that should be used for this compiler as libraries
|
||||
*
|
||||
* @param files
|
||||
* list of jar files
|
||||
*/
|
||||
@Override
|
||||
public void setLibraires(Iterable<File> files) {
|
||||
libraries = files;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles given class.
|
||||
*
|
||||
* @param className
|
||||
* Name of the class
|
||||
* @param sourceCode
|
||||
* source code
|
||||
* @return CompilationResult with the class
|
||||
* @throws RuntimeException
|
||||
* if compilation failed with errros
|
||||
*/
|
||||
@Override
|
||||
public CompilationResult compile(String className, String sourceCode) {
|
||||
return compile(new String[] { className }, new String[] { sourceCode });
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles list of classes. Amount of classNames must be equal to amount of
|
||||
* sourceCodes
|
||||
*
|
||||
* @param classNames
|
||||
* classNames
|
||||
* @param sourceCode
|
||||
* list of source codes
|
||||
* @return CompilationResult with needed files
|
||||
* @throws IllegalArgumentException
|
||||
* if size of classNames not equals to size of sourceCodes
|
||||
* @throws RuntimeException
|
||||
* if compilation failed with errros
|
||||
*/
|
||||
@Override
|
||||
public CompilationResult compile(String[] classNames, String[] sourceCode)
|
||||
throws IllegalArgumentException {
|
||||
|
||||
if (classNames.length != sourceCode.length) {
|
||||
throw new IllegalArgumentException(
|
||||
"Amount of classes is not equal to amount of sources");
|
||||
}
|
||||
|
||||
List<JavaFileObject> compilationUnits = new ArrayList<JavaFileObject>();
|
||||
|
||||
for (int i = 0; i < classNames.length; i++) {
|
||||
JavaFileObject compilationUnit = new JavaSourceFromString(
|
||||
classNames[i], sourceCode[i]);
|
||||
compilationUnits.add(compilationUnit);
|
||||
}
|
||||
|
||||
return doCompilation(compilationUnits);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles given files. Files must be java sources.
|
||||
*
|
||||
* @param compilationUnits
|
||||
* files to compile
|
||||
* @return CompilationResult with classes
|
||||
* @throws RuntimeException
|
||||
* if compilation failed with errros
|
||||
*/
|
||||
@Override
|
||||
public CompilationResult compile(Iterable<File> compilationUnits) {
|
||||
List<JavaFileObject> list = new ArrayList<JavaFileObject>();
|
||||
|
||||
for (File f : compilationUnits) {
|
||||
list.add(new JavaSourceFromFile(f, JavaFileObject.Kind.SOURCE));
|
||||
}
|
||||
|
||||
return doCompilation(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Actually performs compilation. Compiler expects sources in UTF-8
|
||||
* encoding. Also compiler generates full debugging info for classes.
|
||||
*
|
||||
* @param compilationUnits
|
||||
* Units that will be compiled
|
||||
* @return CompilationResult with compiledClasses
|
||||
* @throws RuntimeException
|
||||
* if compilation failed with errros
|
||||
*/
|
||||
protected CompilationResult doCompilation(
|
||||
Iterable<JavaFileObject> compilationUnits) {
|
||||
List<String> options = Arrays.asList("-encoding", "UTF-8", "-g");
|
||||
DiagnosticListener<JavaFileObject> listener = new ErrorListener();
|
||||
ClassFileManager manager = new ClassFileManager(javaCompiler, listener);
|
||||
manager.setParentClassLoader(parentClassLoader);
|
||||
|
||||
if (libraries != null) {
|
||||
try {
|
||||
manager.addLibraries(libraries);
|
||||
} catch (IOException e) {
|
||||
log.error("Can't set libraries for compiler.", e);
|
||||
}
|
||||
}
|
||||
|
||||
JavaCompiler.CompilationTask task = javaCompiler.getTask(null, manager,
|
||||
listener, options, null, compilationUnits);
|
||||
|
||||
if (!task.call()) {
|
||||
throw new RuntimeException("Error while compiling classes");
|
||||
}
|
||||
|
||||
ScriptClassLoader cl = manager.getClassLoader(null);
|
||||
Class<?>[] compiledClasses = classNamesToClasses(manager
|
||||
.getCompiledClasses().keySet(), cl);
|
||||
return new CompilationResult(compiledClasses, cl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reolves list of classes by their names
|
||||
*
|
||||
* @param classNames
|
||||
* names of the classes
|
||||
* @param cl
|
||||
* classLoader to use to resove classes
|
||||
* @return resolved classes
|
||||
* @throws RuntimeException
|
||||
* if can't find class
|
||||
*/
|
||||
protected Class<?>[] classNamesToClasses(Collection<String> classNames,
|
||||
ScriptClassLoader cl) {
|
||||
Class<?>[] classes = new Class<?>[classNames.size()];
|
||||
|
||||
int i = 0;
|
||||
for (String className : classNames) {
|
||||
try {
|
||||
Class<?> clazz = cl.loadClass(className);
|
||||
classes[i] = clazz;
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
return classes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Only java files are supported by java compiler
|
||||
*
|
||||
* @return "java";
|
||||
*/
|
||||
@Override
|
||||
public String[] getSupportedFileTypes() {
|
||||
return new String[] { "java" };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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.impl.javacc;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
|
||||
/**
|
||||
* This class represents URL Connection that is used to "connect" to scripts
|
||||
* binary data that was loaded by specified
|
||||
* {@link ScriptCompilerImpl}.<br>
|
||||
* <br>
|
||||
* TODO: Implement all methods of {@link URLConnection} to ensure valid
|
||||
* behaviour
|
||||
*
|
||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||
*/
|
||||
public class VirtualClassURLConnection extends URLConnection {
|
||||
|
||||
/**
|
||||
* Input stream, is assigned from class
|
||||
*/
|
||||
private InputStream is;
|
||||
|
||||
/**
|
||||
* Creates URL connections that "connects" to class binary data
|
||||
*
|
||||
* @param url
|
||||
* class name
|
||||
* @param cl
|
||||
* classloader
|
||||
*/
|
||||
protected VirtualClassURLConnection(URL url, ScriptClassLoaderImpl cl) {
|
||||
super(url);
|
||||
BinaryClass bc = cl.getClassFileManager().getCompiledClasses()
|
||||
.get(url.getHost());
|
||||
byte[] b = new byte[bc.getBytes().length];
|
||||
System.arraycopy(bc.getBytes(), 0, b, 0, b.length);
|
||||
is = new ByteArrayInputStream(b);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is ignored
|
||||
*/
|
||||
@Override
|
||||
public void connect() throws IOException {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public InputStream getInputStream() throws IOException {
|
||||
return is;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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.impl.javacc;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLStreamHandler;
|
||||
|
||||
/**
|
||||
* This class represents URL Stream handler that accepts
|
||||
* {@value #HANDLER_PROTOCOL} protocol
|
||||
*
|
||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||
*/
|
||||
public class VirtualClassURLStreamHandler extends URLStreamHandler {
|
||||
|
||||
/**
|
||||
* Script Handler protocol for classes compiled from source
|
||||
*/
|
||||
public static final String HANDLER_PROTOCOL = "aescript://";
|
||||
|
||||
/**
|
||||
* Script class loader that loaded those classes
|
||||
*/
|
||||
private final ScriptClassLoaderImpl cl;
|
||||
|
||||
/**
|
||||
* Creates new instance of url stream handler with given classloader
|
||||
*
|
||||
* @param cl
|
||||
* ScriptClassLoaderImpl that was used to load compiled class
|
||||
*/
|
||||
public VirtualClassURLStreamHandler(ScriptClassLoaderImpl cl) {
|
||||
this.cl = cl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens new URL connection for URL
|
||||
*
|
||||
* @param u
|
||||
* url
|
||||
* @return Opened connection
|
||||
* @throws IOException
|
||||
* never thrown
|
||||
*/
|
||||
@Override
|
||||
protected URLConnection openConnection(URL u) throws IOException {
|
||||
return new VirtualClassURLConnection(u, cl);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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 {
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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 {
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* 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.List;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
import com.l2jserver.service.game.scripting.impl.javacc.ScriptCompilerImpl;
|
||||
|
||||
/**
|
||||
* Simple class that represents script info.<br>
|
||||
* <br>
|
||||
* It contains Script root, list of libraries and list of child contexes
|
||||
*
|
||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||
*/
|
||||
@XmlRootElement(name = "scriptinfo")
|
||||
@XmlAccessorType(XmlAccessType.NONE)
|
||||
public class ScriptInfo {
|
||||
/**
|
||||
* Root of this script context. Child directories of root will be scanned
|
||||
* for script files
|
||||
*/
|
||||
@XmlAttribute(required = true)
|
||||
private File root;
|
||||
|
||||
/**
|
||||
* List of libraries of this script context
|
||||
*/
|
||||
@XmlElement(name = "library")
|
||||
private List<File> libraries;
|
||||
|
||||
/**
|
||||
* List of child contexts
|
||||
*/
|
||||
@XmlElement(name = "scriptinfo")
|
||||
private List<ScriptInfo> scriptInfos;
|
||||
|
||||
/**
|
||||
* Default compiler class name.
|
||||
*/
|
||||
@XmlElement(name = "compiler")
|
||||
private String compilerClass = ScriptCompilerImpl.class.getName();
|
||||
|
||||
/**
|
||||
* Returns root of script context
|
||||
*
|
||||
* @return root of script context
|
||||
*/
|
||||
public File getRoot() {
|
||||
return root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets root for script context
|
||||
*
|
||||
* @param root
|
||||
* root for script context
|
||||
*/
|
||||
public void setRoot(File root) {
|
||||
this.root = root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns list of libraries that will be used byscript context and it's
|
||||
* children
|
||||
*
|
||||
* @return lib of libraries
|
||||
*/
|
||||
public List<File> getLibraries() {
|
||||
return libraries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets list of libraries that will be used by script context and it's
|
||||
* children
|
||||
*
|
||||
* @param libraries
|
||||
* sets list of libraries
|
||||
*/
|
||||
public void setLibraries(List<File> libraries) {
|
||||
this.libraries = libraries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return list of child context descriptors
|
||||
*
|
||||
* @return list of child context descriptors
|
||||
*/
|
||||
public List<ScriptInfo> getScriptInfos() {
|
||||
return scriptInfos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets list of child context descriptors
|
||||
*
|
||||
* @param scriptInfos
|
||||
* list of child context descriptors
|
||||
*/
|
||||
public void setScriptInfos(List<ScriptInfo> scriptInfos) {
|
||||
this.scriptInfos = scriptInfos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns compiler class name
|
||||
*
|
||||
* @return name of compiler class
|
||||
*/
|
||||
public String getCompilerClass() {
|
||||
return compilerClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets compiler class name
|
||||
*
|
||||
* @param compilerClass
|
||||
* name of compiler class
|
||||
*/
|
||||
public void setCompilerClass(String compilerClass) {
|
||||
this.compilerClass = compilerClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if roots are quals
|
||||
*
|
||||
* @param o
|
||||
* object to compare with
|
||||
* @return true if this ScriptInfo and anothers ScriptInfo has same root
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o)
|
||||
return true;
|
||||
if (o == null || getClass() != o.getClass())
|
||||
return false;
|
||||
|
||||
ScriptInfo that = (ScriptInfo) o;
|
||||
|
||||
return root.equals(that.root);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns hashcode of root
|
||||
*
|
||||
* @return hashcode of root
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return root.hashCode();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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.util.Set;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
/**
|
||||
* Root element for script descriptors
|
||||
*
|
||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||
*/
|
||||
@XmlRootElement(name = "scriptlist")
|
||||
@XmlAccessorType(XmlAccessType.NONE)
|
||||
public class ScriptList {
|
||||
/**
|
||||
* List of Script descriptors
|
||||
*/
|
||||
@XmlElement(name = "scriptinfo", type = ScriptInfo.class)
|
||||
private Set<ScriptInfo> scriptInfos;
|
||||
|
||||
/**
|
||||
* Returns list of script descriptors
|
||||
*
|
||||
* @return list of script descriptors
|
||||
*/
|
||||
public Set<ScriptInfo> getScriptInfos() {
|
||||
return scriptInfos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets list of script descriptors
|
||||
*
|
||||
* @param scriptInfos
|
||||
* lisft of script descriptors
|
||||
*/
|
||||
public void setScriptInfos(Set<ScriptInfo> scriptInfos) {
|
||||
this.scriptInfos = scriptInfos;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* 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("st/contexts.xml"));
|
||||
* ...
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
94
src/main/java/com/l2jserver/util/ClassUtils.java
Normal file
94
src/main/java/com/l2jserver/util/ClassUtils.java
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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.util;
|
||||
|
||||
/**
|
||||
* This class contains utilities that are used when we are working with classes
|
||||
*
|
||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||
*/
|
||||
public class ClassUtils {
|
||||
/**
|
||||
* Return true if class a is either equivalent to class b, or if class a is
|
||||
* a subclass of class b, i.e. if a either "extends" or "implements" b. Note
|
||||
* tht either or both "Class" objects may represent interfaces.
|
||||
*
|
||||
* @param a
|
||||
* class
|
||||
* @param b
|
||||
* class
|
||||
* @return true if a == b or a extends b or a implements b
|
||||
*/
|
||||
public static boolean isSubclass(Class<?> a, Class<?> b) {
|
||||
// We rely on the fact that for any given java class or
|
||||
// primtitive type there is a unqiue Class object, so
|
||||
// we can use object equivalence in the comparisons.
|
||||
if (a == b) {
|
||||
return true;
|
||||
}
|
||||
if (a == null || b == null) {
|
||||
return false;
|
||||
}
|
||||
for (Class<?> x = a; x != null; x = x.getSuperclass()) {
|
||||
if (x == b) {
|
||||
return true;
|
||||
}
|
||||
if (b.isInterface()) {
|
||||
Class<?> interfaces[] = x.getInterfaces();
|
||||
for (Class<?> anInterface : interfaces) {
|
||||
if (isSubclass(anInterface, b)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if class in member of the package
|
||||
*
|
||||
* @param clazz
|
||||
* class to check
|
||||
* @param packageName
|
||||
* package
|
||||
* @return true if is member
|
||||
*/
|
||||
public static boolean isPackageMember(Class<?> clazz, String packageName) {
|
||||
return isPackageMember(clazz.getName(), packageName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if classNames belongs to package
|
||||
*
|
||||
* @param className
|
||||
* class name
|
||||
* @param packageName
|
||||
* package
|
||||
* @return true if belongs
|
||||
*/
|
||||
public static boolean isPackageMember(String className, String packageName) {
|
||||
if (!className.contains(".")) {
|
||||
return packageName == null || packageName.isEmpty();
|
||||
} else {
|
||||
String classPackage = className.substring(0,
|
||||
className.lastIndexOf('.'));
|
||||
return packageName.equals(classPackage);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,9 +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.mysql5.DAOModuleMySQL5;
|
||||
import com.l2jserver.model.id.CharacterID;
|
||||
import com.l2jserver.model.id.ID;
|
||||
import com.l2jserver.model.world.L2Character;
|
||||
|
||||
@@ -7,11 +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.mysql5.DAOModuleMySQL5;
|
||||
import com.l2jserver.model.id.factory.CharacterIDFactory;
|
||||
import com.l2jserver.model.id.factory.IDFactoryModule;
|
||||
import com.l2jserver.model.id.factory.ItemIDFactory;
|
||||
|
||||
Reference in New Issue
Block a user