1
0
mirror of https://github.com/Rogiel/l2jserver2 synced 2025-12-05 23:22:47 +00:00

Implements XML based service descriptor allowing to switch services

This commit is contained in:
2011-12-28 00:35:35 -02:00
parent 228f481e86
commit 976cfaf4e0
53 changed files with 1270 additions and 1171 deletions

View File

@@ -25,7 +25,7 @@
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.4</version>
<scope>test</scope>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>

View File

@@ -0,0 +1,64 @@
/*
* This file is part of l2jserver2 <l2jserver2.com>.
*
* l2jserver2 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.
*
* l2jserver2 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 l2jserver2. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jserver.service;
import javolution.lang.Configurable;
/**
* Implements basic management for configurable services
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
* @param <T>
* the service configuration type
*/
public class AbstractConfigurableService<T extends ServiceConfiguration>
extends AbstractService implements ConfigurableService<T> {
/**
* The service configuration
*/
protected T config;
/**
* The service configuration class
*/
private final Class<T> configType;
/**
* @param configType
* the service configuration class
*/
public AbstractConfigurableService(Class<T> configType) {
this.configType = configType;
}
/**
* Transparently implements
* {@link ConfigurableService#getConfigurationInterface()} without
* implementing the interface
*
* @return the configuration interface set at {@link Configurable}
* annotation, if present.
*/
@Override
public Class<T> getConfigurationInterface() {
return configType;
}
@Override
public void setConfiguration(T configuration) {
config = configuration;
}
}

View File

@@ -0,0 +1,42 @@
/*
* This file is part of l2jserver2 <l2jserver2.com>.
*
* l2jserver2 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.
*
* l2jserver2 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 l2jserver2. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jserver.service;
/**
* Marks whether an service can be configured or not
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
* @param <T>
* the configuration interface type
*/
public interface ConfigurableService<T extends ServiceConfiguration> extends
Service {
/**
* @return the configuration interface used by this service
*/
Class<T> getConfigurationInterface();
/**
* Please note that this method will only be set at {@link Service#start()}.
* Once {@link Service#stop()} is called, the configuration will be set to
* <code>null</code>.
*
* @param configuration
* the service configuration instance
*/
void setConfiguration(T configuration);
}

View File

