This is an automated email from the ASF dual-hosted git repository.
elecharny pushed a commit to branch 1.2.X
in repository https://gitbox.apache.org/repos/asf/mina-ftpserver.git
The following commit(s) were added to refs/heads/1.2.X by this push:
new 081801d6 - Code refactoring - Javadoc addition - Minor cosmetic changes
081801d6 is described below
commit 081801d6969425ac19cbf3b71c0498192803cc10
Author: emmanuel lecharny <[email protected]>
AuthorDate: Tue Jul 4 00:47:00 2023 +0200
- Code refactoring
- Javadoc addition
- Minor cosmetic changes
---
.../java/org/apache/ftpserver/command/Command.java | 11 +-
.../apache/ftpserver/command/CommandFactory.java | 36 ------
.../ftpserver/command/CommandFactoryFactory.java | 138 ++++++++++++---------
.../command/impl/DefaultCommandFactory.java | 13 +-
.../org/apache/ftpserver/command/impl/HELP.java | 10 +-
.../apache/ftpserver/impl/DefaultFtpRequest.java | 21 ++--
.../apache/ftpserver/impl/DefaultFtpServer.java | 1 +
.../ftpserver/impl/DefaultFtpServerContext.java | 7 +-
.../apache/ftpserver/impl/FtpReplyTranslator.java | 8 +-
.../ftpserver/message/MessageResourceFactory.java | 3 +-
.../message/impl/DefaultMessageResource.java | 117 +++++++++--------
.../usermanager/DbUserManagerFactory.java | 7 ++
.../usermanager/PropertiesUserManagerFactory.java | 14 +--
.../usermanager/impl/PropertiesUserManager.java | 3 +-
.../org/apache/ftpserver/util/PasswordUtil.java | 26 ++--
15 files changed, 217 insertions(+), 198 deletions(-)
diff --git a/core/src/main/java/org/apache/ftpserver/command/Command.java
b/core/src/main/java/org/apache/ftpserver/command/Command.java
index a0fb8035..7dd7f53f 100644
--- a/core/src/main/java/org/apache/ftpserver/command/Command.java
+++ b/core/src/main/java/org/apache/ftpserver/command/Command.java
@@ -32,19 +32,14 @@ import org.apache.ftpserver.impl.FtpServerContext;
* @author <a href="http://mina.apache.org">Apache MINA Project</a>
*/
public interface Command {
-
/**
* Execute command.
*
- * @param session
- * The current {@link FtpIoSession}
- * @param context
- * The current {@link FtpServerContext}
+ * @param session The current {@link FtpIoSession}
+ * @param context The current {@link FtpServerContext}
* @param request The current {@link FtpRequest}
* @throws IOException
* @throws FtpException
*/
- void execute(FtpIoSession session, FtpServerContext context,
- FtpRequest request) throws IOException, FtpException;
-
+ void execute(FtpIoSession session, FtpServerContext context, FtpRequest
request) throws IOException, FtpException;
}
diff --git
a/core/src/main/java/org/apache/ftpserver/command/CommandFactory.java
b/core/src/main/java/org/apache/ftpserver/command/CommandFactory.java
index 5c987b46..d9823fdb 100644
--- a/core/src/main/java/org/apache/ftpserver/command/CommandFactory.java
+++ b/core/src/main/java/org/apache/ftpserver/command/CommandFactory.java
@@ -33,40 +33,4 @@ public interface CommandFactory {
* null if no such command exists.
*/
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);
}
diff --git
a/core/src/main/java/org/apache/ftpserver/command/CommandFactoryFactory.java
b/core/src/main/java/org/apache/ftpserver/command/CommandFactoryFactory.java
index d2149110..3291aaa9 100644
--- a/core/src/main/java/org/apache/ftpserver/command/CommandFactoryFactory.java
+++ b/core/src/main/java/org/apache/ftpserver/command/CommandFactoryFactory.java
@@ -86,62 +86,82 @@ public class CommandFactoryFactory {
static {
// first populate the default command list
- DEFAULT_COMMAND_MAP.put("ABOR", new ABOR());
- DEFAULT_COMMAND_MAP.put("ACCT", new ACCT());
- DEFAULT_COMMAND_MAP.put("APPE", new APPE());
- DEFAULT_COMMAND_MAP.put("AUTH", new AUTH());
- DEFAULT_COMMAND_MAP.put("CDUP", new CDUP());
- DEFAULT_COMMAND_MAP.put("CWD", new CWD());
- DEFAULT_COMMAND_MAP.put("DELE", new DELE());
- DEFAULT_COMMAND_MAP.put("EPRT", new EPRT());
- DEFAULT_COMMAND_MAP.put("EPSV", new EPSV());
- DEFAULT_COMMAND_MAP.put("FEAT", new FEAT());
- DEFAULT_COMMAND_MAP.put("HELP", new HELP());
- DEFAULT_COMMAND_MAP.put("LANG", new LANG());
- DEFAULT_COMMAND_MAP.put("LIST", new LIST());
- DEFAULT_COMMAND_MAP.put(MD5.MD5, new MD5());
- DEFAULT_COMMAND_MAP.put("MFMT", new MFMT());
- DEFAULT_COMMAND_MAP.put(MD5.MMD5, new MD5());
- DEFAULT_COMMAND_MAP.put("MDTM", new MDTM());
- DEFAULT_COMMAND_MAP.put("MLST", new MLST());
- DEFAULT_COMMAND_MAP.put("MKD", new MKD());
- DEFAULT_COMMAND_MAP.put("MLSD", new MLSD());
- DEFAULT_COMMAND_MAP.put("MODE", new MODE());
- DEFAULT_COMMAND_MAP.put("NLST", new NLST());
- DEFAULT_COMMAND_MAP.put("NOOP", new NOOP());
- DEFAULT_COMMAND_MAP.put("OPTS", new OPTS());
- DEFAULT_COMMAND_MAP.put("PASS", new PASS());
- DEFAULT_COMMAND_MAP.put("PASV", new PASV());
- DEFAULT_COMMAND_MAP.put("PBSZ", new PBSZ());
- DEFAULT_COMMAND_MAP.put("PORT", new PORT());
- DEFAULT_COMMAND_MAP.put("PROT", new PROT());
- DEFAULT_COMMAND_MAP.put("PWD", new PWD());
- DEFAULT_COMMAND_MAP.put("QUIT", new QUIT());
- DEFAULT_COMMAND_MAP.put("REIN", new REIN());
- DEFAULT_COMMAND_MAP.put("REST", new REST());
- DEFAULT_COMMAND_MAP.put("RETR", new RETR());
- DEFAULT_COMMAND_MAP.put("RMD", new RMD());
- DEFAULT_COMMAND_MAP.put("RNFR", new RNFR());
- DEFAULT_COMMAND_MAP.put("RNTO", new RNTO());
- DEFAULT_COMMAND_MAP.put("SITE", new SITE());
- DEFAULT_COMMAND_MAP.put("SIZE", new SIZE());
- DEFAULT_COMMAND_MAP.put("SITE_DESCUSER", new SITE_DESCUSER());
- DEFAULT_COMMAND_MAP.put("SITE_HELP", new SITE_HELP());
- DEFAULT_COMMAND_MAP.put("SITE_STAT", new SITE_STAT());
- DEFAULT_COMMAND_MAP.put("SITE_WHO", new SITE_WHO());
- DEFAULT_COMMAND_MAP.put("SITE_ZONE", new SITE_ZONE());
-
- DEFAULT_COMMAND_MAP.put("STAT", new STAT());
- DEFAULT_COMMAND_MAP.put("STOR", new STOR());
- DEFAULT_COMMAND_MAP.put("STOU", new STOU());
- DEFAULT_COMMAND_MAP.put("STRU", new STRU());
- DEFAULT_COMMAND_MAP.put("SYST", new SYST());
- DEFAULT_COMMAND_MAP.put("TYPE", new TYPE());
- DEFAULT_COMMAND_MAP.put("USER", new USER());
+ DEFAULT_COMMAND_MAP.put("ABOR", new ABOR()); //
rfc959, 4.1.3
+ DEFAULT_COMMAND_MAP.put("ACCT", new ACCT()); //
rfc959, 4.1.1
+ // ADAT, rfc2228, 3?
+ // ALLO, rfc959?
+ DEFAULT_COMMAND_MAP.put("APPE", new APPE()); //
rfc959, 4.1.3
+ DEFAULT_COMMAND_MAP.put("AUTH", new AUTH()); //
rfc2228, 3
+ //AVBL, draft-peterson-streamlined-ftp-command-extensions?
+ // CCC, rfc2228, 3?
+ DEFAULT_COMMAND_MAP.put("CDUP", new CDUP()); //
rfc959, 4.1.1
+ // CONF, rfc2228, 3?
+ // CSID, draft-peterson-streamlined-ftp-command-extensions?
+ DEFAULT_COMMAND_MAP.put("CWD", new CWD()); //
rfc959, 4.1.1
+ DEFAULT_COMMAND_MAP.put("DELE", new DELE()); //
rfc959, 4.1.3
+ // DSIZ, draft-peterson-streamlined-ftp-command-extensions?
+ // ENC, rfc2228, 3?
+ DEFAULT_COMMAND_MAP.put("EPRT", new EPRT()); //
rfc2428, 2
+ DEFAULT_COMMAND_MAP.put("EPSV", new EPSV()); //
rfc2428, 3
+ DEFAULT_COMMAND_MAP.put("FEAT", new FEAT()); //
rfc2389, 3
+ DEFAULT_COMMAND_MAP.put("HELP", new HELP()); //
rfc959, 4.1.3
+ // HOST, rfc7151?
+ DEFAULT_COMMAND_MAP.put("LANG", new LANG()); //
rfc2640, 4.1
+ DEFAULT_COMMAND_MAP.put("LIST", new LIST()); //
rfc959, 4.1.3
+ // LPRT, rfc1639 2?
+ // LPSV, rfc1639 2?
+ DEFAULT_COMMAND_MAP.put(MD5.MD5, new MD5()); //
draft-twine-ftpmd5-00.txt, 3.1
+ // MIC, rfc2228, 3?
+ DEFAULT_COMMAND_MAP.put(MD5.MMD5, new MD5()); //
draft-twine-ftpmd5-00.txt , 3.2
+ DEFAULT_COMMAND_MAP.put("MDTM", new MDTM()); //
rfc3659, 3
+ // "MFCT, draft-somers-ftp-mfxx, 4
+ // "MFF, draft-somers-ftp-mfxx, 5
+ DEFAULT_COMMAND_MAP.put("MFMT", new MFMT()); //
draft-somers-ftp-mfxx, 3
+ DEFAULT_COMMAND_MAP.put("MKD", new MKD()); //
rfc959, 4.1.3
+ DEFAULT_COMMAND_MAP.put("MLSD", new MLSD()); //
rfc3659, 7
+ DEFAULT_COMMAND_MAP.put("MLST", new MLST()); //
rfc3659, 7
+ DEFAULT_COMMAND_MAP.put("MODE", new MODE()); //
rfc959, 4.1.2
+ DEFAULT_COMMAND_MAP.put("NLST", new NLST()); //
rfc959, 4.1.3
+ DEFAULT_COMMAND_MAP.put("NOOP", new NOOP()); //
rfc959, 4.1.3
+ DEFAULT_COMMAND_MAP.put("OPTS", new OPTS()); //
rfc2389, 4
+ DEFAULT_COMMAND_MAP.put("PASS", new PASS()); //
rfc959, 4.1.1
+ DEFAULT_COMMAND_MAP.put("PASV", new PASV()); //
rfc959, 4.1.2
+ DEFAULT_COMMAND_MAP.put("PBSZ", new PBSZ()); //
rfc2228, 3
+ DEFAULT_COMMAND_MAP.put("PORT", new PORT()); //
rfc959, 4.1.2
+ DEFAULT_COMMAND_MAP.put("PROT", new PROT()); //
rfc2228, 3
+ DEFAULT_COMMAND_MAP.put("PWD", new PWD()); //
rfc959, 4.1.3
+ DEFAULT_COMMAND_MAP.put("QUIT", new QUIT()); //
rfc959, 4.1.1
+ DEFAULT_COMMAND_MAP.put("REIN", new REIN()); //
rfc959, 4.1.1
+ DEFAULT_COMMAND_MAP.put("REST", new REST()); //
rfc959, 4.1.3, rfc3659, 5
+ DEFAULT_COMMAND_MAP.put("RETR", new RETR()); //
rfc959, 4.1.3
+ DEFAULT_COMMAND_MAP.put("RMD", new RMD()); //
rfc959, 4.1.3
+ // RMDA, draft-peterson-streamlined-ftp-command-extensions?
+ DEFAULT_COMMAND_MAP.put("RNFR", new RNFR()); //
rfc959, 4.1.3
+ DEFAULT_COMMAND_MAP.put("RNTO", new RNTO()); //
rfc959, 4.1.3
+ DEFAULT_COMMAND_MAP.put("SITE", new SITE()); //
rfc959, 4.1.3
+ DEFAULT_COMMAND_MAP.put("SITE_DESCUSER", new SITE_DESCUSER()); //
rfc959, 4.1.3
+ DEFAULT_COMMAND_MAP.put("SITE_HELP", new SITE_HELP()); //
rfc959, 4.1.3
+ DEFAULT_COMMAND_MAP.put("SITE_STAT", new SITE_STAT()); //
rfc959, 4.1.3
+ DEFAULT_COMMAND_MAP.put("SITE_WHO", new SITE_WHO()); //
rfc959, 4.1.3
+ DEFAULT_COMMAND_MAP.put("SITE_ZONE", new SITE_ZONE()); //
rfc959, 4.1.3
+ DEFAULT_COMMAND_MAP.put("SIZE", new SIZE()); //
rfc3659, 4
+ // SMNT, rfc959?
+ // SPSV, draft-rosenau-ftp-single-port
+ DEFAULT_COMMAND_MAP.put("STAT", new STAT()); //
rfc959, 4.1.3
+ DEFAULT_COMMAND_MAP.put("STOR", new STOR()); //
rfc959, 4.1.3
+ DEFAULT_COMMAND_MAP.put("STOU", new STOU()); //
rfc959, 4.1.3
+ DEFAULT_COMMAND_MAP.put("STRU", new STRU()); //
rfc959, 4.1.2
+ DEFAULT_COMMAND_MAP.put("SYST", new SYST()); //
rfc959, 4.1.3
+ // THMB, draft-peterson-streamlined-ftp-command-extensions
+ DEFAULT_COMMAND_MAP.put("TYPE", new TYPE()); //
rfc959, 4.1.2
+ // TVFS, rfc3659, 6?
+ DEFAULT_COMMAND_MAP.put("USER", new USER()); //
rfc959, 4.1.1
}
+ /** The commands map */
private Map<String, Command> commandMap = new HashMap<String, Command>();
+ /** A flag indicating of we have non-default commands */
private boolean useDefaultCommands = true;
/**
@@ -151,7 +171,8 @@ public class CommandFactoryFactory {
public CommandFactory createCommandFactory() {
Map<String, Command> mergedCommands = new HashMap<String, Command>();
- if(useDefaultCommands) {
+
+ if (useDefaultCommands) {
mergedCommands.putAll(DEFAULT_COMMAND_MAP);
}
@@ -172,8 +193,7 @@ public class CommandFactoryFactory {
/**
* Sets whether the default commands will be used.
*
- * @param useDefaultCommands
- * true if default commands should be used
+ * @param useDefaultCommands <code>true</code> if default commands should
be used
*/
public void setUseDefaultCommands(final boolean useDefaultCommands) {
this.useDefaultCommands = useDefaultCommands;
@@ -194,10 +214,11 @@ public class CommandFactoryFactory {
* @param command The command
*/
public void addCommand(String commandName, Command command) {
- if(commandName == null) {
+ if (commandName == null) {
throw new NullPointerException("commandName can not be null");
}
- if(command == null) {
+
+ if (command == null) {
throw new NullPointerException("command can not be null");
}
@@ -207,8 +228,7 @@ public class CommandFactoryFactory {
/**
* Set commands to add or override to the default commands
*
- * @param commandMap
- * The map of commands, the key will be used to map to requests.
+ * @param commandMap The map of commands, the key will be used to map to
requests.
*/
public void setCommandMap(final Map<String, Command> commandMap) {
if (commandMap == null) {
diff --git
a/core/src/main/java/org/apache/ftpserver/command/impl/DefaultCommandFactory.java
b/core/src/main/java/org/apache/ftpserver/command/impl/DefaultCommandFactory.java
index 8b0fd476..24bad29e 100644
---
a/core/src/main/java/org/apache/ftpserver/command/impl/DefaultCommandFactory.java
+++
b/core/src/main/java/org/apache/ftpserver/command/impl/DefaultCommandFactory.java
@@ -37,7 +37,10 @@ import org.apache.ftpserver.command.CommandFactoryFactory;
* @author <a href="http://mina.apache.org">Apache MINA Project</a>
*/
public class DefaultCommandFactory implements CommandFactory {
+ /** The list of supported commands */
+ private final Map<String, Command> commandMap;
+ /** Internal constructor, use {@link CommandFactoryFactory} instead */
public DefaultCommandFactory() {
this(new HashMap<String, Command>());
}
@@ -49,16 +52,16 @@ public class DefaultCommandFactory implements
CommandFactory {
this.commandMap = commandMap;
}
- private final Map<String, Command> commandMap;
/**
- * Get command. Returns null if not found.
+ * {@inheritDoc}
*/
+ @Override
public Command getCommand(final String cmdName) {
- if (cmdName == null || cmdName.equals("")) {
+ if (cmdName == null || (cmdName.length() == 0)) {
return null;
}
- String upperCaseCmdName = cmdName.toUpperCase();
- return commandMap.get(upperCaseCmdName);
+
+ return commandMap.get(cmdName.toUpperCase());
}
}
diff --git a/core/src/main/java/org/apache/ftpserver/command/impl/HELP.java
b/core/src/main/java/org/apache/ftpserver/command/impl/HELP.java
index f5607908..885c186b 100644
--- a/core/src/main/java/org/apache/ftpserver/command/impl/HELP.java
+++ b/core/src/main/java/org/apache/ftpserver/command/impl/HELP.java
@@ -32,17 +32,18 @@ import org.apache.ftpserver.message.MessageResource;
/**
* <strong>Internal class, do not use directly.</strong>
*
- * <code>HELP [<SP> <string>] <CRLF></code><br>
+ * <code>HELP [<SP> <string>] <CRLF></code><br>
*
* This command shall cause the server to send helpful information regarding
its
* implementation status over the control connection to the user. The command
* may take an argument (e.g., any command name) and return more specific
* information as a response.
+ * <br>
+ * Defined in RFC 959
*
* @author <a href="http://mina.apache.org">Apache MINA Project</a>
*/
public class HELP extends AbstractCommand {
-
/**
* Execute command.
*/
@@ -63,10 +64,11 @@ public class HELP extends AbstractCommand {
// print command specific help if available
String ftpCmd = request.getArgument().toUpperCase();
MessageResource resource = context.getMessageResource();
- if (resource.getMessage(FtpReply.REPLY_214_HELP_MESSAGE, ftpCmd,
- session.getLanguage()) == null) {
+
+ if (resource.getMessage(FtpReply.REPLY_214_HELP_MESSAGE, ftpCmd,
session.getLanguage()) == null) {
ftpCmd = null;
}
+
session.write(LocalizedFtpReply.translate(session, request, context,
FtpReply.REPLY_214_HELP_MESSAGE, ftpCmd, null));
}
diff --git
a/core/src/main/java/org/apache/ftpserver/impl/DefaultFtpRequest.java
b/core/src/main/java/org/apache/ftpserver/impl/DefaultFtpRequest.java
index 6f8f9192..c75d7055 100644
--- a/core/src/main/java/org/apache/ftpserver/impl/DefaultFtpRequest.java
+++ b/core/src/main/java/org/apache/ftpserver/impl/DefaultFtpRequest.java
@@ -29,20 +29,22 @@ import org.apache.ftpserver.ftplet.FtpRequest;
* @author <a href="http://mina.apache.org">Apache MINA Project</a>
*/
public class DefaultFtpRequest implements FtpRequest {
-
+ /** The request line */
private final String line;
+ /** The FTP command */
private final String command;
+ /** The FTP argument */
private final String argument;
- /**
- * timestamp when this request was received
- */
+ /** timestamp when this request was received */
private final long receivedTime;
/**
* Default constructor.
+ *
+ * @param requestLine The request line
*/
public DefaultFtpRequest(final String requestLine) {
//Assuming we create the request as soon as we receive the command
from
@@ -50,7 +52,7 @@ public class DefaultFtpRequest implements FtpRequest {
//bunch of things after we receive the command from the client and
//before constructing this FtpRequest object, then this method is not
//going to be accurate and need to look for an alternative solution.
- this.receivedTime = System.currentTimeMillis();
+ receivedTime = System.currentTimeMillis();
line = requestLine.trim();
int spInd = line.indexOf(' ');
command = parseCmd(line, spInd);
@@ -62,14 +64,17 @@ public class DefaultFtpRequest implements FtpRequest {
*/
private String parseCmd(final String lineToParse, int spInd) {
String cmd = null;
+
if (spInd != -1) {
cmd = line.substring(0, spInd).toUpperCase();
} else {
cmd = line.toUpperCase();
}
+
if ((cmd.length() > 0) && (cmd.charAt(0) == 'X')) {
cmd = cmd.substring(1);
}
+
return cmd;
}
@@ -77,10 +82,12 @@ public class DefaultFtpRequest implements FtpRequest {
String arg = null;
if (spInd != -1) {
arg = line.substring(spInd + 1);
+
if (arg.equals("")) {
arg = null;
}
}
+
return arg;
}
@@ -109,7 +116,7 @@ public class DefaultFtpRequest implements FtpRequest {
* Has argument.
*/
public boolean hasArgument() {
- return getArgument() != null;
+ return argument != null;
}
public long getReceivedTime() {
@@ -123,6 +130,6 @@ public class DefaultFtpRequest implements FtpRequest {
*/
@Override
public String toString() {
- return getRequestLine();
+ return line;
}
}
diff --git a/core/src/main/java/org/apache/ftpserver/impl/DefaultFtpServer.java
b/core/src/main/java/org/apache/ftpserver/impl/DefaultFtpServer.java
index 680bd19a..d6197c7b 100644
--- a/core/src/main/java/org/apache/ftpserver/impl/DefaultFtpServer.java
+++ b/core/src/main/java/org/apache/ftpserver/impl/DefaultFtpServer.java
@@ -76,6 +76,7 @@ public class DefaultFtpServer implements FtpServer {
try {
Map<String, Listener> listeners = serverContext.getListeners();
+
for (Listener listener : listeners.values()) {
listener.start(serverContext);
startedListeners.add(listener);
diff --git
a/core/src/main/java/org/apache/ftpserver/impl/DefaultFtpServerContext.java
b/core/src/main/java/org/apache/ftpserver/impl/DefaultFtpServerContext.java
index 731b0f58..c9ee1270 100644
--- a/core/src/main/java/org/apache/ftpserver/impl/DefaultFtpServerContext.java
+++ b/core/src/main/java/org/apache/ftpserver/impl/DefaultFtpServerContext.java
@@ -63,6 +63,7 @@ public class DefaultFtpServerContext implements
FtpServerContext {
private final Logger LOG = LoggerFactory
.getLogger(DefaultFtpServerContext.class);
+ /** The FTP messages per language */
private MessageResource messageResource = new
MessageResourceFactory().createMessageResource();
private UserManager userManager = new
PropertiesUserManagerFactory().createUserManager();
@@ -101,7 +102,11 @@ public class DefaultFtpServerContext implements
FtpServerContext {
}
/**
- * Create default users.
+ * Create default users:
+ * <ul>
+ * <li>Admin</li>
+ * <li>Anonymous</ul>
+ * </ul>
*/
public void createDefaultUsers() throws Exception {
UserManager userManager = getUserManager();
diff --git
a/core/src/main/java/org/apache/ftpserver/impl/FtpReplyTranslator.java
b/core/src/main/java/org/apache/ftpserver/impl/FtpReplyTranslator.java
index dc53f5d1..cd63f3f7 100644
--- a/core/src/main/java/org/apache/ftpserver/impl/FtpReplyTranslator.java
+++ b/core/src/main/java/org/apache/ftpserver/impl/FtpReplyTranslator.java
@@ -113,19 +113,21 @@ public class FtpReplyTranslator {
* the basic message
* @return the translated message
*/
- public static String translateMessage(FtpIoSession session,
- FtpRequest request, FtpServerContext context, int code, String subId,
- String basicMsg) {
+ public static String translateMessage(FtpIoSession session, FtpRequest
request, FtpServerContext context,
+ int code, String subId, String basicMsg) {
MessageResource resource = context.getMessageResource();
String lang = session.getLanguage();
String msg = null;
+
if (resource != null) {
msg = resource.getMessage(code, subId, lang);
}
+
if (msg == null) {
msg = "";
}
+
msg = replaceVariables(session, request, context, code, basicMsg, msg);
return msg;
diff --git
a/core/src/main/java/org/apache/ftpserver/message/MessageResourceFactory.java
b/core/src/main/java/org/apache/ftpserver/message/MessageResourceFactory.java
index a55c7d3b..66fb1044 100644
---
a/core/src/main/java/org/apache/ftpserver/message/MessageResourceFactory.java
+++
b/core/src/main/java/org/apache/ftpserver/message/MessageResourceFactory.java
@@ -30,9 +30,10 @@ import
org.apache.ftpserver.message.impl.DefaultMessageResource;
* @author <a href="http://mina.apache.org">Apache MINA Project</a>
*/
public class MessageResourceFactory {
-
+ /** The supported languages */
private List<String> languages;
+ /** The directory where the message are stored */
private File customMessageDirectory;
/**
diff --git
a/core/src/main/java/org/apache/ftpserver/message/impl/DefaultMessageResource.java
b/core/src/main/java/org/apache/ftpserver/message/impl/DefaultMessageResource.java
index 67caaf4b..c473b248 100644
---
a/core/src/main/java/org/apache/ftpserver/message/impl/DefaultMessageResource.java
+++
b/core/src/main/java/org/apache/ftpserver/message/impl/DefaultMessageResource.java
@@ -21,11 +21,9 @@ package org.apache.ftpserver.message.impl;
import java.io.File;
import java.io.FileInputStream;
-import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
@@ -33,40 +31,41 @@ import java.util.Properties;
import org.apache.ftpserver.FtpServerConfigurationException;
import org.apache.ftpserver.message.MessageResource;
import org.apache.ftpserver.message.MessageResourceFactory;
-import org.apache.ftpserver.util.IoUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* <strong>Internal class, do not use directly.</strong>
- *
- * Class to get FtpServer reply messages. This supports i18n. Basic message
- * search path is:
- *
- * <strong><strong>Internal class, do not use directly.</strong></strong>
+ * <br>
+ * Class to get FtpServer reply messages. This supports i18n.
+ * <br>
+ * Basic message search path is:
*
* Custom Language Specific Messages -> Default Language Specific Messages ->
* Custom Common Messages -> Default Common Messages -> null (not found)
+ * <br>
+ * <strong>Internal class, do not use directly.</strong>
*
* @author <a href="http://mina.apache.org">Apache MINA Project</a>
*/
public class DefaultMessageResource implements MessageResource {
+ /** A logger for this class */
+ private final Logger LOG =
LoggerFactory.getLogger(DefaultMessageResource.class);
- private final Logger LOG = LoggerFactory
- .getLogger(DefaultMessageResource.class);
-
+ /** The default path for the message root */
private final static String RESOURCE_PATH =
"org/apache/ftpserver/message/";
+ /** The requested languages. Default to none, ie EN */
private final List<String> languages;
+ /** The <language, properties> list of messages */
private final Map<String, PropertiesPair> messages;
/**
* Internal constructor, do not use directly. Use {@link
MessageResourceFactory} instead.
*/
- public DefaultMessageResource(List<String> languages,
- File customMessageDirectory) {
- if(languages != null) {
+ public DefaultMessageResource(List<String> languages, File
customMessageDirectory) {
+ if (languages != null) {
this.languages = Collections.unmodifiableList(languages);
} else {
this.languages = null;
@@ -74,77 +73,76 @@ public class DefaultMessageResource implements
MessageResource {
// populate different properties
messages = new HashMap<String, PropertiesPair>();
+
if (languages != null) {
for (String language : languages) {
PropertiesPair pair = createPropertiesPair(language,
customMessageDirectory);
messages.put(language, pair);
}
}
+
+ // The default property pair
PropertiesPair pair = createPropertiesPair(null,
customMessageDirectory);
messages.put(null, pair);
}
+ /**
+ * Define a pair of default and custom properties.
+ *
+ * @author <a href="mailto:[email protected]">Apache Directory
Project</a>
+ */
private static class PropertiesPair {
+ /** The default properties */
public Properties defaultProperties = new Properties();
+ /** The custom properties */
public Properties customProperties = new Properties();
}
/**
* Create Properties pair object. It stores the default and the custom
* messages.
+ * The default file to read will be stored in
<em>org/apache/ftpserver/message/FtpStatus.properties</em>
+ * or <em>org/apache/ftpserver/message/FtpStatus_<lang>.properties</em> if
a language is provided.
+ * The custom file to read will be stored in
<em>org/apache/ftpserver/message/FtpStatus.gen</em>
+ * or <em>org/apache/ftpserver/message/FtpStatus_<lang>.gen</em> if a
language is provided.
*/
private PropertiesPair createPropertiesPair(String lang, File
customMessageDirectory) {
PropertiesPair pair = new PropertiesPair();
// load default resource
String defaultResourceName;
+
if (lang == null) {
defaultResourceName = RESOURCE_PATH + "FtpStatus.properties";
} else {
- defaultResourceName = RESOURCE_PATH + "FtpStatus_" + lang
- + ".properties";
+ defaultResourceName = RESOURCE_PATH + "FtpStatus_" + lang +
".properties";
}
- InputStream in = null;
- try {
- in = getClass().getClassLoader().getResourceAsStream(
- defaultResourceName);
- if (in != null) {
- try {
- pair.defaultProperties.load(in);
- } catch (IOException e) {
- throw new FtpServerConfigurationException(
- "Failed to load messages from \"" +
defaultResourceName + "\", file not found in classpath");
- }
- } else {
- throw new FtpServerConfigurationException(
- "Failed to load messages from \"" +
defaultResourceName + "\", file not found in classpath");
- }
- } finally {
- IoUtils.close(in);
+
+ try (InputStream in =
getClass().getClassLoader().getResourceAsStream(defaultResourceName)) {
+ pair.defaultProperties.load(in);
+ } catch (Exception ex){
+ throw new FtpServerConfigurationException(
+ "Failed to load messages from \"" + defaultResourceName + "\",
file not found in classpath");
}
// load custom resource
File resourceFile = null;
+
if (lang == null) {
resourceFile = new File(customMessageDirectory, "FtpStatus.gen");
} else {
- resourceFile = new File(customMessageDirectory, "FtpStatus_" + lang
- + ".gen");
+ resourceFile = new File(customMessageDirectory, "FtpStatus_" +
lang + ".gen");
}
- in = null;
- try {
- if (resourceFile.exists()) {
- in = new FileInputStream(resourceFile);
+
+ if (resourceFile.exists()) {
+ try (InputStream in = new FileInputStream(resourceFile)) {
pair.customProperties.load(in);
+ } catch (Exception ex) {
+ LOG.warn("MessageResourceImpl.createPropertiesPair()", ex);
+ throw new
FtpServerConfigurationException("MessageResourceImpl.createPropertiesPair()",
ex);
}
- } catch (Exception ex) {
- LOG.warn("MessageResourceImpl.createPropertiesPair()", ex);
- throw new FtpServerConfigurationException(
- "MessageResourceImpl.createPropertiesPair()", ex);
- } finally {
- IoUtils.close(in);
}
return pair;
@@ -152,6 +150,8 @@ public class DefaultMessageResource implements
MessageResource {
/**
* Get all the available languages.
+ *
+ * @return The list of available languages
*/
public List<String> getAvailableLanguages() {
if (languages == null) {
@@ -163,22 +163,32 @@ public class DefaultMessageResource implements
MessageResource {
/**
* Get the message. If the message not found, it will return null.
+ *
+ * @param code The FTP code for which we want the message
+ * @param subId The FTP command for this code
+ * @param language The language to use
+ * @return The message for this code and command
*/
public String getMessage(int code, String subId, String language) {
// find the message key
String key = String.valueOf(code);
+
if (subId != null) {
key = key + '.' + subId;
}
// get language specific value
String value = null;
+
PropertiesPair pair = null;
+
if (language != null) {
language = language.toLowerCase();
pair = messages.get(language);
+
if (pair != null) {
value = pair.customProperties.getProperty(key);
+
if (value == null) {
value = pair.defaultProperties.getProperty(key);
}
@@ -188,8 +198,10 @@ public class DefaultMessageResource implements
MessageResource {
// if not available get the default value
if (value == null) {
pair = messages.get(null);
+
if (pair != null) {
value = pair.customProperties.getProperty(key);
+
if (value == null) {
value = pair.defaultProperties.getProperty(key);
}
@@ -200,7 +212,10 @@ public class DefaultMessageResource implements
MessageResource {
}
/**
- * Get all messages.
+ * Get all messages for a specific language.
+ *
+ * @param language The language we are interested in. If
<code>null</code>, we will use the default properties.
+ * @return The resulting messages
*/
public Map<String, String> getMessages(String language) {
Properties messages = new Properties();
@@ -208,13 +223,16 @@ public class DefaultMessageResource implements
MessageResource {
// load properties sequentially
// (default,custom,default language,custom language)
PropertiesPair pair = this.messages.get(null);
+
if (pair != null) {
messages.putAll(pair.defaultProperties);
messages.putAll(pair.customProperties);
}
+
if (language != null) {
language = language.toLowerCase();
pair = this.messages.get(language);
+
if (pair != null) {
messages.putAll(pair.defaultProperties);
messages.putAll(pair.customProperties);
@@ -222,6 +240,7 @@ public class DefaultMessageResource implements
MessageResource {
}
Map<String, String> result = new HashMap<String, String>();
+
for(Object key : messages.keySet()) {
result.put(key.toString(), messages.getProperty(key.toString()));
}
@@ -233,13 +252,13 @@ public class DefaultMessageResource implements
MessageResource {
* Dispose component - clear all maps.
*/
public void dispose() {
- Iterator<String> it = messages.keySet().iterator();
- while (it.hasNext()) {
- String language = it.next();
+
+ for (String language : messages.keySet()) {
PropertiesPair pair = messages.get(language);
pair.customProperties.clear();
pair.defaultProperties.clear();
}
+
messages.clear();
}
}
diff --git
a/core/src/main/java/org/apache/ftpserver/usermanager/DbUserManagerFactory.java
b/core/src/main/java/org/apache/ftpserver/usermanager/DbUserManagerFactory.java
index e64823d1..ff068d24 100644
---
a/core/src/main/java/org/apache/ftpserver/usermanager/DbUserManagerFactory.java
+++
b/core/src/main/java/org/apache/ftpserver/usermanager/DbUserManagerFactory.java
@@ -57,30 +57,37 @@ public class DbUserManagerFactory implements
UserManagerFactory {
throw new FtpServerConfigurationException(
"Required data source not provided");
}
+
if (insertUserStmt == null) {
throw new FtpServerConfigurationException(
"Required insert user SQL statement not provided");
}
+
if (updateUserStmt == null) {
throw new FtpServerConfigurationException(
"Required update user SQL statement not provided");
}
+
if (deleteUserStmt == null) {
throw new FtpServerConfigurationException(
"Required delete user SQL statement not provided");
}
+
if (selectUserStmt == null) {
throw new FtpServerConfigurationException(
"Required select user SQL statement not provided");
}
+
if (selectAllStmt == null) {
throw new FtpServerConfigurationException(
"Required select all users SQL statement not provided");
}
+
if (isAdminStmt == null) {
throw new FtpServerConfigurationException(
"Required is admin user SQL statement not provided");
}
+
if (authenticateStmt == null) {
throw new FtpServerConfigurationException(
"Required authenticate user SQL statement not provided");
diff --git
a/core/src/main/java/org/apache/ftpserver/usermanager/PropertiesUserManagerFactory.java
b/core/src/main/java/org/apache/ftpserver/usermanager/PropertiesUserManagerFactory.java
index b3ddc7e6..985efa7e 100644
---
a/core/src/main/java/org/apache/ftpserver/usermanager/PropertiesUserManagerFactory.java
+++
b/core/src/main/java/org/apache/ftpserver/usermanager/PropertiesUserManagerFactory.java
@@ -31,13 +31,14 @@ import
org.apache.ftpserver.usermanager.impl.PropertiesUserManager;
* @author <a href="http://mina.apache.org">Apache MINA Project</a>
*/
public class PropertiesUserManagerFactory implements UserManagerFactory {
-
+ /** The default admin name */
private String adminName = "admin";
private File userDataFile;
private URL userDataURL;
+ /** The default password encryption method*/
private PasswordEncryptor passwordEncryptor = new Md5PasswordEncryptor();
/**
@@ -45,17 +46,15 @@ public class PropertiesUserManagerFactory implements
UserManagerFactory {
*/
public UserManager createUserManager() {
if (userDataURL != null) {
- return new PropertiesUserManager(passwordEncryptor, userDataURL,
- adminName);
+ return new PropertiesUserManager(passwordEncryptor, userDataURL,
adminName);
} else {
-
- return new PropertiesUserManager(passwordEncryptor, userDataFile,
- adminName);
+ return new PropertiesUserManager(passwordEncryptor, userDataFile,
adminName);
}
}
/**
* Get the admin name.
+ *
* @return The admin user name
*/
public String getAdminName() {
@@ -66,8 +65,7 @@ public class PropertiesUserManagerFactory implements
UserManagerFactory {
* Set the name to use as the administrator of the server. The default
value
* is "admin".
*
- * @param adminName
- * The administrator user name
+ * @param adminName The administrator user name
*/
public void setAdminName(String adminName) {
this.adminName = adminName;
diff --git
a/core/src/main/java/org/apache/ftpserver/usermanager/impl/PropertiesUserManager.java
b/core/src/main/java/org/apache/ftpserver/usermanager/impl/PropertiesUserManager.java
index 8faf5f3d..a896019e 100644
---
a/core/src/main/java/org/apache/ftpserver/usermanager/impl/PropertiesUserManager.java
+++
b/core/src/main/java/org/apache/ftpserver/usermanager/impl/PropertiesUserManager.java
@@ -140,8 +140,7 @@ public class PropertiesUserManager extends
AbstractUserManager {
/**
* Internal constructor, do not use directly. Use {@link
PropertiesUserManagerFactory} instead.
*/
- public PropertiesUserManager(PasswordEncryptor passwordEncryptor,
- URL userDataPath, String adminName) {
+ public PropertiesUserManager(PasswordEncryptor passwordEncryptor, URL
userDataPath, String adminName) {
super(adminName, passwordEncryptor);
loadFromUrl(userDataPath);
diff --git a/core/src/main/java/org/apache/ftpserver/util/PasswordUtil.java
b/core/src/main/java/org/apache/ftpserver/util/PasswordUtil.java
index cf65046e..198e8fda 100644
--- a/core/src/main/java/org/apache/ftpserver/util/PasswordUtil.java
+++ b/core/src/main/java/org/apache/ftpserver/util/PasswordUtil.java
@@ -24,16 +24,11 @@ public class PasswordUtil {
* Securely compares two strings up to a maximum number of characters in a
way
* that obscures the password length from timing attacks
*
- * @param input
- * user input
- * @param password
- * correct password
- * @param loops
- * number of characters to compare; must be larger than password
- * length; 1024 is a good number
+ * @param input user input
+ * @param password correct password
+ * @param loops number of characters to compare; must be larger than
password length; 1024 is a good number
*
- * @throws IllegalArgumentException
- * when the limit is less than the password length
+ * @throws IllegalArgumentException when the limit is less than the
password length
*
* @return true if the passwords match
*/
@@ -41,11 +36,13 @@ public class PasswordUtil {
if (loops < password.length()) {
throw new IllegalArgumentException("loops must be equal or greater
than the password length");
}
+
/*
* Set the default result based on the string lengths; if the lengths
do not
* match then we know that this comparison should always fail.
*/
int result = (input.length() ^ password.length());
+
/*
* Cycle through all of the characters up to the limit value
*
@@ -66,12 +63,9 @@ public class PasswordUtil {
* Securely compares two strings forcing the number of loops equal to
password length
* thereby obscuring the password length based on user input
*
- * @param input
- * user input
- * @param password
- * correct password
- * @throws IllegalArgumentException
- * when the limit is less than the password length
+ * @param input user input
+ * @param password correct password
+ * @throws IllegalArgumentException when the limit is less than the
password length
*
* @return true if the passwords match
*/
@@ -80,11 +74,13 @@ public class PasswordUtil {
* the number of compare loops
*/
int loops = password.length();
+
/*
* Set the default result based on the string lengths; if the lengths
do not
* match then we know that this comparison should always fail.
*/
int result = (input.length() ^ password.length());
+
/*
* Cycle through all of the characters up to the limit value
*