diff --git a/config/config.xml b/config/config.xml new file mode 100644 index 000000000..6397b0c4f --- /dev/null +++ b/config/config.xml @@ -0,0 +1,72 @@ + + + + + + + + 1.0 + + 1.0 + + + + + + + + + + jdbc:mysql://localhost/l2jserver2 + + + com.mysql.jdbc.Driver + + + l2j + + + changeme + + + + + 20 + + 20 + + 5 + + + + + + + 0.0.0.0:7777 + + + + + + + + + + + + \ No newline at end of file diff --git a/config/database.properties b/config/properties/database.properties similarity index 100% rename from config/database.properties rename to config/properties/database.properties diff --git a/config/template.properties b/config/properties/template.properties similarity index 100% rename from config/template.properties rename to config/properties/template.properties diff --git a/config/vfs.properties b/config/properties/vfs.properties similarity index 100% rename from config/vfs.properties rename to config/properties/vfs.properties diff --git a/dist/config/config.xml b/dist/config/config.xml new file mode 100644 index 000000000..6397b0c4f --- /dev/null +++ b/dist/config/config.xml @@ -0,0 +1,72 @@ + + + + + + + + 1.0 + + 1.0 + + + + + + + + + + jdbc:mysql://localhost/l2jserver2 + + + com.mysql.jdbc.Driver + + + l2j + + + changeme + + + + + 20 + + 20 + + 5 + + + + + + + 0.0.0.0:7777 + + + + + + + + + + + + \ No newline at end of file diff --git a/dist/config/database.properties b/dist/config/properties/database.properties similarity index 100% rename from dist/config/database.properties rename to dist/config/properties/database.properties diff --git a/dist/config/template.properties b/dist/config/properties/template.properties similarity index 100% rename from dist/config/template.properties rename to dist/config/properties/template.properties diff --git a/dist/config/vfs.properties b/dist/config/properties/vfs.properties similarity index 100% rename from dist/config/vfs.properties rename to dist/config/properties/vfs.properties diff --git a/src/main/java/com/l2jserver/game/net/handler/Lineage2PacketHandler.java b/src/main/java/com/l2jserver/game/net/handler/Lineage2PacketHandler.java index 801108e4c..7b90a797e 100644 --- a/src/main/java/com/l2jserver/game/net/handler/Lineage2PacketHandler.java +++ b/src/main/java/com/l2jserver/game/net/handler/Lineage2PacketHandler.java @@ -124,7 +124,7 @@ public class Lineage2PacketHandler extends SimpleChannelHandler { body.text(exception); } }; - connection.sendCommunityHTML(template); + connection.sendHTML(template); // order client not to wait any packet connection.sendActionFailed(); diff --git a/src/main/java/com/l2jserver/service/configuration/Configuration.java b/src/main/java/com/l2jserver/service/configuration/Configuration.java index 819d1d56b..d651f3911 100644 --- a/src/main/java/com/l2jserver/service/configuration/Configuration.java +++ b/src/main/java/com/l2jserver/service/configuration/Configuration.java @@ -16,12 +16,13 @@ */ package com.l2jserver.service.configuration; -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.configuration.ProxyConfigurationService.ConfigurationName; + /** * Configuration interface *