@@ -0,0 +1,108 @@
/*
* This file is part of l2jserver2 <l2jserver2.com>.
*
* l2jserver2 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.
*
* l2jserver2 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 l2jserver2. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jserver.service;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import org.w3c.dom.DOMException;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
* @param <T>
* the service type
*/
@XmlAccessorType(XmlAccessType.NONE)
@XmlRootElement(name = "services")
public class ServiceDescriptor<T extends Service> {
/**
* The service interface class
*/
@XmlAttribute(name = "interface")
private final Class<T> serviceInterface;
/**
* The service implementation class
*/
@XmlAttribute(name = "implementation")
private final Class<? extends T> serviceImplementation;
/**
* The node (will be used later for configuration purposes)
*/
private final Node node;
/**
* @param serviceInterface
* the service interface
* @param serviceImplementation
* the service implementation
* @param node
* the XML node
*/
public ServiceDescriptor(Class<T> serviceInterface,
Class<? extends T> serviceImplementation, Node node) {
this.serviceInterface = serviceInterface;
this.serviceImplementation = serviceImplementation;
this.node = node;
}
/**
* @return the service interface class
*/
public Class<T> getServiceInterface() {
return serviceInterface;
}
/**
* @return the service implementation class
*/
public Class<? extends T> getServiceImplementation() {
return serviceImplementation;
}
/**
* @return the xml node
*/
public Node getNode() {
return node;
}
/**
* @param node
* the XML node
* @return a new {@link ServiceDescriptor} instance for the given service
* XML node
* @throws ClassNotFoundException
* if any of the services class could not be found
* @throws DOMException
* if any error occur while parsing the XML data
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public static ServiceDescriptor fromNode(Node node)
throws ClassNotFoundException, DOMException {
final NamedNodeMap attrs = node.getAttributes();
final Class<? extends Service> serviceInterface = (Class<? extends Service>) Class
.forName(attrs.getNamedItem("interface").getNodeValue());
final Class<? extends Service> serviceImplementation = (Class<? extends Service>) Class
.forName(attrs.getNamedItem("implementation").getNodeValue());
return new ServiceDescriptor(serviceInterface, serviceImplementation,
node);
}
}

View File

@@ -23,7 +23,7 @@ import com.l2jserver.util.exception.L2Exception;
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public abstract class ServiceException extends L2Exception {
public class ServiceException extends L2Exception {
/**
* The Java Serialization API serial
*/

View File

@@ -16,14 +16,29 @@
*/
package com.l2jserver.service;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Map;
import java.util.Set;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.Scopes;
import com.l2jserver.service.configuration.ConfigurationService;
import com.l2jserver.service.core.LoggingService;
import com.l2jserver.util.ClassUtils;
import com.l2jserver.util.factory.CollectionFactory;
@@ -37,31 +52,89 @@ public class ServiceManager {
/**
* The logger
*/
private final Logger logger;
private Logger logger;
/**
* The Guice Injector
*/
private final Injector injector;
private Injector injector;
/**
* The configuration service
*/
private ConfigurationService configurationService;
/**
* The DAO module
*/
private Class<? extends Module> daoModule;
/**
* List of all known services by this manager
*/
private final Set<Service> knownServices = CollectionFactory.newSet();
/**
* The service descriptors
*/
private final Map<Class<? extends Service>, ServiceDescriptor<?>> descriptors = CollectionFactory
.newMap();
/**
* @param injector
* the {@link Guice} {@link Injector}
* @param file
* the XML file
* @throws SAXException
* if any XML parsing error occur
* @throws IOException
* if any error occur while reading the file
* @throws ParserConfigurationException
* if any XML parsing error occur
* @throws ClassNotFoundException
* if the service class could not be found
* @throws DOMException
* if any XML parsing error occur
* @throws ServiceException
* if any service error occur
*/
@Inject
public ServiceManager(Injector injector) {
@SuppressWarnings("unchecked")
public void load(Path file) throws SAXException, IOException,
ParserConfigurationException, ClassNotFoundException, DOMException,
ServiceException {
Document document = DocumentBuilderFactory.newInstance()
.newDocumentBuilder().parse(Files.newInputStream(file));
final Map<Class<? extends Service>, ServiceDescriptor<?>> descriptors = CollectionFactory
.newMap();
final NodeList nodeList = document.getElementsByTagName("service");
for (int i = 0; i < nodeList.getLength(); i++) {
final Node node = nodeList.item(i);
final ServiceDescriptor<?> descriptor = ServiceDescriptor
.fromNode(node);
descriptors.put(descriptor.getServiceInterface(), descriptor);
}
final Node node = document.getElementsByTagName("dao").item(0);
if (node == null)
throw new ServiceException("DAO module declaration not found");
daoModule = (Class<? extends Module>) Class.forName(node
.getAttributes().getNamedItem("module").getNodeValue());
this.descriptors.putAll(descriptors);
}
/**
* Initializes the service manager
*
* @param injector
* the injector instance
* @throws ServiceStartException
* if any error occur while starting logging or configuration
* service
*/
public void init(Injector injector) throws ServiceStartException {
this.injector = injector;
final LoggingService service = injector
.getInstance(LoggingService.class);
knownServices.add(service);
try {
service.start();
} catch (ServiceStartException e) {
throw new RuntimeException(e);
}
service.start();
configurationService = injector.getInstance(ConfigurationService.class);
knownServices.add(configurationService);
configurationService.start();
logger = LoggerFactory.getLogger(ServiceManager.class);
}
@@ -76,6 +149,17 @@ public class ServiceManager {
return injector.getInstance(serviceClass);
}
/**
* @param serviceClass
* the service class
* @return the {@link ServiceDescriptor} for the requested service
*/
@SuppressWarnings("unchecked")
public <T extends Service> ServiceDescriptor<T> getServiceDescriptor(
Class<T> serviceClass) {
return (ServiceDescriptor<T>) descriptors.get(serviceClass);
}
/**
* Starts the given service implementation
*
@@ -87,6 +171,7 @@ public class ServiceManager {
* @throws ServiceStartException
* if any error occur while starting service
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public <T extends Service> T start(Class<T> serviceClass)
throws ServiceStartException {
final T service = injector.getInstance(serviceClass);
@@ -99,6 +184,13 @@ public class ServiceManager {
startDependencies(service.getDependencies());
logger.debug("{}: Starting service...",
serviceClass.getSimpleName());
if (service instanceof ConfigurableService) {
final ServiceConfiguration config = configurationService
.getServiceConfiguration(
(ConfigurableService<?>) service,
(Class<? extends Service>) serviceClass);
((ConfigurableService) service).setConfiguration(config);
}
service.start();
logger.info("{} started", serviceClass.getSimpleName());
return service;
@@ -152,6 +244,9 @@ public class ServiceManager {
logger.debug("{0}: Stopping service...",
serviceClass.getSimpleName());
stopDependencies(service);
if (service instanceof ConfigurableService) {
((ConfigurableService<?>) service).setConfiguration(null);
}
service.stop();
logger.info("{0}: Service stopped!", serviceClass.getSimpleName());
} catch (ServiceStopException e) {
@@ -245,4 +340,29 @@ public class ServiceManager {
throw e;
}
}
/**
* @return a newly created {@link Guice} {@link Module} with all loaded
* services
*/
public Module newGuiceModule() {
return new AbstractModule() {
@Override
@SuppressWarnings("unchecked")
protected void configure() {
bind(ServiceManager.class).toInstance(ServiceManager.this);
try {
install(daoModule.newInstance());
} catch (Exception e) {
throw new RuntimeException(e);
}
for (@SuppressWarnings("rawtypes")
final ServiceDescriptor descriptor : descriptors.values()) {
bind(descriptor.getServiceInterface()).to(
descriptor.getServiceImplementation()).in(
Scopes.SINGLETON);
}
}
};
}
}

View File

@@ -16,7 +16,9 @@
*/
package com.l2jserver.service.configuration;
import com.l2jserver.service.ConfigurableService;
import com.l2jserver.service.Service;
import com.l2jserver.service.ServiceConfiguration;
/**
* The configuration service is responsible for reading and writing in
@@ -27,13 +29,15 @@ import com.l2jserver.service.Service;
*/
public interface ConfigurationService extends Service {
/**
* Get the configuration object for <tt>config</tt>
* Get the configuration for the given service
*
* @param <C>
* the configuration type
* @param config
* the configuration interface class
* @param service
* the service
* @param serviceInterface
* the service interface
* @return the configuration object
*/
<C extends Configuration> C get(Class<C> config);
<C extends ServiceConfiguration> C getServiceConfiguration(
ConfigurableService<?> service,
Class<? extends Service> serviceInterface);
}

View File

@@ -16,8 +16,6 @@
*/
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;
@@ -26,23 +24,23 @@ 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.ConfigurableService;
import com.l2jserver.service.Service;
import com.l2jserver.service.ServiceConfiguration;
import com.l2jserver.service.ServiceDescriptor;
import com.l2jserver.service.ServiceManager;
import com.l2jserver.service.ServiceStartException;
import com.l2jserver.service.cache.CacheService;
import com.l2jserver.service.configuration.Configuration.ConfigurationPropertyGetter;
@@ -60,33 +58,16 @@ import com.l2jserver.util.transformer.TransformerFactory;
@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}
* The service manager. Will provide XML nodes for service configuration
* interfaces
*/
private DocumentBuilderFactory factory;
/**
* The DOM {@link DocumentBuilder}
*/
private DocumentBuilder builder;
/**
* The XML {@link Document} containing configuration data
*/
private Document properties;
/**
* The cache of configuration objects
*/
private Map<Class<?>, Object> cache = CollectionFactory.newWeakMap();
private final ServiceManager serviceManager;
/**
* Defines the XPath for the configuration parameter
@@ -103,50 +84,29 @@ public class XMLConfigurationService extends AbstractService implements
/**
* Creates a new empty instance
*
* @param serviceManager
* the service manager
*/
@Inject
protected XMLConfigurationService() {
}
/**
* Creates a new service instance. <b>This is used for tests</b>
*
* @param file
* the configuration file
*/
protected XMLConfigurationService(File file) {
this.file = file;
protected XMLConfigurationService(ServiceManager serviceManager) {
this.serviceManager = serviceManager;
}
@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 extends Configuration> C get(Class<C> 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;
public <C extends ServiceConfiguration> C getServiceConfiguration(
ConfigurableService<?> service,
Class<? extends Service> serviceInterface) {
final ServiceDescriptor<?> serviceDescriptor = serviceManager
.getServiceDescriptor(serviceInterface);
return (C) Proxy.newProxyInstance(this.getClass().getClassLoader(),
new Class<?>[] { service.getConfigurationInterface() },
new ConfigInvocationHandler(serviceDescriptor.getNode()));
}
/**
@@ -158,7 +118,7 @@ public class XMLConfigurationService extends AbstractService implements
/**
* The invocation handler properties
*/
private final Document properties;
private final Node properties;
/**
* The invocation cache
*/
@@ -168,7 +128,7 @@ public class XMLConfigurationService extends AbstractService implements
* @param properties
* the properties
*/
public ConfigInvocationHandler(Document properties) {
public ConfigInvocationHandler(Node properties) {
this.properties = properties;
}
@@ -345,11 +305,4 @@ public class XMLConfigurationService extends AbstractService implements
}
return null;
}
/**
* @return the configuration store directory
*/
public File getFile() {
return file;
}
}

View File

@@ -0,0 +1,25 @@
/*
* This file is part of l2jserver2 <l2jserver2.com>.
*
* l2jserver2 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.
*
* l2jserver2 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 l2jserver2. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jserver.service.core.vfs;
/**
* Configuration interface for {@link Java7VFSService}.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public interface Java7VFSConfiguration extends VFSConfiguration {
}

View File

@@ -22,27 +22,23 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.inject.Inject;
import com.l2jserver.service.AbstractService;
import com.l2jserver.service.AbstractConfigurableService;
import com.l2jserver.service.ServiceStartException;
import com.l2jserver.service.ServiceStopException;
import com.l2jserver.service.configuration.ConfigurationService;
/**
* Implementation of {@link VFSService} using default Java7 APIs.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public class Java7VFSService extends AbstractService implements VFSService {
public class Java7VFSService extends
AbstractConfigurableService<Java7VFSConfiguration> implements
VFSService {
/**
* The logger
*/
private final Logger log = LoggerFactory.getLogger(this.getClass());
/**
* The Java 7 vfs configuration
*/
private final Java7VFSConfiguration config;
/**
* The root {@link Path} of the server data
*/
@@ -53,20 +49,11 @@ public class Java7VFSService extends AbstractService implements VFSService {
private Path dataRoot;
/**
* Configuration interface for {@link Java7VFSService}.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public interface Java7VFSConfiguration extends VFSConfiguration {
}
/**
* @param configService
* the configuration service
* Creates a new instance
*/
@Inject
protected Java7VFSService(final ConfigurationService configService) {
this.config = configService.get(Java7VFSConfiguration.class);
public Java7VFSService() {
super(Java7VFSConfiguration.class);
}
@Override

View File

@@ -0,0 +1,25 @@
/*
* This file is part of l2jserver2 <l2jserver2.com>.
*
* l2jserver2 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.
*
* l2jserver2 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 l2jserver2. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jserver.service.core.vfs;
/**
* Configuration interface for {@link TrueZipVFSService}.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public interface TrueZipVFSConfiguration extends VFSConfiguration {
}

View File

@@ -22,7 +22,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.inject.Inject;
import com.l2jserver.service.AbstractService;
import com.l2jserver.service.AbstractConfigurableService;
import com.l2jserver.service.ServiceStartException;
import com.l2jserver.service.ServiceStopException;
import com.l2jserver.service.configuration.ConfigurationService;
@@ -35,17 +35,14 @@ import de.schlichtherle.truezip.nio.file.TPath;
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public class TrueZipVFSService extends AbstractService implements VFSService {
public class TrueZipVFSService extends
AbstractConfigurableService<TrueZipVFSConfiguration> implements
VFSService {
/**
* The logger
*/
private final Logger log = LoggerFactory.getLogger(this.getClass());
/**
* The Java 7 vfs configuration
*/
private final TrueZipVFSConfiguration config;
/**
* The root {@link Path} of the server data
*/
@@ -55,21 +52,13 @@ public class TrueZipVFSService extends AbstractService implements VFSService {
*/
private TPath dataRoot;
/**
* Configuration interface for {@link TrueZipVFSService}.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public interface TrueZipVFSConfiguration extends VFSConfiguration {
}
/**
* @param configService
* the configuration service
*/
@Inject
protected TrueZipVFSService(final ConfigurationService configService) {
this.config = configService.get(TrueZipVFSConfiguration.class);
super(TrueZipVFSConfiguration.class);
}
@Override

View File

@@ -0,0 +1,62 @@
/*
* This file is part of l2jserver2 <l2jserver2.com>.
*
* l2jserver2 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.
*
* l2jserver2 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 l2jserver2. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jserver.service.core.vfs;
import java.net.URI;
import java.nio.file.Path;
import com.l2jserver.service.ServiceConfiguration;
import com.l2jserver.service.configuration.Configuration;
import com.l2jserver.service.configuration.XMLConfigurationService.ConfigurationXPath;
/**
* VFS service configuration
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
* @see Configuration
*/
public interface VFSConfiguration extends ServiceConfiguration {
/**
* @return the VFS root {@link URI}
*/
@ConfigurationPropertyGetter(defaultValue = "")
@ConfigurationXPath("fileSystem/@root")
Path getRoot();
/**
* @param root
* the new VFS root {@link URI}
*/
@ConfigurationPropertySetter
@ConfigurationXPath("fileSystem/@root")
void setRoot(Path root);
/**
* @return the VFS root {@link URI}
*/
@ConfigurationPropertyGetter(defaultValue = "")
@ConfigurationXPath("fileSystem/data/@root")
String getDataPath();
/**
* @param data
* the new data root {@link URI}
*/
@ConfigurationPropertySetter
@ConfigurationXPath("fileSystem/data/@root")
void setDataPath(String data);
}

View File

@@ -16,13 +16,9 @@
*/
package com.l2jserver.service.core.vfs;
import java.net.URI;
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.XMLConfigurationService.ConfigurationXPath;
/**
* The VFS service is responsible for creating a Virtual File System that is
@@ -31,44 +27,6 @@ import com.l2jserver.service.configuration.XMLConfigurationService.Configuration
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public interface VFSService extends Service {
/**
* VFS service configuration
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
* @see Configuration
*/
public interface VFSConfiguration extends ServiceConfiguration {
/**
* @return the VFS root {@link URI}
*/
@ConfigurationPropertyGetter(defaultValue = "")
@ConfigurationXPath("/configuration/services/vfs/root")
Path getRoot();
/**
* @param root
* the new VFS root {@link URI}
*/
@ConfigurationPropertySetter
@ConfigurationXPath("/configuration/services/vfs/root")
void setRoot(Path root);
/**
* @return the VFS root {@link URI}
*/
@ConfigurationPropertyGetter(defaultValue = "")
@ConfigurationXPath("/configuration/services/vfs/data")
String getDataPath();
/**
* @param data
* the new data root {@link URI}
*/
@ConfigurationPropertySetter
@ConfigurationXPath("/configuration/services/vfs/data")
void setDataPath(String data);
}
/**
* Resolves an file. If the file cannot be resolved, null will be returned.
* <p>

View File

@@ -0,0 +1,44 @@
/*
* This file is part of l2jserver2 <l2jserver2.com>.
*
* l2jserver2 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.
*
* l2jserver2 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 l2jserver2. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jserver.service.database;
import com.l2jserver.service.ServiceConfiguration;
import com.l2jserver.service.configuration.Configuration;
import com.l2jserver.service.configuration.XMLConfigurationService.ConfigurationXPath;
/**
* Database service configuration
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
* @see Configuration
*/
public interface DatabaseConfiguration extends ServiceConfiguration {
/**
* @return the update schema state
*/
@ConfigurationPropertyGetter(defaultValue = "true")
@ConfigurationXPath("schema/@automaticUpdate")
boolean isAutomaticSchemaUpdateEnabled();
/**
* @param updateSchema
* the new uodate schema state
*/
@ConfigurationPropertySetter
@ConfigurationXPath("schema/@automaticUpdate")
void setUpdateSchema(boolean updateSchema);
}

View File

@@ -22,9 +22,6 @@ import java.nio.file.Path;
import com.l2jserver.model.Model;
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.XMLConfigurationService.ConfigurationXPath;
import com.l2jserver.service.core.threading.AsyncFuture;
import com.mysema.query.sql.RelationalPath;
import com.mysema.query.sql.RelationalPathBase;
@@ -45,29 +42,6 @@ import com.mysema.query.sql.RelationalPathBase;
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public interface DatabaseService extends Service {
/**
* Database service configuration
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
* @see Configuration
*/
public interface DatabaseConfiguration extends ServiceConfiguration {
/**
* @return the update schema state
*/
@ConfigurationPropertyGetter(defaultValue = "true")
@ConfigurationXPath("/configuration/services/database/automaticSchemaUpdate")
boolean isAutomaticSchemaUpdateEnabled();
/**
* @param updateSchema
* the new uodate schema state
*/
@ConfigurationPropertySetter
@ConfigurationXPath("/configuration/services/database/automaticSchemaUpdate")
void setUpdateSchema(boolean updateSchema);
}
/**
* Executes several operations inside a single database transaction.
* <p>

View File

@@ -35,13 +35,11 @@ import com.l2jserver.model.Model;
import com.l2jserver.model.Model.ObjectDesire;
import com.l2jserver.model.id.ID;
import com.l2jserver.model.id.object.allocator.IDAllocator;
import com.l2jserver.service.AbstractService;
import com.l2jserver.service.AbstractConfigurableService;
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.ConfigurationService;
import com.l2jserver.service.configuration.XMLConfigurationService.ConfigurationXPath;
import com.l2jserver.service.core.threading.AbstractTask;
import com.l2jserver.service.core.threading.AsyncFuture;
import com.l2jserver.service.core.threading.ScheduledAsyncFuture;
@@ -96,12 +94,9 @@ import com.orientechnologies.orient.core.tx.OTransaction;
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public abstract class AbstractOrientDatabaseService extends AbstractService
implements DatabaseService {
/**
* The configuration object
*/
private final OrientDatabaseConfiguration config;
public abstract class AbstractOrientDatabaseService extends
AbstractConfigurableService<OrientDatabaseConfiguration> implements
DatabaseService {
/**
* The logger
*/
@@ -136,60 +131,6 @@ public abstract class AbstractOrientDatabaseService extends AbstractService
private final ThreadLocal<ODatabaseDocumentTx> transaction = new ThreadLocal<ODatabaseDocumentTx>();
/**
* Configuration interface for {@link AbstractOrientDatabaseService}.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public interface OrientDatabaseConfiguration extends DatabaseConfiguration {
/**
* @return the orientdb url
*/
@ConfigurationPropertyGetter(defaultValue = "local:data/database")
@ConfigurationXPath("/configuration/services/database/orientdb/url")
String getUrl();
/**
* @param url
* the new orientdb url
*/
@ConfigurationPropertySetter
@ConfigurationXPath("/configuration/services/database/orientdb/url")
void setUrl(String url);
/**
* @return the orientdb database username
*/
@ConfigurationPropertyGetter(defaultValue = "admin")
@ConfigurationXPath("/configuration/services/database/orientdb/username")
String getUsername();
/**
* @param username
* the orientdb database username
*/
@ConfigurationPropertySetter
@ConfigurationXPath("/configuration/services/database/orientdb/username")
void setUsername(String username);
/**
* @return the orientdb database password
*/
@ConfigurationPropertyGetter(defaultValue = "admin")
@ConfigurationXPath("/configuration/services/database/orientdb/password")
String getPassword();
/**
* @param password
* the jdbc database password
*/
@ConfigurationPropertySetter
@ConfigurationXPath("/configuration/services/database/jdbc/password")
void setPassword(String password);
}
/**
* @param configService
* the configuration service
* @param cacheService
* the cache service
* @param threadService
@@ -198,10 +139,10 @@ public abstract class AbstractOrientDatabaseService extends AbstractService
* the {@link DataAccessObject DAO} resolver
*/
@Inject
public AbstractOrientDatabaseService(ConfigurationService configService,
public AbstractOrientDatabaseService(
CacheService cacheService, ThreadService threadService,
DAOResolver daoResolver) {
config = configService.get(OrientDatabaseConfiguration.class);
super(OrientDatabaseConfiguration.class);
this.cacheService = cacheService;
this.threadService = threadService;
this.daoResolver = daoResolver;

View File

@@ -0,0 +1,72 @@
/*
* This file is part of l2jserver2 <l2jserver2.com>.
*
* l2jserver2 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.
*
* l2jserver2 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 l2jserver2. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jserver.service.database.orientdb;
import com.l2jserver.service.configuration.XMLConfigurationService.ConfigurationXPath;
import com.l2jserver.service.database.DatabaseConfiguration;
/**
* Configuration interface for {@link AbstractOrientDatabaseService}.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public interface OrientDatabaseConfiguration extends DatabaseConfiguration {
/**
* @return the orientdb url
*/
@ConfigurationPropertyGetter(defaultValue = "local:data/database")
@ConfigurationXPath("connection/@url")
String getUrl();
/**
* @param url
* the new orientdb url
*/
@ConfigurationPropertySetter
@ConfigurationXPath("connection/@url")
void setUrl(String url);
/**
* @return the orientdb database username
*/
@ConfigurationPropertyGetter(defaultValue = "admin")
@ConfigurationXPath("connection/authentication/@username")
String getUsername();
/**
* @param username
* the orientdb database username
*/
@ConfigurationPropertySetter
@ConfigurationXPath("connection/authentication/@username")
void setUsername(String username);
/**
* @return the orientdb database password
*/
@ConfigurationPropertyGetter(defaultValue = "admin")
@ConfigurationXPath("connection/authentication/@password")
String getPassword();
/**
* @param password
* the jdbc database password
*/
@ConfigurationPropertySetter
@ConfigurationXPath("connection/authentication/@password")
void setPassword(String password);
}

View File

@@ -43,13 +43,11 @@ import com.l2jserver.model.Model;
import com.l2jserver.model.Model.ObjectDesire;
import com.l2jserver.model.id.ID;
import com.l2jserver.model.id.object.allocator.IDAllocator;
import com.l2jserver.service.AbstractService;
import com.l2jserver.service.AbstractConfigurableService;
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.ConfigurationService;
import com.l2jserver.service.configuration.XMLConfigurationService.ConfigurationXPath;
import com.l2jserver.service.core.threading.AbstractTask;
import com.l2jserver.service.core.threading.AsyncFuture;
import com.l2jserver.service.core.threading.ScheduledAsyncFuture;
@@ -101,12 +99,9 @@ import com.mysema.query.types.Path;
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public abstract class AbstractSQLDatabaseService extends AbstractService
implements DatabaseService {
/**
* The configuration object
*/
private final JDBCDatabaseConfiguration config;
public abstract class AbstractSQLDatabaseService extends
AbstractConfigurableService<JDBCDatabaseConfiguration> implements
DatabaseService {
/**
* The logger
*/
@@ -173,120 +168,6 @@ public abstract class AbstractSQLDatabaseService extends AbstractService
private final Type<?>[] sqlTypes;
/**
* Configuration interface for {@link AbstractSQLDatabaseService}.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public interface JDBCDatabaseConfiguration extends DatabaseConfiguration {
/**
* @return the jdbc url
*/
@ConfigurationPropertyGetter(defaultValue = "jdbc:mysql://localhost/l2jserver2")
@ConfigurationXPath("/configuration/services/database/jdbc/url")
String getJdbcUrl();
/**
* @param jdbcUrl
* the new jdbc url
*/
@ConfigurationPropertySetter
@ConfigurationXPath("/configuration/services/database/jdbc/url")
void setJdbcUrl(String jdbcUrl);
/**
* @return the database engine class
*/
@ConfigurationPropertyGetter(defaultValue = "com.l2jserver.service.database.sql.MySQLDatabaseEngine")
@ConfigurationXPath("/configuration/services/database/jdbc/engine")
Class<? extends DatabaseEngine> getDatabaseEngineClass();
/**
* @param driver
* the new database engine class
*/
@ConfigurationPropertySetter
@ConfigurationXPath("/configuration/services/database/jdbc/engine")
void setDatabaseEngineClass(Class<? extends DatabaseEngine> driver);
/**
* @return the jdbc database username
*/
@ConfigurationPropertyGetter(defaultValue = "l2j")
@ConfigurationXPath("/configuration/services/database/jdbc/username")
String getUsername();
/**
* @param username
* the jdbc database username
*/
@ConfigurationPropertySetter
@ConfigurationXPath("/configuration/services/database/jdbc/username")
void setUsername(String username);
/**
* @return the jdbc database password
*/
@ConfigurationPropertyGetter(defaultValue = "changeme")
@ConfigurationXPath("/configuration/services/database/jdbc/password")
String getPassword();
/**
* @param password
* the jdbc database password
*/
@ConfigurationPropertySetter
@ConfigurationXPath("/configuration/services/database/jdbc/password")
void setPassword(String password);
/**
* @return the maximum number of active connections
*/
@ConfigurationPropertyGetter(defaultValue = "20")
@ConfigurationXPath("/configuration/services/database/connections/active-maximum")
int getMaxActiveConnections();
/**
* @param password
* the maximum number of active connections
*/
@ConfigurationPropertySetter
@ConfigurationXPath("/configuration/services/database/connections/active-maximum")
void setMaxActiveConnections(int password);
/**
* @return the maximum number of idle connections
*/
@ConfigurationPropertyGetter(defaultValue = "20")
@ConfigurationXPath("/configuration/services/database/connections/idle-maximum")
int getMaxIdleConnections();
/**
* @param password
* the maximum number of idle connections
*/
@ConfigurationPropertySetter
@ConfigurationXPath("/configuration/services/database/connections/idle-maximum")
void setMaxIdleConnections(int password);
/**
* @return the minimum number of idle connections
*/
@ConfigurationPropertyGetter(defaultValue = "5")
@ConfigurationXPath("/configuration/services/database/connections/idle-minimum")
int getMinIdleConnections();
/**
* @param password
* the minimum number of idle connections
*/
@ConfigurationPropertySetter
@ConfigurationXPath("/configuration/services/database/connections/idle-minimum")
void setMinIdleConnections(int password);
}
/**
* @param configService
* the configuration service
* @param cacheService
* the cache service
* @param threadService
@@ -299,10 +180,10 @@ public abstract class AbstractSQLDatabaseService extends AbstractService
* the SQL mapping types
*/
@Inject
public AbstractSQLDatabaseService(ConfigurationService configService,
CacheService cacheService, ThreadService threadService,
VFSService vfsService, DAOResolver daoResolver, Type<?>... types) {
config = configService.get(JDBCDatabaseConfiguration.class);
public AbstractSQLDatabaseService(CacheService cacheService,
ThreadService threadService, VFSService vfsService,
DAOResolver daoResolver, Type<?>... types) {
super(JDBCDatabaseConfiguration.class);
this.cacheService = cacheService;
this.threadService = threadService;
this.vfsService = vfsService;
@@ -409,6 +290,7 @@ public abstract class AbstractSQLDatabaseService extends AbstractService
}
log.info("Importing {} to {}", path, entity);
try {
conn.setAutoCommit(false);
CSVUtils.parseCSV(path, new CSVMapProcessor<Long>() {
@Override
public Long process(final Map<String, String> map) {
@@ -433,8 +315,15 @@ public abstract class AbstractSQLDatabaseService extends AbstractService
return insert.execute();
}
});
conn.commit();
} catch (SQLException e) {
try {
conn.rollback();
} catch (SQLException e1) {
}
} finally {
try {
conn.setAutoCommit(true);
conn.close();
} catch (SQLException e) {
}

View File

@@ -0,0 +1,132 @@
/*
* This file is part of l2jserver2 <l2jserver2.com>.
*
* l2jserver2 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.
*
* l2jserver2 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 l2jserver2. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jserver.service.database.sql;
import com.l2jserver.service.configuration.XMLConfigurationService.ConfigurationXPath;
import com.l2jserver.service.database.DatabaseConfiguration;
/**
* Configuration interface for {@link AbstractSQLDatabaseService}.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public interface JDBCDatabaseConfiguration extends DatabaseConfiguration {
/**
* @return the jdbc url
*/
@ConfigurationPropertyGetter(defaultValue = "jdbc:mysql://localhost/l2jserver2")
@ConfigurationXPath("connection/@url")
String getJdbcUrl();
/**
* @param jdbcUrl
* the new jdbc url
*/
@ConfigurationPropertySetter
@ConfigurationXPath("connection/@url")
void setJdbcUrl(String jdbcUrl);
/**
* @return the database engine class
*/
@ConfigurationPropertyGetter(defaultValue = "com.l2jserver.service.database.sql.MySQLDatabaseEngine")
@ConfigurationXPath("connection/engine/@class")
Class<? extends DatabaseEngine> getDatabaseEngineClass();
/**
* @param driver
* the new database engine class
*/
@ConfigurationPropertySetter
@ConfigurationXPath("connection/engine/@class")
void setDatabaseEngineClass(Class<? extends DatabaseEngine> driver);
/**
* @return the jdbc database username
*/
@ConfigurationPropertyGetter(defaultValue = "l2j")
@ConfigurationXPath("connection/authentication/@username")
String getUsername();
/**
* @param username
* the jdbc database username
*/
@ConfigurationPropertySetter
@ConfigurationXPath("connection/authentication/@username")
void setUsername(String username);
/**
* @return the jdbc database password
*/
@ConfigurationPropertyGetter(defaultValue = "changeme")
@ConfigurationXPath("connection/authentication/@password")
String getPassword();
/**
* @param password
* the jdbc database password
*/
@ConfigurationPropertySetter
@ConfigurationXPath("connection/authentication/@password")
void setPassword(String password);
/**
* @return the maximum number of active connections
*/
@ConfigurationPropertyGetter(defaultValue = "20")
@ConfigurationXPath("connection/pool/@max-active")
int getMaxActiveConnections();
/**
* @param maxActive
* the maximum number of active connections
*/
@ConfigurationPropertySetter
@ConfigurationXPath("connection/pool/@max-active")
void setMaxActiveConnections(int maxActive);
/**
* @return the maximum number of idle connections
*/
@ConfigurationPropertyGetter(defaultValue = "20")
@ConfigurationXPath("connection/pool/@max-idle")
int getMaxIdleConnections();
/**
* @param maxIdle
* the maximum number of idle connections
*/
@ConfigurationPropertySetter
@ConfigurationXPath("connection/pool/@max-idle")
void setMaxIdleConnections(int maxIdle);
/**
* @return the minimum number of idle connections
*/
@ConfigurationPropertyGetter(defaultValue = "5")
@ConfigurationXPath("connection/pool/@min-idle")
int getMinIdleConnections();
/**
* @param minIdle
* the minimum number of idle connections
*/
@ConfigurationPropertySetter
@ConfigurationXPath("connection/pool/@min-idle")
void setMinIdleConnections(int minIdle);
}

View File

@@ -16,6 +16,7 @@
*/
package com.l2jserver.util;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
/**
@@ -61,6 +62,39 @@ public class ClassUtils {
return false;
}
/**
* Recursively searches for an annotation <h1>Search order</h1>
* <p>
* <ol>
* <li><code>cls</code> class</li>
* <li><code>cls</code> implementing interfaces</code></li>
* <li><code>cls</code> super class</code></li>
* </ol>
* If after all those steps, no annotation is found, <code>null</code> is
* returned.
*
* @param annotationClass
* the annotation class
* @param cls
* the class to start searching
* @return the annotation, if found.
*/
public static <T extends Annotation> T getAnnotation(
Class<T> annotationClass, Class<?> cls) {
T annotation = cls.getAnnotation(annotationClass);
if (annotation == null) {
for (final Class<?> interfaceCls : cls.getInterfaces()) {
annotation = getAnnotation(annotationClass, interfaceCls);
if (annotation != null)
break;
}
}
if (annotation == null && cls.getSuperclass() != null
&& cls.getSuperclass() != Object.class)
annotation = getAnnotation(annotationClass, cls.getSuperclass());
return annotation;
}
/**
* Checks if class in member of the package
*

View File

@@ -1,148 +0,0 @@
/*
* This file is part of l2jserver2 <l2jserver2.com>.
*
* l2jserver2 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.
*
* l2jserver2 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 l2jserver2. If not, see <http://www.gnu.org/licenses/>.
*/
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;
/**
* Tests for {@link XMLConfigurationService}
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public class XMLConfigurationServiceTest {
/**
* The {@link TestConfig} proxy
*/
private TestConfig config;
/**
* Preparation for tests
*
* @throws ServiceStartException
*/
@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 config string
*
* @throws ServiceStartException
*/
@Test
public void testString() throws ServiceStartException {
Assert.assertEquals("test", config.getTestString());
}
/**
* Test default value
*
* @throws ServiceStartException
*/
@Test
public void testDefaultValue() throws ServiceStartException {
Assert.assertEquals("default", config.getDefaultTestString());
}
/**
* Test integer
*
* @throws ServiceStartException
*/
@Test
public void testInteger() throws ServiceStartException {
Assert.assertEquals(256, config.getTestInteger());
}
/**
* Test setter
*
* @throws ServiceStartException
*/
@Test
public void testSetter() throws ServiceStartException {
config.setTestString("new-value");
Assert.assertEquals("new-value", config.getTestString());
}
/**
* Test null setter
*
* @throws ServiceStartException
*/
@Test
public void testNullSetter() throws ServiceStartException {
config.setTestString(null);
Assert.assertEquals("test-default", config.getTestString());
}
/**
* The TestConfig interface
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public interface TestConfig extends Configuration {
/**
* @return an configuration string
*/
@ConfigurationPropertyGetter(defaultValue = "test-default")
@ConfigurationXPath("/configuration/test/testvalue")
String getTestString();
/**
* @param value
* any string
*/
@ConfigurationPropertySetter
@ConfigurationXPath("/configuration/test/testvalue")
void setTestString(String value);
/**
* @return an configuration string
*/
@ConfigurationPropertyGetter(defaultValue = "default")
@ConfigurationXPath("/configuration/test/nonexistentkey")
String getDefaultTestString();
/**
* @return an configuration integer
*/
@ConfigurationPropertyGetter(defaultValue = "0")
@ConfigurationXPath("/configuration/test/integer")
int getTestInteger();
/**
* @param n
* any integer
*/
@ConfigurationPropertySetter
@ConfigurationXPath("/configuration/test/integer")
void setTestInteger(Integer n);
}
}