You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by ng...@apache.org on 2008/06/09 16:29:10 UTC
svn commit: r665702 - in /mina/ftpserver/trunk/core: ./
src/main/java/org/apache/ftpserver/
src/main/java/org/apache/ftpserver/config/
src/main/java/org/apache/ftpserver/config/spring/
src/main/java/org/apache/ftpserver/interfaces/ src/main/resources/M...
Author: ngn
Date: Mon Jun 9 07:29:09 2008
New Revision: 665702
URL: http://svn.apache.org/viewvc?rev=665702&view=rev
Log:
First stab at an implementation of Spring based configuration (FTPSERVER-124)
Added:
mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/config/
mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/config/spring/
mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/config/spring/CommandFactoryBeanDefinitionParser.java
mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/config/spring/FileSystemBeanDefinitionParser.java
mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/config/spring/FtpServerNamespaceHandler.java
mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/config/spring/ListenerBeanDefinitionParser.java
mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/config/spring/ServerBeanDefinitionParser.java
mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/config/spring/SpringUtil.java
mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/config/spring/UserManagerBeanDefinitionParser.java
mina/ftpserver/trunk/core/src/main/resources/META-INF/
mina/ftpserver/trunk/core/src/main/resources/META-INF/spring.handlers
mina/ftpserver/trunk/core/src/main/resources/META-INF/spring.schemas
mina/ftpserver/trunk/core/src/main/resources/org/apache/ftpserver/config/
mina/ftpserver/trunk/core/src/main/resources/org/apache/ftpserver/config/spring/
mina/ftpserver/trunk/core/src/main/resources/org/apache/ftpserver/config/spring/ftpserver-1.0.xsd
mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/config/
mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/config/spring/
mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/config/spring/SpringConfigTest.java
mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/config/spring/TestFtplet.java
mina/ftpserver/trunk/core/src/test/resources/spring-config/
mina/ftpserver/trunk/core/src/test/resources/spring-config/config-spring-1.xml
Modified:
mina/ftpserver/trunk/core/pom.xml
mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/FtpServer.java
mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/interfaces/CommandFactory.java
Modified: mina/ftpserver/trunk/core/pom.xml
URL: http://svn.apache.org/viewvc/mina/ftpserver/trunk/core/pom.xml?rev=665702&r1=665701&r2=665702&view=diff
==============================================================================
--- mina/ftpserver/trunk/core/pom.xml (original)
+++ mina/ftpserver/trunk/core/pom.xml Mon Jun 9 07:29:09 2008
@@ -28,6 +28,9 @@
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
+ <include>**/*.handlers</include>
+ <include>**/*.schemas</include>
+ <include>**/*.xsd</include>
</includes>
</resource>
</resources>
@@ -91,6 +94,12 @@
<artifactId>hsqldb</artifactId>
<scope>test</scope>
</dependency>
- </dependencies>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-beans</artifactId>
+ <version>2.5.2</version>
+ </dependency>
+
+ </dependencies>
</project>
Modified: mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/FtpServer.java
URL: http://svn.apache.org/viewvc/mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/FtpServer.java?rev=665702&r1=665701&r2=665702&view=diff
==============================================================================
--- mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/FtpServer.java (original)
+++ mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/FtpServer.java Mon Jun 9 07:29:09 2008
@@ -22,7 +22,12 @@
import java.util.Map;
+import org.apache.ftpserver.ftplet.FileSystemManager;
+import org.apache.ftpserver.ftplet.Ftplet;
+import org.apache.ftpserver.ftplet.UserManager;
+import org.apache.ftpserver.interfaces.CommandFactory;
import org.apache.ftpserver.interfaces.FtpServerContext;
+import org.apache.ftpserver.interfaces.MessageResource;
import org.apache.ftpserver.listener.Listener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -52,8 +57,9 @@
}
/**
- * Constructor. Set the server context.
- * @throws Exception
+ * Constructor. Set a custom the server context.
+ * @throws Exception
+ * TODO consider removing
*/
public FtpServer(FtpServerContext serverContext) throws Exception {
this.serverContext = serverContext;
@@ -145,7 +151,123 @@
return serverContext;
}
+ /**
+ * Set a custom server context to be used for this server
+ * @param serverContext The custom server context
+ */
public void setServerContext(FtpServerContext serverContext) {
this.serverContext = serverContext;
}
+
+ private DefaultFtpServerContext checkAndGetContext() {
+ if(getServerContext() instanceof DefaultFtpServerContext) {
+ return (DefaultFtpServerContext) getServerContext();
+ } else {
+ throw new IllegalStateException("Custom FtpServerContext provided, setters can not be used on FtpServer");
+ }
+ }
+
+ /**
+ * Get all listeners available one this server
+ * @return The current listeners
+ */
+ public Map<String, Listener> getListeners() {
+ return getServerContext().getListeners();
+ }
+
+ /**
+ * Set the listeners for this server, replaces existing listeners
+ * @param listeners The listeners to use for this server with the name as the key
+ * and the listener as the value
+ * @throws IllegalStateException If a custom server context has been set
+ */
+ public void setListeners(Map<String, Listener> listeners) {
+ checkAndGetContext().setListeners(listeners);
+ }
+
+ /**
+ * Get all {@link Ftplet}s registered at this server
+ * @return All {@link Ftplet}s
+ */
+ public Map<String, Ftplet> getFtplets() {
+ return getServerContext().getFtpletContainer().getFtplets();
+ }
+
+ /**
+ * Set the {@link Ftplet}s to be active for this server. Replaces existing {@link Ftplet}s
+ * @param ftplets Ftplets as a map with the name as the key and the Ftplet as the value
+ * @throws IllegalStateException If a custom server context has been set
+ */
+ public void setFtplets(Map<String, Ftplet> ftplets) {
+ getServerContext().getFtpletContainer().setFtplets(ftplets);
+ }
+
+ /**
+ * Retrieve the user manager used with this server
+ * @return The user manager
+ */
+ public UserManager getUserManager() {
+ return getServerContext().getUserManager();
+ }
+
+ /**
+ * Set the user manager to be used for this server
+ * @param userManager The {@link UserManager}
+ * @throws IllegalStateException If a custom server context has been set
+ */
+ public void setUserManager(UserManager userManager) {
+ checkAndGetContext().setUserManager(userManager);
+ }
+
+ /**
+ * Retrieve the file system used with this server
+ * @return The {@link FileSystemManager}
+ */
+ public FileSystemManager getFileSystem() {
+ return getServerContext().getFileSystemManager();
+ }
+
+ /**
+ * Set the file system to be used for this server
+ * @param fileSystem The {@link FileSystemManager}
+ * @throws IllegalStateException If a custom server context has been set
+ */
+ public void setFileSystem(FileSystemManager fileSystem) {
+ checkAndGetContext().setFileSystemManager(fileSystem);
+ }
+
+ /**
+ * Retrieve the command factory used with this server
+ * @return The {@link CommandFactory}
+ */
+ public CommandFactory getCommandFactory() {
+ return getServerContext().getCommandFactory();
+ }
+
+ /**
+ * Set the command factory to be used for this server
+ * @param commandFactory The {@link CommandFactory}
+ * @throws IllegalStateException If a custom server context has been set
+ */
+ public void setCommandFactory(CommandFactory commandFactory) {
+ checkAndGetContext().setCommandFactory(commandFactory);
+ }
+
+ /**
+ * Retrieve the message resource used with this server
+ * @return The {@link MessageResource}
+ */
+ public MessageResource getMessageResource() {
+ return getServerContext().getMessageResource();
+ }
+
+ /**
+ * Set the message resource to be used with this server
+ * @param messageResource The {@link MessageResource}
+ * @throws IllegalStateException If a custom server context has been set
+ */
+ public void setMessageResource(MessageResource messageResource) {
+ checkAndGetContext().setMessageResource(messageResource);
+ }
+
}
Added: mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/config/spring/CommandFactoryBeanDefinitionParser.java
URL: http://svn.apache.org/viewvc/mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/config/spring/CommandFactoryBeanDefinitionParser.java?rev=665702&view=auto
==============================================================================
--- mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/config/spring/CommandFactoryBeanDefinitionParser.java (added)
+++ mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/config/spring/CommandFactoryBeanDefinitionParser.java Mon Jun 9 07:29:09 2008
@@ -0,0 +1,49 @@
+package org.apache.ftpserver.config.spring;
+
+import java.util.List;
+
+import org.apache.ftpserver.DefaultCommandFactory;
+import org.apache.ftpserver.interfaces.CommandFactory;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.support.ManagedMap;
+import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
+import org.springframework.beans.factory.xml.ParserContext;
+import org.springframework.util.StringUtils;
+import org.w3c.dom.Element;
+
+/**
+ * Parses the FtpServer "commands" element into a Spring
+ * bean graph
+ */
+public class CommandFactoryBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected Class<? extends CommandFactory> getBeanClass(Element element) {
+ return DefaultCommandFactory.class;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
+ ManagedMap commands = new ManagedMap();
+
+ List<Element> childs = SpringUtil.getChildElements(element);
+
+ for(Element commandElm : childs) {
+ String name = commandElm.getAttribute("name");
+ Object bean = SpringUtil.parseSpringChildElement(commandElm, parserContext, builder);
+ commands.put(name, bean);
+ }
+
+ builder.addPropertyValue("commandMap", commands);
+
+ if(StringUtils.hasText(element.getAttribute("use-default"))) {
+ builder.addPropertyValue("useDefaultCommands", Boolean.parseBoolean(element.getAttribute("use-default")));
+ }
+ }
+}
Added: mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/config/spring/FileSystemBeanDefinitionParser.java
URL: http://svn.apache.org/viewvc/mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/config/spring/FileSystemBeanDefinitionParser.java?rev=665702&view=auto
==============================================================================
--- mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/config/spring/FileSystemBeanDefinitionParser.java (added)
+++ mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/config/spring/FileSystemBeanDefinitionParser.java Mon Jun 9 07:29:09 2008
@@ -0,0 +1,37 @@
+package org.apache.ftpserver.config.spring;
+
+import org.apache.ftpserver.filesystem.NativeFileSystemManager;
+import org.apache.ftpserver.ftplet.FileSystemManager;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
+import org.springframework.beans.factory.xml.ParserContext;
+import org.springframework.util.StringUtils;
+import org.w3c.dom.Element;
+
+/**
+ * Parses the FtpServer "native-filesystem" element into a Spring
+ * bean graph
+ */
+public class FileSystemBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected Class<? extends FileSystemManager> getBeanClass(Element element) {
+ return NativeFileSystemManager.class;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
+ if(StringUtils.hasText(element.getAttribute("case-insensitive"))) {
+ builder.addPropertyValue("caseInsensitive", Boolean.parseBoolean(element.getAttribute("case-insensitive")));
+ }
+ if(StringUtils.hasText(element.getAttribute("create-home"))) {
+ builder.addPropertyValue("create-home", Boolean.parseBoolean(element.getAttribute("create-home")));
+ }
+ }
+}
Added: mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/config/spring/FtpServerNamespaceHandler.java
URL: http://svn.apache.org/viewvc/mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/config/spring/FtpServerNamespaceHandler.java?rev=665702&view=auto
==============================================================================
--- mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/config/spring/FtpServerNamespaceHandler.java (added)
+++ mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/config/spring/FtpServerNamespaceHandler.java Mon Jun 9 07:29:09 2008
@@ -0,0 +1,37 @@
+package org.apache.ftpserver.config.spring;
+
+import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
+
+/**
+ * Registration point for FtpServer bean defintion parsers
+ */
+public class FtpServerNamespaceHandler extends NamespaceHandlerSupport {
+
+ /**
+ * The FtpServer Spring config namespace
+ */
+ public static final String FTPSERVER_NS = "http://mina.apache.org/ftpserver/spring/v1";
+
+
+ /**
+ * Register the necessary element names with the appropriate
+ * bean definition parser
+ */
+ public FtpServerNamespaceHandler() {
+ registerBeanDefinitionParser("server", new ServerBeanDefinitionParser());
+ registerBeanDefinitionParser("nio-listener", new ListenerBeanDefinitionParser());
+ registerBeanDefinitionParser("file-user-manager", new UserManagerBeanDefinitionParser());
+ registerBeanDefinitionParser("db-user-manager", new UserManagerBeanDefinitionParser());
+ registerBeanDefinitionParser("native-filesystem", new FileSystemBeanDefinitionParser());
+ registerBeanDefinitionParser("commands", new CommandFactoryBeanDefinitionParser());
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void init() {
+ // do nothing
+ }
+
+}
Added: mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/config/spring/ListenerBeanDefinitionParser.java
URL: http://svn.apache.org/viewvc/mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/config/spring/ListenerBeanDefinitionParser.java?rev=665702&view=auto
==============================================================================
--- mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/config/spring/ListenerBeanDefinitionParser.java (added)
+++ mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/config/spring/ListenerBeanDefinitionParser.java Mon Jun 9 07:29:09 2008
@@ -0,0 +1,234 @@
+package org.apache.ftpserver.config.spring;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.ftpserver.DefaultDataConnectionConfig;
+import org.apache.ftpserver.DefaultDataConnectionConfig.Active;
+import org.apache.ftpserver.DefaultDataConnectionConfig.Passive;
+import org.apache.ftpserver.interfaces.DataConnectionConfig;
+import org.apache.ftpserver.listener.mina.MinaListener;
+import org.apache.ftpserver.ssl.DefaultSslConfiguration;
+import org.apache.ftpserver.ssl.SslConfiguration;
+import org.apache.mina.filter.firewall.Subnet;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
+import org.springframework.beans.factory.xml.ParserContext;
+import org.springframework.util.StringUtils;
+import org.w3c.dom.Element;
+
+/**
+ * Parses the FtpServer "nio-listener" element into a Spring
+ * bean graph
+ */
+public class ListenerBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected Class<MinaListener> getBeanClass(Element element) {
+ return MinaListener.class;
+ }
+
+ /**
+ * Parse CIDR notations into MINA {@link Subnet}s.
+ * TODO: move to Mina
+ */
+ private Subnet parseSubnet(String subnet) {
+ if(subnet == null) {
+ throw new NullPointerException("subnet can not be null");
+ }
+
+ String[] tokens = subnet.split("/");
+
+ String ipString;
+ String maskString;
+ if(tokens.length == 2) {
+ ipString = tokens[0];
+ maskString = tokens[1];
+ } else if(tokens.length == 1) {
+ ipString = tokens[0];
+ maskString = "32";
+ } else {
+ throw new IllegalArgumentException("Illegal subnet format: " + subnet);
+ }
+
+ InetAddress address;
+ try {
+ address = InetAddress.getByName(ipString);
+ } catch (UnknownHostException e) {
+ throw new IllegalArgumentException("Illegal IP address in subnet: " + subnet);
+ }
+
+ int mask = Integer.parseInt(maskString);
+ if(mask < 0 || mask > 32) {
+ throw new IllegalArgumentException("Mask must be in the range 0-32");
+ }
+
+ return new Subnet(address, mask);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
+ if(StringUtils.hasText(element.getAttribute("port"))) {
+ builder.addPropertyValue("port", Integer.parseInt(element.getAttribute("port")));
+ }
+
+ SslConfiguration ssl = parseSsl(element);
+ if(ssl != null) {
+ builder.addPropertyValue("ssl", ssl);
+ }
+
+ Element dataConElm = SpringUtil.getChildElement(element, FtpServerNamespaceHandler.FTPSERVER_NS, "data-connection");
+ if(dataConElm != null) {
+ DataConnectionConfig dc = parseDataConnection(dataConElm);
+ builder.addPropertyValue("dataConnection", dc);
+ }
+
+ Element blacklistElm = SpringUtil.getChildElement(element, FtpServerNamespaceHandler.FTPSERVER_NS, "blacklist");
+ if(blacklistElm != null && StringUtils.hasText(blacklistElm.getTextContent())) {
+ String[] blocks = blacklistElm.getTextContent().split("[\\s,]+");
+ List<Subnet> subnets = new ArrayList<Subnet>();
+
+ for(String block : blocks) {
+ subnets.add(parseSubnet(block));
+ }
+
+ builder.addPropertyValue("blockedSubnets", subnets);
+ }
+
+ if(StringUtils.hasText(element.getAttribute("idle-timeout"))) {
+ builder.addPropertyValue("idleTimeout", SpringUtil.parseInt(element, "idle-timeout", 300));
+ }
+ if(StringUtils.hasText(element.getAttribute("port"))) {
+ builder.addPropertyValue("port", SpringUtil.parseInt(element, "port", 21));
+ }
+ InetAddress localAddress = SpringUtil.parseInetAddress(element, "local-address");
+ if(localAddress != null) {
+ builder.addPropertyValue("localAddress", localAddress);
+ }
+ builder.addPropertyValue("implicitSsl", SpringUtil.parseBoolean(element, "implicit-ssl", false));
+ }
+
+
+ private SslConfiguration parseSsl(Element parent) {
+ Element sslElm = SpringUtil.getChildElement(parent, FtpServerNamespaceHandler.FTPSERVER_NS, "ssl");
+
+ if(sslElm != null) {
+ DefaultSslConfiguration ssl = new DefaultSslConfiguration();
+
+ Element keyStoreElm = SpringUtil.getChildElement(sslElm, FtpServerNamespaceHandler.FTPSERVER_NS, "keystore");
+ if(keyStoreElm != null) {
+ ssl.setKeystoreFile(SpringUtil.parseFile(keyStoreElm, "file"));
+ ssl.setKeystorePassword(SpringUtil.parseString(keyStoreElm, "password"));
+
+ String type = SpringUtil.parseString(keyStoreElm, "type");
+ if(type != null) {
+ ssl.setKeystoreType(type);
+ }
+
+ String keyAlias = SpringUtil.parseString(keyStoreElm, "key-alias");
+ if(keyAlias != null) {
+ ssl.setKeyAlias(keyAlias);
+ }
+
+ String keyPassword = SpringUtil.parseString(keyStoreElm, "key-password");
+ if(keyPassword != null) {
+ ssl.setKeyPassword(keyPassword);
+ }
+
+ String algorithm = SpringUtil.parseString(keyStoreElm, "algorithm");
+ if(algorithm != null) {
+ ssl.setKeystoreAlgorithm(algorithm);
+ }
+ }
+
+ Element trustStoreElm = SpringUtil.getChildElement(sslElm, FtpServerNamespaceHandler.FTPSERVER_NS, "truststore");
+ if(trustStoreElm != null) {
+ ssl.setTruststoreFile(SpringUtil.parseFile(trustStoreElm, "file"));
+ ssl.setTruststorePassword(SpringUtil.parseString(trustStoreElm, "password"));
+
+ String type = SpringUtil.parseString(trustStoreElm, "type");
+ if(type != null) {
+ ssl.setTruststoreType(type);
+ }
+
+ String algorithm = SpringUtil.parseString(trustStoreElm, "algorithm");
+ if(algorithm != null) {
+ ssl.setTruststoreAlgorithm(algorithm);
+ }
+ }
+
+ String clientAuthStr = SpringUtil.parseString(sslElm, "client-authentication");
+ if(clientAuthStr != null) {
+ ssl.setClientAuthentication(clientAuthStr);
+ }
+
+ String enabledCiphersuites = SpringUtil.parseString(sslElm, "enabled-ciphersuites");
+ if(enabledCiphersuites != null) {
+ ssl.setEnabledCipherSuites(enabledCiphersuites.split(" "));
+ }
+
+ return ssl;
+ } else {
+ return null;
+ }
+
+
+ }
+
+ private DataConnectionConfig parseDataConnection(Element element) {
+ DefaultDataConnectionConfig dc = new DefaultDataConnectionConfig();
+
+ SslConfiguration ssl = parseSsl(element);
+ if(ssl != null) {
+ dc.setSsl(ssl);
+ }
+
+ Element activeElm = SpringUtil.getChildElement(element, FtpServerNamespaceHandler.FTPSERVER_NS, "active");
+ if(activeElm != null) {
+ Active active = new Active();
+ active.setEnable(SpringUtil.parseBoolean(activeElm, "enabled", true));
+ active.setIpCheck(SpringUtil.parseBoolean(activeElm, "ip-check", false));
+ active.setLocalPort(SpringUtil.parseInt(activeElm, "local-port", 0));
+
+ InetAddress localAddress = SpringUtil.parseInetAddress(activeElm, "local-address");
+ if(localAddress != null) {
+ active.setLocalAddress(localAddress);
+ }
+
+ dc.setActive(active);
+ }
+
+ Element passiveElm = SpringUtil.getChildElement(element, FtpServerNamespaceHandler.FTPSERVER_NS, "passive");
+ if(passiveElm != null) {
+ Passive passive = new Passive();
+
+ InetAddress address = SpringUtil.parseInetAddress(passiveElm, "address");
+ if(address != null) {
+ passive.setAddress(address);
+ }
+
+ InetAddress externalAddress = SpringUtil.parseInetAddress(passiveElm, "external-address");
+ if(externalAddress != null) {
+ passive.setExternalAddress(externalAddress);
+ }
+
+ String ports = SpringUtil.parseString(passiveElm, "ports");
+ if(ports != null) {
+ passive.setPorts(ports);
+ }
+ dc.setPassive(passive);
+ }
+
+ return dc;
+ }
+
+
+}
Added: mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/config/spring/ServerBeanDefinitionParser.java
URL: http://svn.apache.org/viewvc/mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/config/spring/ServerBeanDefinitionParser.java?rev=665702&view=auto
==============================================================================
--- mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/config/spring/ServerBeanDefinitionParser.java (added)
+++ mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/config/spring/ServerBeanDefinitionParser.java Mon Jun 9 07:29:09 2008
@@ -0,0 +1,141 @@
+package org.apache.ftpserver.config.spring;
+
+import java.io.File;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.ftpserver.FtpServer;
+import org.apache.ftpserver.FtpServerConfigurationException;
+import org.apache.ftpserver.interfaces.MessageResource;
+import org.apache.ftpserver.message.MessageResourceImpl;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.support.ManagedMap;
+import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
+import org.springframework.beans.factory.xml.ParserContext;
+import org.springframework.util.StringUtils;
+import org.w3c.dom.Element;
+
+/**
+ * Parses the FtpServer "server" element into a Spring
+ * bean graph
+ */
+public class ServerBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
+
+
+ /**
+ * {@inheritDoc}
+ */
+ protected Class<? extends FtpServer> getBeanClass(Element element) {
+ return FtpServer.class;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
+ List<Element> childs = SpringUtil.getChildElements(element);
+ for(Element childElm : childs) {
+ String childName = childElm.getLocalName();
+
+ if("listeners".equals(childName)) {
+ Map listeners = parseListeners(childElm, parserContext, builder);
+
+ if(listeners.size() > 0) {
+ builder.addPropertyValue("listeners", listeners);
+ }
+ } else if("ftplets".equals(childName)) {
+ Map ftplets = parseFtplets(childElm, parserContext, builder);
+ builder.addPropertyValue("ftplets", ftplets);
+ } else if("file-user-manager".equals(childName) ||
+ "db-user-manager".equals(childName)) {
+ Object userManager = parserContext.getDelegate().parseCustomElement(childElm, builder.getBeanDefinition());
+ builder.addPropertyValue("userManager", userManager);
+ } else if("user-manager".equals(childName)) {
+ builder.addPropertyValue("userManager", SpringUtil.parseSpringChildElement(childElm, parserContext, builder));
+ } else if("native-filesystem".equals(childName)) {
+ Object fileSystem = parserContext.getDelegate().parseCustomElement(childElm, builder.getBeanDefinition());
+ builder.addPropertyValue("fileSystem", fileSystem);
+ } else if("filesystem".equals(childName)) {
+ builder.addPropertyValue("fileSystem", SpringUtil.parseSpringChildElement(childElm, parserContext, builder));
+ } else if("commands".equals(childName)) {
+ Object commandFactory = parserContext.getDelegate().parseCustomElement(childElm, builder.getBeanDefinition());
+ builder.addPropertyValue("commandFactory", commandFactory);
+ } else if("messages".equals(childName)) {
+ MessageResource mr = parseMessageResource(childElm, parserContext, builder);
+ builder.addPropertyValue("messageResource", mr);
+
+ } else {
+ throw new FtpServerConfigurationException("Unknown configuration name: " + childName);
+ }
+ }
+ }
+
+ /**
+ * Parse the "messages" element
+ */
+ private MessageResource parseMessageResource(Element childElm, ParserContext parserContext,
+ BeanDefinitionBuilder builder) {
+
+ MessageResourceImpl mr = new MessageResourceImpl();
+
+ if(StringUtils.hasText(childElm.getAttribute("languages"))) {
+ String langString = childElm.getAttribute("languages");
+
+ String[] languages = langString.split("[\\s,]+");
+
+ mr.setLanguages(languages);
+ }
+
+ if(StringUtils.hasText(childElm.getAttribute("directory"))) {
+ mr.setCustomMessageDirectory(new File(childElm.getAttribute("directory")));
+
+ }
+
+ return mr;
+ }
+
+ /**
+ * Parse the "ftplets" element
+ */
+ private Map parseFtplets(Element childElm, ParserContext parserContext, BeanDefinitionBuilder builder) {
+ ManagedMap ftplets = new ManagedMap();
+
+ List<Element> childs = SpringUtil.getChildElements(childElm);
+
+ for(Element ftpletElm : childs) {
+ ftplets.put(ftpletElm.getAttribute("name"),
+ SpringUtil.parseSpringChildElement(ftpletElm, parserContext, builder));
+ }
+
+ return ftplets;
+ }
+
+ /**
+ * Parse listeners elements
+ */
+ @SuppressWarnings("unchecked")
+ private Map parseListeners(Element listenersElm, ParserContext parserContext, BeanDefinitionBuilder builder) {
+ ManagedMap listeners = new ManagedMap();
+
+ List<Element> childs = SpringUtil.getChildElements(listenersElm);
+
+ for(Element listenerElm : childs) {
+ Object listener = null;
+ String ln = listenerElm.getLocalName();
+ if("nio-listener".equals(ln)) {
+ listener = parserContext.getDelegate().parseCustomElement(listenerElm, builder.getBeanDefinition());
+ } else if ("listener".equals(ln)) {
+ listener = SpringUtil.parseSpringChildElement(listenerElm, parserContext, builder);
+ } else {
+ throw new FtpServerConfigurationException("Unknown listener element " + ln);
+ }
+
+ String name = listenerElm.getAttribute("name");
+
+ listeners.put(name, listener);
+ }
+
+ return listeners;
+ }
+}
Added: mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/config/spring/SpringUtil.java
URL: http://svn.apache.org/viewvc/mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/config/spring/SpringUtil.java?rev=665702&view=auto
==============================================================================
--- mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/config/spring/SpringUtil.java (added)
+++ mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/config/spring/SpringUtil.java Mon Jun 9 07:29:09 2008
@@ -0,0 +1,151 @@
+package org.apache.ftpserver.config.spring;
+
+import java.io.File;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.ftpserver.FtpServerConfigurationException;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.xml.ParserContext;
+import org.springframework.util.StringUtils;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * Various util methods for the Spring config parsing and configuration
+ */
+public class SpringUtil {
+
+ /**
+ * Get all child elements for the element
+ * @param elm The element for which to locate children
+ * @return All children
+ */
+ public static List<Element> getChildElements(Element elm) {
+ List<Element> elements = new ArrayList<Element>();
+ NodeList childs = elm.getChildNodes();
+ for(int i = 0; i<childs.getLength(); i++) {
+ Node child = childs.item(i);
+
+ if(child instanceof Element) {
+ elements.add((Element) child);
+ }
+ }
+
+ return elements;
+ }
+
+ /**
+ * Get the first child element matching the local name and namespace
+ * @param parent The element for which to locate the child
+ * @param ns The namespace to match, or null for any namespace
+ * @param localName The local name to match, or null for any local name
+ * @return The first child matching the criteria
+ */
+ public static Element getChildElement(Element parent, String ns, String localName) {
+ List<Element> elements = getChildElements(parent);
+
+ for(Element element : elements) {
+ if((ns == null || ns.equals(element.getNamespaceURI()) &&
+ (localName == null || localName.equals(element.getLocalName())))) {
+ return element;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Parse specific Spring elements, bean and ref
+ * @param parent The element in which we will look for Spring elements
+ * @param parserContext The Spring parser context
+ * @param builder The Spring bean definition builder
+ * @return The Spring bean definition
+ */
+ public static Object parseSpringChildElement(Element parent, ParserContext parserContext, BeanDefinitionBuilder builder) {
+ Element springElm = getChildElement(parent, null, null);
+
+ String ln = springElm.getLocalName();
+ if("bean".equals(ln)) {
+ return parserContext.getDelegate().parseBeanDefinitionElement(springElm, builder.getBeanDefinition());
+ } else if("ref".equals(ln)) {
+ return parserContext.getDelegate().parsePropertySubElement(springElm, builder.getBeanDefinition());
+ } else {
+ throw new FtpServerConfigurationException("Unknown spring element " + ln);
+ }
+ }
+
+ /**
+ * Parses a attribute value into a boolean.
+ * If the attribute is missing or has no content, a default value is returned
+ * @param parent The element
+ * @param attrName The attribute name
+ * @param defaultValue The default value
+ * @return The value, or the default value
+ */
+ public static boolean parseBoolean(Element parent, String attrName, boolean defaultValue) {
+ if(StringUtils.hasText(parent.getAttribute(attrName))) {
+ return Boolean.parseBoolean(parent.getAttribute(attrName));
+ }
+ return defaultValue;
+ }
+
+ /**
+ * Parses a attribute value into an integer.
+ * If the attribute is missing or has no content, a default value is returned
+ * @param parent The element
+ * @param attrName The attribute name
+ * @param defaultValue The default value
+ * @return The value, or the default value
+ */
+ public static int parseInt(Element parent, String attrName, int defaultValue) {
+ if(StringUtils.hasText(parent.getAttribute(attrName))) {
+ return Integer.parseInt(parent.getAttribute(attrName));
+ }
+ return defaultValue;
+ }
+
+ /**
+ * Return the string value of an attribute, or null if the attribute is missing
+ * @param parent The element
+ * @param attrName The attribute name
+ * @return The attribute string value
+ */
+ public static String parseString(Element parent, String attrName) {
+ return parent.getAttribute(attrName);
+ }
+
+ /**
+ * Return an attribute value as a {@link File}
+ * @param parent The element
+ * @param attrName The attribute name
+ * @return The file representing the path used in the attribute
+ */
+ public static File parseFile(Element parent, String attrName) {
+ if(StringUtils.hasText(parent.getAttribute(attrName))) {
+ return new File(parent.getAttribute(attrName));
+ }
+ return null;
+ }
+
+ /**
+ * Return an attribute value as an {@link InetAddress}
+ * @param parent The element
+ * @param attrName The attribute name
+ * @return The attribute value parsed into a {@link InetAddress}
+ */
+ public static InetAddress parseInetAddress(Element parent, String attrName) {
+ if(StringUtils.hasText(parent.getAttribute(attrName))) {
+ try {
+ return InetAddress.getByName(parent.getAttribute(attrName));
+ } catch (UnknownHostException e) {
+ throw new FtpServerConfigurationException("Unknown host", e);
+ }
+ }
+ return null;
+ }
+
+}
Added: mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/config/spring/UserManagerBeanDefinitionParser.java
URL: http://svn.apache.org/viewvc/mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/config/spring/UserManagerBeanDefinitionParser.java?rev=665702&view=auto
==============================================================================
--- mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/config/spring/UserManagerBeanDefinitionParser.java (added)
+++ mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/config/spring/UserManagerBeanDefinitionParser.java Mon Jun 9 07:29:09 2008
@@ -0,0 +1,52 @@
+package org.apache.ftpserver.config.spring;
+
+import org.apache.ftpserver.ftplet.UserManager;
+import org.apache.ftpserver.usermanager.DbUserManager;
+import org.apache.ftpserver.usermanager.PropertiesUserManager;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
+import org.springframework.beans.factory.xml.ParserContext;
+import org.springframework.util.StringUtils;
+import org.w3c.dom.Element;
+
+/**
+ * Parses the FtpServer "file-user-manager" or "db-user-manager" elements into a Spring
+ * bean graph
+ */
+public class UserManagerBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
+
+ @Override
+ protected Class<? extends UserManager> getBeanClass(Element element) {
+ if(element.getLocalName().equals("file-user-manager")) {
+ return PropertiesUserManager.class;
+ } else {
+ return DbUserManager.class;
+ }
+ }
+
+ @Override
+ protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
+ if(getBeanClass(element) == PropertiesUserManager.class) {
+ builder.addPropertyValue("propFile", element.getAttribute("file"));
+ if(StringUtils.hasText(element.getAttribute("encrypt-passwords")) &&
+ element.getAttribute("encrypt-passwords").equals("true")) {
+ builder.addPropertyValue("encryptPasswords", true);
+ }
+ } else {
+ Element dsElm = SpringUtil.getChildElement(element,
+ FtpServerNamespaceHandler.FTPSERVER_NS, "data-source");
+
+ // schema ensure we get the right type of element
+ Element springElm = SpringUtil.getChildElement(dsElm, null, null);
+ Object o;
+ if("bean".equals(springElm.getLocalName())) {
+ o = parserContext.getDelegate().parseBeanDefinitionElement(springElm, builder.getBeanDefinition());
+ } else {
+ // ref
+ o = parserContext.getDelegate().parsePropertySubElement(springElm, builder.getBeanDefinition());
+
+ }
+ builder.addPropertyValue("dataSource", o);
+ }
+ }
+}
Modified: mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/interfaces/CommandFactory.java
URL: http://svn.apache.org/viewvc/mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/interfaces/CommandFactory.java?rev=665702&r1=665701&r2=665702&view=diff
==============================================================================
--- mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/interfaces/CommandFactory.java (original)
+++ mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/interfaces/CommandFactory.java Mon Jun 9 07:29:09 2008
@@ -19,6 +19,10 @@
package org.apache.ftpserver.interfaces;
+import java.util.Map;
+
+import com.sun.org.apache.bcel.internal.generic.ISUB;
+
/**
* Command factory interface.
@@ -30,4 +34,41 @@
* Get the command instance.
*/
Command getCommand(String commandName);
+
+ /**
+ * Get the registered SITE commands
+ * @return Active site commands, the key is
+ * the site command name, used in FTP
+ * sessions as SITE <command name>
+ */
+// Map<String, Command> getSiteCommands();
+
+ /**
+ * Register SITE commands. The map can replace or
+ * append to the default SITE commands provided
+ * by FtpServer depending on the value of
+ * {@see CommandFactory#isUseDefaultSiteCommands()}
+ * @param siteCommands Active site commands, the key is
+ * the site command name, used in FTP
+ * sessions as SITE <command name>. The value is the
+ * command
+ */
+// void setSiteCommands(Map<String, Command> siteCommands);
+
+ /**
+ * Should custom site commands append to or replace
+ * the default commands provided by FtpServer?.
+ * The default is to append
+ * @return true if custom commands should append to the default,
+ * false if they should replace
+ */
+// boolean isUseDefaultSiteCommands();
+
+ /**
+ * Should custom site commands append to or replace
+ * the default commands provided by FtpServer?.
+ * @param useDefaultSiteCommands true if custom commands should append to the default,
+ * false if they should replace
+ */
+// void setUseDefaultSiteCommands(boolean useDefaultSiteCommands);
}
Added: mina/ftpserver/trunk/core/src/main/resources/META-INF/spring.handlers
URL: http://svn.apache.org/viewvc/mina/ftpserver/trunk/core/src/main/resources/META-INF/spring.handlers?rev=665702&view=auto
==============================================================================
--- mina/ftpserver/trunk/core/src/main/resources/META-INF/spring.handlers (added)
+++ mina/ftpserver/trunk/core/src/main/resources/META-INF/spring.handlers Mon Jun 9 07:29:09 2008
@@ -0,0 +1 @@
+http\://mina.apache.org/ftpserver/spring/v1=org.apache.ftpserver.config.spring.FtpServerNamespaceHandler
\ No newline at end of file
Added: mina/ftpserver/trunk/core/src/main/resources/META-INF/spring.schemas
URL: http://svn.apache.org/viewvc/mina/ftpserver/trunk/core/src/main/resources/META-INF/spring.schemas?rev=665702&view=auto
==============================================================================
--- mina/ftpserver/trunk/core/src/main/resources/META-INF/spring.schemas (added)
+++ mina/ftpserver/trunk/core/src/main/resources/META-INF/spring.schemas Mon Jun 9 07:29:09 2008
@@ -0,0 +1 @@
+http\://mina.apache.org/ftpserver/ftpserver-1.0.xsd=org/apache/ftpserver/config/spring/ftpserver-1.0.xsd
\ No newline at end of file
Added: mina/ftpserver/trunk/core/src/main/resources/org/apache/ftpserver/config/spring/ftpserver-1.0.xsd
URL: http://svn.apache.org/viewvc/mina/ftpserver/trunk/core/src/main/resources/org/apache/ftpserver/config/spring/ftpserver-1.0.xsd?rev=665702&view=auto
==============================================================================
--- mina/ftpserver/trunk/core/src/main/resources/org/apache/ftpserver/config/spring/ftpserver-1.0.xsd (added)
+++ mina/ftpserver/trunk/core/src/main/resources/org/apache/ftpserver/config/spring/ftpserver-1.0.xsd Mon Jun 9 07:29:09 2008
@@ -0,0 +1,223 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
+ targetNamespace="http://mina.apache.org/ftpserver/spring/v1"
+ xmlns="http://mina.apache.org/ftpserver/spring/v1"
+ xmlns:beans="http://www.springframework.org/schema/beans">
+
+ <!-- Import the Spring beans XML schema -->
+ <xs:import namespace="http://www.springframework.org/schema/beans"
+ schemaLocation="http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"/>
+
+ <!-- The main entry point, used for setting up an entire FTP server -->
+ <xs:element name="server">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" name="listeners">
+ <xs:complexType>
+ <xs:choice minOccurs="1" maxOccurs="unbounded">
+ <xs:element ref="nio-listener"/>
+ <xs:element ref="listener"/>
+ </xs:choice>
+ </xs:complexType>
+ </xs:element>
+ <xs:element minOccurs="0" ref="ftplets"/>
+ <xs:choice minOccurs="0" maxOccurs="1">
+ <xs:element minOccurs="0" ref="file-user-manager"/>
+ <xs:element minOccurs="0" ref="db-user-manager"/>
+ <xs:element minOccurs="0" ref="user-manager"/>
+ </xs:choice>
+ <xs:choice minOccurs="0" maxOccurs="1">
+ <xs:element minOccurs="0" ref="native-filesystem"/>
+ <xs:element minOccurs="0" ref="filesystem"/>
+ </xs:choice>
+ <xs:element minOccurs="0" ref="commands"/>
+ <xs:element minOccurs="0" ref="messages"/>
+ </xs:sequence>
+ <xs:attribute name="id" type="xs:ID"/>
+
+ </xs:complexType>
+ </xs:element>
+
+ <!-- Reusable element for defining SSL properties -->
+ <xs:element name="ssl">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" name="keystore">
+ <xs:complexType>
+ <xs:attribute name="file"/>
+ <xs:attribute name="password"/>
+ <xs:attribute name="type"/>
+ <xs:attribute name="algorithm"/>
+ <xs:attribute name="key-alias"/>
+ <xs:attribute name="key-password"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element minOccurs="0" name="truststore">
+ <xs:complexType>
+ <xs:attribute name="file"/>
+ <xs:attribute name="password"/>
+ <xs:attribute name="type"/>
+ <xs:attribute name="algorithm"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="client-authentication" type="xs:string"/>
+ <xs:attribute name="enabled-ciphersuites"/>
+ </xs:complexType>
+ </xs:element>
+
+ <!-- Element used to define the default, NIO based listener -->
+ <xs:element name="nio-listener">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="ssl"/>
+ <xs:element minOccurs="0" name="data-connection">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="ssl"/>
+ <xs:element minOccurs="0" name="active">
+ <xs:complexType>
+ <xs:attribute name="enabled" type="xs:boolean"/>
+ <xs:attribute name="local-address"/>
+ <xs:attribute name="local-port" type="xs:int"/>
+ <xs:attribute name="ip-check" type="xs:boolean"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element minOccurs="0" name="passive">
+ <xs:complexType>
+ <xs:attribute name="address"/>
+ <xs:attribute name="external-address"/>
+ <xs:attribute name="ports"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="idle-timeout" type="xs:int"/>
+ </xs:complexType>
+
+ </xs:element>
+ <xs:element minOccurs="0" name="blacklist" type="xs:string"/>
+ </xs:sequence>
+ <xs:attribute name="name" use="required" type="xs:string"/>
+ <xs:attribute name="local-address"/>
+ <xs:attribute name="port" type="xs:int"/>
+ <xs:attribute name="idle-timeout" type="xs:int"/>
+ <xs:attribute name="implicit-ssl" type="xs:boolean"/>
+ </xs:complexType>
+ </xs:element>
+
+ <!-- Extension element used for defining a custom listener -->
+ <xs:element name="listener" type="spring-bean-or-ref-with-name"/>
+
+ <!-- Element used to configure Ftplets for used with the server -->
+ <xs:element name="ftplets">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="ftplet">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:choice maxOccurs="unbounded">
+ <xs:element ref="beans:bean"/>
+ <xs:element ref="beans:ref"/>
+ </xs:choice>
+ </xs:sequence>
+ <xs:attribute name="name" use="required" type="xs:string"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <!-- Element used to configure a file based user manager -->
+ <xs:element name="file-user-manager">
+ <xs:complexType>
+ <xs:attribute name="file" use="required" type="xs:string"/>
+ <xs:attribute name="encrypt-passwords" type="xs:boolean"/>
+ </xs:complexType>
+ </xs:element>
+
+ <!-- Element used to configure a database based user manager -->
+ <xs:element name="db-user-manager">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="data-source" type="spring-bean-or-ref"/>
+ <xs:element name="statements">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="insert-user" type="xs:string"/>
+ <xs:element name="update-user" type="xs:string"/>
+ <xs:element name="delete-user" type="xs:string"/>
+ <xs:element name="select-user" type="xs:string"/>
+ <xs:element name="select-all-users" type="xs:string"/>
+ <xs:element name="is-admin" type="xs:string"/>
+ <xs:element name="authenticate" type="xs:string"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <!-- Extension element used for defining a custom user manager -->
+ <xs:element name="user-manager" type="spring-bean-or-ref"/>
+
+ <!-- Element used to configure the default file system -->
+ <xs:element name="native-filesystem">
+ <xs:complexType>
+ <xs:attribute name="case-insensitive" type="xs:boolean"/>
+ <xs:attribute name="create-home" type="xs:boolean"/>
+ </xs:complexType>
+ </xs:element>
+
+ <!-- Extension element used for defining a custom file system -->
+ <xs:element name="filesystem" type="spring-bean-or-ref"/>
+
+ <!-- Element used to provide custom command implementations -->
+ <xs:element name="commands">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="command">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:choice maxOccurs="unbounded">
+ <xs:element ref="beans:bean"/>
+ <xs:element ref="beans:ref"/>
+ </xs:choice>
+ </xs:sequence>
+ <xs:attribute name="name" use="required"/>
+ </xs:complexType>
+
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="use-default" type="xs:boolean"/>
+ </xs:complexType>
+ </xs:element>
+
+ <!-- Element used to configure and localize messages -->
+ <xs:element name="messages">
+ <xs:complexType>
+ <xs:attribute name="languages"/>
+ <xs:attribute name="directory"/>
+ </xs:complexType>
+ </xs:element>
+
+ <!-- Reusable type used for extension elements -->
+ <xs:complexType name="spring-bean-or-ref">
+ <xs:choice>
+ <xs:element ref="beans:bean"/>
+ <xs:element ref="beans:ref"/>
+ </xs:choice>
+ </xs:complexType>
+
+ <!-- Reusable type used for named extension elements -->
+ <xs:complexType name="spring-bean-or-ref-with-name">
+ <xs:sequence>
+ <xs:choice>
+ <xs:element ref="beans:bean"/>
+ <xs:element ref="beans:ref"/>
+ </xs:choice>
+
+ </xs:sequence>
+ <xs:attribute name="name" use="required" type="xs:string"/>
+ </xs:complexType>
+
+</xs:schema>
Added: mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/config/spring/SpringConfigTest.java
URL: http://svn.apache.org/viewvc/mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/config/spring/SpringConfigTest.java?rev=665702&view=auto
==============================================================================
--- mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/config/spring/SpringConfigTest.java (added)
+++ mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/config/spring/SpringConfigTest.java Mon Jun 9 07:29:09 2008
@@ -0,0 +1,61 @@
+package org.apache.ftpserver.config.spring;
+
+import java.net.InetAddress;
+import java.util.List;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+import org.apache.ftpserver.DefaultCommandFactory;
+import org.apache.ftpserver.FtpServer;
+import org.apache.ftpserver.command.HELP;
+import org.apache.ftpserver.listener.Listener;
+import org.apache.ftpserver.listener.mina.MinaListener;
+import org.apache.mina.filter.firewall.Subnet;
+import org.springframework.beans.factory.xml.XmlBeanFactory;
+import org.springframework.core.io.FileSystemResource;
+
+public class SpringConfigTest extends TestCase {
+
+ public void test() throws Throwable {
+ XmlBeanFactory factory = new XmlBeanFactory(new FileSystemResource("src/test/resources/spring-config/config-spring-1.xml"));
+
+ FtpServer server = (FtpServer) factory.getBean("server");
+ server.start();
+
+ Map<String, Listener> listeners = server.getServerContext().getListeners();
+ assertEquals(3, listeners.size());
+
+ Listener listener = listeners.get("listener0");
+ assertNotNull(listener);
+ assertTrue(listener instanceof MinaListener);
+ assertEquals(2222, ((MinaListener)listener).getPort());
+
+ List<Subnet> subnets = ((MinaListener)listener).getBlockedSubnets();
+ assertEquals(3, subnets.size());
+ assertEquals(new Subnet(InetAddress.getByName("1.2.3.0"), 16), subnets.get(0));
+ assertEquals(new Subnet(InetAddress.getByName("1.2.4.0"), 16), subnets.get(1));
+ assertEquals(new Subnet(InetAddress.getByName("1.2.3.4"), 32), subnets.get(2));
+
+ listener = listeners.get("listener1");
+ assertNotNull(listener);
+ assertTrue(listener instanceof MinaListener);
+ assertEquals(2223, ((MinaListener)listener).getPort());
+
+ listener = listeners.get("listener2");
+ assertNotNull(listener);
+ assertTrue(listener instanceof MinaListener);
+ assertEquals(2224, ((MinaListener)listener).getPort());
+
+ DefaultCommandFactory cf = (DefaultCommandFactory) server.getServerContext().getCommandFactory();
+ assertEquals(1, cf.getCommandMap().size());
+ assertTrue(cf.getCommand("FOO") instanceof HELP);
+
+ String[] languages = server.getServerContext().getMessageResource().getAvailableLanguages();
+
+ assertEquals(3, languages.length);
+ assertEquals("se", languages[0]);
+ assertEquals("no", languages[1]);
+ assertEquals("da", languages[2]);
+ }
+}
Added: mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/config/spring/TestFtplet.java
URL: http://svn.apache.org/viewvc/mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/config/spring/TestFtplet.java?rev=665702&view=auto
==============================================================================
--- mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/config/spring/TestFtplet.java (added)
+++ mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/config/spring/TestFtplet.java Mon Jun 9 07:29:09 2008
@@ -0,0 +1,17 @@
+package org.apache.ftpserver.config.spring;
+
+import org.apache.ftpserver.ftplet.DefaultFtplet;
+
+public class TestFtplet extends DefaultFtplet {
+
+ private int foo;
+
+ public int getFoo() {
+ return foo;
+ }
+
+ public void setFoo(int foo) {
+ this.foo = foo;
+ }
+
+}
Added: mina/ftpserver/trunk/core/src/test/resources/spring-config/config-spring-1.xml
URL: http://svn.apache.org/viewvc/mina/ftpserver/trunk/core/src/test/resources/spring-config/config-spring-1.xml?rev=665702&view=auto
==============================================================================
--- mina/ftpserver/trunk/core/src/test/resources/spring-config/config-spring-1.xml (added)
+++ mina/ftpserver/trunk/core/src/test/resources/spring-config/config-spring-1.xml Mon Jun 9 07:29:09 2008
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans:beans xmlns="http://mina.apache.org/ftpserver/spring/v1"
+ xmlns:beans="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
+ http://mina.apache.org/ftpserver/spring/v1 http://mina.apache.org/ftpserver/ftpserver-1.0.xsd
+ ">
+
+ <beans:bean id="listener1" class="org.apache.ftpserver.listener.mina.MinaListener">
+ <beans:property name="port" value="2223"/>
+ </beans:bean>
+
+ <server id="server">
+ <listeners>
+ <nio-listener name="listener0" port="2222">
+ <data-connection>
+ <ssl>
+ <keystore file="/tmp/tmp.jks" password="secret"/>
+ </ssl>
+ <active enabled="true" local-address="1.2.3.4"/>
+ <passive ports="123-125"/>
+ </data-connection>
+ <blacklist>1.2.3.0/16, 1.2.4.0/16, 1.2.3.4</blacklist>
+ </nio-listener>
+ <listener name="listener1">
+ <beans:ref bean="listener1"/>
+ </listener>
+ <listener name="listener2">
+ <beans:bean class="org.apache.ftpserver.listener.mina.MinaListener">
+ <beans:property name="port" value="2224"/>
+ </beans:bean>
+ </listener>
+ </listeners>
+ <ftplets>
+ <ftplet name="ftplet1">
+ <beans:bean class="org.apache.ftpserver.config.spring.TestFtplet">
+ <beans:property name="foo" value="123"/>
+ </beans:bean>
+
+ </ftplet>
+ </ftplets>
+ <!--<file-user-manager file="/tmp/foo.users" encrypt-passwords="true" />-->
+ <user-manager>
+ <beans:bean class="org.apache.ftpserver.usermanager.PropertiesUserManager"/>
+ </user-manager>
+ <native-filesystem case-insensitive="false" />
+ <commands use-default="false">
+ <command name="FOO">
+ <beans:bean class="org.apache.ftpserver.command.HELP" />
+ </command>
+ </commands>
+ <messages languages="se no ,da" />
+ </server>
+</beans:beans>