@@ -35,23 +36,6 @@ import java.lang.annotation.Target; * @author Rogiel */ public interface Configuration { - /** - * Each configuration can define the name of its configuration. This will be - * used by implementations to look for the configuration. - * - * @author Rogiel - * - */ - @Retention(RetentionPolicy.RUNTIME) - @Documented - @Target(value = ElementType.TYPE) - public @interface ConfigurationName { - /** - * @return the configuration name - */ - String value(); - } - /** * The getter method for an configuration property *

@@ -62,11 +46,6 @@ public interface Configuration { @Retention(RetentionPolicy.RUNTIME) @Target(value = ElementType.METHOD) public @interface ConfigurationPropertyGetter { - /** - * @return the property name - */ - String name(); - /** * @return the default value to be used */ @@ -83,9 +62,5 @@ public interface Configuration { @Retention(RetentionPolicy.RUNTIME) @Target(value = ElementType.METHOD) public @interface ConfigurationPropertySetter { - /** - * @return the property name - */ - String name(); } } diff --git a/src/main/java/com/l2jserver/service/configuration/ProxyConfigurationService.java b/src/main/java/com/l2jserver/service/configuration/ProxyConfigurationService.java index 1cc1bba3b..417ffc692 100644 --- a/src/main/java/com/l2jserver/service/configuration/ProxyConfigurationService.java +++ b/src/main/java/com/l2jserver/service/configuration/ProxyConfigurationService.java @@ -21,6 +21,11 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.lang.annotation.Annotation; +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 java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; @@ -35,7 +40,6 @@ import com.l2jserver.service.AbstractService; import com.l2jserver.service.AbstractService.Depends; import com.l2jserver.service.ServiceStartException; import com.l2jserver.service.cache.CacheService; -import com.l2jserver.service.configuration.Configuration.ConfigurationName; import com.l2jserver.service.configuration.Configuration.ConfigurationPropertyGetter; import com.l2jserver.service.configuration.Configuration.ConfigurationPropertySetter; import com.l2jserver.service.core.LoggingService; @@ -55,7 +59,7 @@ public class ProxyConfigurationService extends AbstractService implements /** * The directory in which configuration files are stored */ - private final File directory = new File("./config"); + private final File directory = new File("./config/properties"); /** * The logger */ @@ -66,6 +70,30 @@ public class ProxyConfigurationService extends AbstractService implements */ private Map, Object> cache = CollectionFactory.newWeakMap(); + @Retention(RetentionPolicy.RUNTIME) + @Documented + @Target(value = ElementType.METHOD) + public @interface ConfigurationPropertiesKey { + String value(); + } + + /** + * Each configuration can define the name of its configuration. This will be + * used by implementations to look for the configuration. + * + * @author Rogiel + * + */ + @Retention(RetentionPolicy.RUNTIME) + @Documented + @Target(value = ElementType.TYPE) + public @interface ConfigurationName { + /** + * @return the configuration name + */ + String value(); + } + @Override protected void doStart() throws ServiceStartException { if (!directory.exists()) @@ -128,15 +156,23 @@ public class ProxyConfigurationService extends AbstractService implements if (args == null || args.length == 0) { final ConfigurationPropertyGetter getter = method .getAnnotation(ConfigurationPropertyGetter.class); + final ConfigurationPropertiesKey propertiesKey = method + .getAnnotation(ConfigurationPropertiesKey.class); if (getter == null) return null; - return get(getter, method.getReturnType()); + if (propertiesKey == null) + return null; + return get(getter, propertiesKey, method.getReturnType()); } else if (args.length == 1) { final ConfigurationPropertySetter setter = method .getAnnotation(ConfigurationPropertySetter.class); + final ConfigurationPropertiesKey propertiesKey = method + .getAnnotation(ConfigurationPropertiesKey.class); if (setter == null) return null; - set(setter, args[0], method.getParameterTypes()[0]); + if (propertiesKey == null) + return null; + set(propertiesKey, args[0], method.getParameterTypes()[0]); } return null; } @@ -146,16 +182,19 @@ public class ProxyConfigurationService extends AbstractService implements * * @param getter * the getter annotation + * @param propertiesKey + * if properties key annotation * @param type * the transformed type * @return the untransformed property */ - private Object get(ConfigurationPropertyGetter getter, Class type) { - if (cache.containsKey(getter.name())) - return cache.get(getter.name()); + private Object get(ConfigurationPropertyGetter getter, + ConfigurationPropertiesKey propertiesKey, Class type) { + if (cache.containsKey(propertiesKey.value())) + return cache.get(propertiesKey.value()); Object o = untransform( - getRaw(getter.name(), getter.defaultValue()), type); - cache.put(getter.name(), o); + getRaw(propertiesKey.value(), getter.defaultValue()), type); + cache.put(propertiesKey.value(), o); return o; } @@ -169,15 +208,15 @@ public class ProxyConfigurationService extends AbstractService implements * @param type * the transformed type */ - private void set(ConfigurationPropertySetter setter, Object value, + private void set(ConfigurationPropertiesKey setter, Object value, Class type) { if (value != null) { - properties.setProperty(setter.name(), + properties.setProperty(setter.value(), transform(value.toString(), type)); - cache.remove(setter.name()); + cache.remove(setter.value()); } else { - properties.remove(setter.name()); - cache.remove(setter.name()); + properties.remove(setter.value()); + cache.remove(setter.value()); } } diff --git a/src/main/java/com/l2jserver/service/configuration/XMLConfigurationService.java b/src/main/java/com/l2jserver/service/configuration/XMLConfigurationService.java new file mode 100644 index 000000000..75027aa8b --- /dev/null +++ b/src/main/java/com/l2jserver/service/configuration/XMLConfigurationService.java @@ -0,0 +1,343 @@ +/* + * This file is part of l2jserver . + * + * l2jserver is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * l2jserver is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with l2jserver. If not, see . + */ +package com.l2jserver.service.configuration; + +import java.io.File; +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.Map; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.xml.sax.SAXException; + +import com.google.common.base.Preconditions; +import com.google.inject.Inject; +import com.l2jserver.service.AbstractService; +import com.l2jserver.service.AbstractService.Depends; +import com.l2jserver.service.ServiceStartException; +import com.l2jserver.service.cache.CacheService; +import com.l2jserver.service.configuration.Configuration.ConfigurationPropertyGetter; +import com.l2jserver.service.core.LoggingService; +import com.l2jserver.util.factory.CollectionFactory; +import com.l2jserver.util.transformer.Transformer; +import com.l2jserver.util.transformer.TransformerFactory; + +/** + * Creates {@link Configuration} object through Java {@link Proxy}. Uses the + * annotations in the interface to retrieve and store values. + * + * @author Rogiel + */ +@Depends({ LoggingService.class, CacheService.class }) +public class XMLConfigurationService extends AbstractService implements + ConfigurationService { + /** + * The directory in which configuration files are stored + */ + private File file = new File("./config/config.xml"); + /** + * The logger + */ + private final Logger log = LoggerFactory.getLogger(this.getClass()); + + /** + * The DOM {@link DocumentBuilderFactory} + */ + private DocumentBuilderFactory factory; + /** + * The DOM {@link DocumentBuilder} + */ + private DocumentBuilder builder; + + private Document properties; + + /** + * The cache of configuration objects + */ + private Map, Object> cache = CollectionFactory.newWeakMap(); + + @Retention(RetentionPolicy.RUNTIME) + public @interface ConfigurationXPath { + String value(); + } + + /** + * Creates a new empty instance + */ + @Inject + protected XMLConfigurationService() { + } + + /** + * Creates a new service instance. This is used for tests + * + * @param file + * the configuration file + */ + protected XMLConfigurationService(File file) { + this.file = file; + } + + @Override + protected void doStart() throws ServiceStartException { + factory = DocumentBuilderFactory.newInstance(); + try { + builder = factory.newDocumentBuilder(); + properties = builder.parse(file); + } catch (ParserConfigurationException e) { + throw new ServiceStartException(e); + } catch (SAXException e) { + throw new ServiceStartException(e); + } catch (IOException e) { + throw new ServiceStartException(e); + } + } + + @Override + @SuppressWarnings("unchecked") + public C get(Class config) { + Preconditions.checkNotNull(config, "config"); + + if (cache.containsKey(config)) + return (C) cache.get(config); + log.debug("Trying to create {} proxy", config); + + C proxy = (C) Proxy.newProxyInstance(this.getClass().getClassLoader(), + new Class[] { config }, new ConfigInvocationHandler( + properties)); + cache.put(config, proxy); + return proxy; + } + + /** + * The invocation handler for configuration interfaces + * + * @author Rogiel + */ + private class ConfigInvocationHandler implements InvocationHandler { + /** + * The invocation handler properties + */ + private final Document properties; + /** + * The invocation cache + */ + private Map cache = CollectionFactory.newWeakMap(); + + /** + * @param properties + * the properties + */ + public ConfigInvocationHandler(Document properties) { + this.properties = properties; + } + + @Override + public Object invoke(Object proxy, Method method, Object[] args) + throws Throwable { + log.debug("Configuration service, method invoked: {}", + method.getName()); + if (args == null || args.length == 0) { + final ConfigurationPropertyGetter getter = method + .getAnnotation(ConfigurationPropertyGetter.class); + final ConfigurationXPath xpath = method + .getAnnotation(ConfigurationXPath.class); + if (getter == null) + return null; + if (xpath == null) + return null; + return get(getter, xpath, method.getReturnType()); + } else if (args.length == 1) { + final ConfigurationXPath xpath = method + .getAnnotation(ConfigurationXPath.class); + if (xpath == null) + return null; + set(xpath, args[0], method.getParameterTypes()[0]); + } + return null; + } + + /** + * Get the untransformed value of an property + * + * @param getter + * the getter annotation + * @param xpath + * the xpath annotation + * @param type + * the transformed type + * @return the untransformed property + */ + private Object get(ConfigurationPropertyGetter getter, + ConfigurationXPath xpath, Class type) { + if (cache.containsKey(xpath.value())) + return cache.get(xpath.value()); + Object o; + try { + o = untransform(getRaw(xpath.value(), getter.defaultValue()), + type); + } catch (XPathExpressionException e) { + return null; + } + cache.put(xpath.value(), o); + return o; + } + + /** + * Set the transformed value of an property + * + * @param xpath + * the xpath annotation + * @param value + * the untransformed value + * @param type + * the transformed type + * @throws XPathExpressionException + * if any error occur while compiling the XPath + */ + private void set(ConfigurationXPath xpath, Object value, Class type) + throws XPathExpressionException { + Node node = (Node) XPathFactory.newInstance().newXPath() + .compile(xpath.value()) + .evaluate(properties, XPathConstants.NODE); + if (value != null) { + node.setNodeValue(transform(value.toString(), type)); + cache.put(xpath.value(), value); + } else { + node.getParentNode().removeChild(node); + cache.remove(xpath.value()); + } + } + + /** + * Untransforms an value + * + * @param value + * the raw value + * @param type + * the output type + * @return the untransformed value + */ + private Object untransform(String value, Class type) { + if (value == null) + return null; + if (type == String.class) + return value; + final Transformer transformer = TransformerFactory + .getTransfromer(type); + if (transformer == null) + return null; + return transformer.untransform(value); + } + + /** + * Transforms an value + * + * @param value + * the raw typed value + * @param type + * the input type + * @return the string representing value + */ + @SuppressWarnings({ "rawtypes", "unchecked" }) + private String transform(Object value, Class type) { + if (value == null) + return null; + if (value instanceof String) + return (String) value; + final Transformer transformer = TransformerFactory + .getTransfromer(type); + if (transformer == null) + return null; + return transformer.transform(value); + } + + /** + * Retrieve the raw value from the property file + * + * @param key + * the key + * @param defaultValue + * the default value + * @return the value found or default value + * @throws XPathExpressionException + * if any XPath exception occur + */ + private String getRaw(String key, String defaultValue) + throws XPathExpressionException { + if (properties == null) + return defaultValue; + String value = XPathFactory.newInstance().newXPath() + .evaluate(key, properties); + if (value == null || value.length() == 0) + return defaultValue; + return value; + } + } + + /** + * Tries to find an annotation in the class or any parent-class. + * + * @param + * the annotation type + * @param annotationClass + * the annotation class + * @param clazz + * the class to look for annotations + * @return the annotation found + */ + private T findAnnotation(Class annotationClass, + Class clazz) { + Preconditions.checkNotNull(annotationClass, "annotationClass"); + Preconditions.checkNotNull(clazz, "clazz"); + + T ann = clazz.getAnnotation(annotationClass); + if (ann != null) + return ann; + + for (Class clazz2 : annotationClass.getInterfaces()) { + if (clazz2 == clazz) + continue; + ann = findAnnotation(annotationClass, clazz2); + if (ann != null) + return ann; + } + return null; + } + + /** + * @return the configuration store directory + */ + public File getFile() { + return file; + } +} diff --git a/src/main/java/com/l2jserver/service/core/vfs/VFSService.java b/src/main/java/com/l2jserver/service/core/vfs/VFSService.java index b29211abd..fedcf162b 100644 --- a/src/main/java/com/l2jserver/service/core/vfs/VFSService.java +++ b/src/main/java/com/l2jserver/service/core/vfs/VFSService.java @@ -22,7 +22,9 @@ import java.nio.file.Path; import com.l2jserver.service.Service; import com.l2jserver.service.ServiceConfiguration; import com.l2jserver.service.configuration.Configuration; -import com.l2jserver.service.configuration.Configuration.ConfigurationName; +import com.l2jserver.service.configuration.ProxyConfigurationService.ConfigurationName; +import com.l2jserver.service.configuration.ProxyConfigurationService.ConfigurationPropertiesKey; +import com.l2jserver.service.configuration.XMLConfigurationService.ConfigurationXPath; /** * The VFS service is responsible for creating a Virtual File System that is @@ -42,14 +44,18 @@ public interface VFSService extends Service { /** * @return the VFS root {@link URI} */ - @ConfigurationPropertyGetter(name = "vfs.root", defaultValue = "") + @ConfigurationPropertyGetter(defaultValue = "") + @ConfigurationPropertiesKey("vfs.root") + @ConfigurationXPath("/configuration/services/vfs/root") Path getRoot(); /** * @param root * the new VFS root {@link URI} */ - @ConfigurationPropertySetter(name = "vfs.root") + @ConfigurationPropertySetter + @ConfigurationPropertiesKey("vfs.root") + @ConfigurationXPath("/configuration/services/vfs/root") void setRoot(Path root); } diff --git a/src/main/java/com/l2jserver/service/database/DatabaseService.java b/src/main/java/com/l2jserver/service/database/DatabaseService.java index f0522c412..d04698857 100644 --- a/src/main/java/com/l2jserver/service/database/DatabaseService.java +++ b/src/main/java/com/l2jserver/service/database/DatabaseService.java @@ -21,7 +21,7 @@ import com.l2jserver.model.id.ID; import com.l2jserver.service.Service; import com.l2jserver.service.ServiceConfiguration; import com.l2jserver.service.configuration.Configuration; -import com.l2jserver.service.configuration.Configuration.ConfigurationName; +import com.l2jserver.service.configuration.ProxyConfigurationService.ConfigurationName; /** * This service provides access to an database implementation. Each diff --git a/src/main/java/com/l2jserver/service/database/JDBCDatabaseService.java b/src/main/java/com/l2jserver/service/database/JDBCDatabaseService.java index e3e26f2c8..59889a55e 100644 --- a/src/main/java/com/l2jserver/service/database/JDBCDatabaseService.java +++ b/src/main/java/com/l2jserver/service/database/JDBCDatabaseService.java @@ -60,6 +60,8 @@ import com.l2jserver.service.ServiceStopException; import com.l2jserver.service.cache.Cache; import com.l2jserver.service.cache.CacheService; import com.l2jserver.service.configuration.ConfigurationService; +import com.l2jserver.service.configuration.ProxyConfigurationService.ConfigurationPropertiesKey; +import com.l2jserver.service.configuration.XMLConfigurationService.ConfigurationXPath; import com.l2jserver.service.core.LoggingService; import com.l2jserver.service.core.threading.ScheduledAsyncFuture; import com.l2jserver.service.core.threading.ThreadService; @@ -155,92 +157,120 @@ public class JDBCDatabaseService extends AbstractService implements /** * @return the jdbc url */ - @ConfigurationPropertyGetter(name = "jdbc.url", defaultValue = "jdbc:mysql://localhost/l2jserver2") + @ConfigurationPropertyGetter(defaultValue = "jdbc:mysql://localhost/l2jserver2") + @ConfigurationPropertiesKey("jdbc.url") + @ConfigurationXPath("/configuration/services/database/jdbc/url") String getJdbcUrl(); /** * @param jdbcUrl * the new jdbc url */ - @ConfigurationPropertySetter(name = "jdbc.url") + @ConfigurationPropertySetter + @ConfigurationPropertiesKey("jdbc.url") + @ConfigurationXPath("/configuration/services/database/jdbc/url") void setJdbcUrl(String jdbcUrl); /** * @return the jdbc driver class */ - @ConfigurationPropertyGetter(name = "jdbc.driver", defaultValue = "com.jdbc.jdbc.Driver") + @ConfigurationPropertyGetter(defaultValue = "com.jdbc.jdbc.Driver") + @ConfigurationPropertiesKey("jdbc.driver") + @ConfigurationXPath("/configuration/services/database/jdbc/driver") String getDriver(); /** * @param driver * the new jdbc driver */ - @ConfigurationPropertySetter(name = "jdbc.driver") + @ConfigurationPropertySetter + @ConfigurationPropertiesKey("jdbc.driver") + @ConfigurationXPath("/configuration/services/database/jdbc/driver") void setDriver(Class driver); /** * @return the jdbc database username */ - @ConfigurationPropertyGetter(name = "jdbc.username", defaultValue = "l2j") + @ConfigurationPropertyGetter(defaultValue = "l2j") + @ConfigurationPropertiesKey("jdbc.username") + @ConfigurationXPath("/configuration/services/database/jdbc/username") String getUsername(); /** * @param username * the jdbc database username */ - @ConfigurationPropertySetter(name = "jdbc.username") + @ConfigurationPropertySetter + @ConfigurationPropertiesKey("jdbc.username") + @ConfigurationXPath("/configuration/services/database/jdbc/username") void setUsername(String username); /** * @return the jdbc database password */ - @ConfigurationPropertyGetter(name = "jdbc.password", defaultValue = "changeme") + @ConfigurationPropertyGetter(defaultValue = "changeme") + @ConfigurationPropertiesKey("jdbc.password") + @ConfigurationXPath("/configuration/services/database/jdbc/password") String getPassword(); /** * @param password * the jdbc database password */ - @ConfigurationPropertySetter(name = "jdbc.password") + @ConfigurationPropertySetter + @ConfigurationPropertiesKey("jdbc.password") + @ConfigurationXPath("/configuration/services/database/jdbc/password") void setPassword(String password); /** * @return the maximum number of active connections */ - @ConfigurationPropertyGetter(name = "jdbc.active.max", defaultValue = "20") + @ConfigurationPropertyGetter(defaultValue = "20") + @ConfigurationPropertiesKey("jdbc.active.max") + @ConfigurationXPath("/configuration/services/database/connections/active-maximum") int getMaxActiveConnections(); /** * @param password * the maximum number of active connections */ - @ConfigurationPropertySetter(name = "jdbc.active.max") + @ConfigurationPropertySetter + @ConfigurationPropertiesKey("jdbc.active.max") + @ConfigurationXPath("/configuration/services/database/connections/active-maximum") void setMaxActiveConnections(int password); /** * @return the maximum number of idle connections */ - @ConfigurationPropertyGetter(name = "jdbc.idle.max", defaultValue = "20") + @ConfigurationPropertyGetter(defaultValue = "20") + @ConfigurationPropertiesKey("jdbc.idle.max") + @ConfigurationXPath("/configuration/services/database/connections/idle-maximum") int getMaxIdleConnections(); /** * @param password * the maximum number of idle connections */ - @ConfigurationPropertySetter(name = "jdbc.idle.max") + @ConfigurationPropertySetter + @ConfigurationPropertiesKey("jdbc.idle.max") + @ConfigurationXPath("/configuration/services/database/connections/idle-maximum") void setMaxIdleConnections(int password); /** * @return the minimum number of idle connections */ - @ConfigurationPropertyGetter(name = "jdbc.idle.min", defaultValue = "5") + @ConfigurationPropertyGetter(defaultValue = "5") + @ConfigurationPropertiesKey("jdbc.idle.min") + @ConfigurationXPath("/configuration/services/database/connections/idle-minimum") int getMinIdleConnections(); /** * @param password * the minimum number of idle connections */ - @ConfigurationPropertySetter(name = "jdbc.idle.min") + @ConfigurationPropertySetter + @ConfigurationPropertiesKey("jdbc.idle.min") + @ConfigurationXPath("/configuration/services/database/connections/idle-minimum") void setMinIdleConnections(int password); } diff --git a/src/main/java/com/l2jserver/service/game/template/XMLTemplateService.java b/src/main/java/com/l2jserver/service/game/template/XMLTemplateService.java index f8d1f0ae6..35e0d87d1 100644 --- a/src/main/java/com/l2jserver/service/game/template/XMLTemplateService.java +++ b/src/main/java/com/l2jserver/service/game/template/XMLTemplateService.java @@ -54,8 +54,10 @@ import com.l2jserver.service.ServiceStartException; import com.l2jserver.service.ServiceStopException; import com.l2jserver.service.cache.Cache; import com.l2jserver.service.cache.CacheService; -import com.l2jserver.service.configuration.Configuration.ConfigurationName; import com.l2jserver.service.configuration.ConfigurationService; +import com.l2jserver.service.configuration.ProxyConfigurationService.ConfigurationName; +import com.l2jserver.service.configuration.ProxyConfigurationService.ConfigurationPropertiesKey; +import com.l2jserver.service.configuration.XMLConfigurationService.ConfigurationXPath; import com.l2jserver.service.core.LoggingService; import com.l2jserver.service.core.vfs.VFSService; import com.l2jserver.util.jaxb.CharacterTemplateIDAdapter; @@ -139,14 +141,18 @@ public class XMLTemplateService extends AbstractService implements /** * @return the directory in which templates are stored */ - @ConfigurationPropertyGetter(name = "template.directory", defaultValue = "data/templates") + @ConfigurationPropertyGetter(defaultValue = "data/templates") + @ConfigurationPropertiesKey("template.directory") + @ConfigurationXPath("/configuration/services/template/directory") URI getTemplateDirectory(); /** * @param file * the directory in which templates are stored */ - @ConfigurationPropertySetter(name = "template.directory") + @ConfigurationPropertySetter + @ConfigurationPropertiesKey("template.directory") + @ConfigurationXPath("/configuration/services/template/directory") void setTemplateDirectory(URI file); } diff --git a/src/main/java/com/l2jserver/service/network/NetworkService.java b/src/main/java/com/l2jserver/service/network/NetworkService.java index c187857e3..a8760da12 100644 --- a/src/main/java/com/l2jserver/service/network/NetworkService.java +++ b/src/main/java/com/l2jserver/service/network/NetworkService.java @@ -27,7 +27,9 @@ import com.l2jserver.model.world.L2Character; import com.l2jserver.service.Service; import com.l2jserver.service.ServiceConfiguration; import com.l2jserver.service.configuration.Configuration; -import com.l2jserver.service.configuration.Configuration.ConfigurationName; +import com.l2jserver.service.configuration.ProxyConfigurationService.ConfigurationName; +import com.l2jserver.service.configuration.ProxyConfigurationService.ConfigurationPropertiesKey; +import com.l2jserver.service.configuration.XMLConfigurationService.ConfigurationXPath; /** * The network service is responsible for communicating the server with the game @@ -78,7 +80,9 @@ public interface NetworkService extends Service { * * @return the listen address */ - @ConfigurationPropertyGetter(name = "listen", defaultValue = "0.0.0.0:7777") + @ConfigurationPropertyGetter(defaultValue = "0.0.0.0:7777") + @ConfigurationPropertiesKey("network.listen") + @ConfigurationXPath("/configuration/services/network/listen") InetSocketAddress getListenAddress(); /** @@ -87,7 +91,9 @@ public interface NetworkService extends Service { * @param addr * the listen address */ - @ConfigurationPropertySetter(name = "listen") + @ConfigurationPropertySetter + @ConfigurationPropertiesKey("network.listen") + @ConfigurationXPath("/configuration/services/network/listen") void setListenAddress(InetSocketAddress addr); } diff --git a/src/test/java/com/l2jserver/service/configuration/XMLConfigurationServiceTest.java b/src/test/java/com/l2jserver/service/configuration/XMLConfigurationServiceTest.java new file mode 100644 index 000000000..fe8e4a61b --- /dev/null +++ b/src/test/java/com/l2jserver/service/configuration/XMLConfigurationServiceTest.java @@ -0,0 +1,100 @@ +/* + * This file is part of l2jserver . + * + * l2jserver is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * l2jserver is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with l2jserver. If not, see . + */ +package com.l2jserver.service.configuration; + +import java.io.File; + +import junit.framework.Assert; + +import org.junit.Before; +import org.junit.Test; + +import com.l2jserver.service.ServiceStartException; +import com.l2jserver.service.configuration.XMLConfigurationService.ConfigurationXPath; + +/** + * @author Rogiel + * + */ +public class XMLConfigurationServiceTest { + /** + * The {@link TestConfig} proxy + */ + private TestConfig config; + + @Before + public void tearUp() throws ServiceStartException { + final XMLConfigurationService service = new XMLConfigurationService( + new File("src/test/resources/test-config.xml")); + service.start(); + config = service.get(TestConfig.class); + } + + @Test + public void testString() throws ServiceStartException { + Assert.assertEquals("test", config.getTestString()); + } + + @Test + public void testDefaultValue() throws ServiceStartException { + Assert.assertEquals("default", config.getDefaultTestString()); + } + + @Test + public void testInteger() throws ServiceStartException { + Assert.assertEquals(256, config.getTestInteger()); + } + + @Test + public void testSetter() throws ServiceStartException { + config.setTestString("new-value"); + Assert.assertEquals("new-value", config.getTestString()); + } + + @Test + public void testNullSetter() throws ServiceStartException { + config.setTestString(null); + Assert.assertEquals("test-default", config.getTestString()); + } + + /** + * The TestConfig interface + * + * @author Rogiel + */ + public interface TestConfig extends Configuration { + @ConfigurationPropertyGetter(defaultValue = "test-default") + @ConfigurationXPath("/configuration/test/testvalue") + String getTestString(); + + @ConfigurationPropertySetter + @ConfigurationXPath("/configuration/test/testvalue") + void setTestString(String value); + + @ConfigurationPropertyGetter(defaultValue = "default") + @ConfigurationXPath("/configuration/test/nonexistentkey") + String getDefaultTestString(); + + @ConfigurationPropertyGetter(defaultValue = "0") + @ConfigurationXPath("/configuration/test/integer") + int getTestInteger(); + + @ConfigurationPropertySetter + @ConfigurationXPath("/configuration/test/integer") + void setTestInteger(Integer n); + } +} diff --git a/src/test/resources/test-config.xml b/src/test/resources/test-config.xml new file mode 100644 index 000000000..fb4d3e840 --- /dev/null +++ b/src/test/resources/test-config.xml @@ -0,0 +1,10 @@ + + + + + test + 256 + + \ No newline at end of file