Greetings everyone, today I will show you how to add your custom
command to the Akka-FTP server. You will need a decent IDE, preferably
IntelliJ, and the knowledge of
Scala. The example for this chapter available
here and compile against Akka-FTP tag
1.0. Let's get started!
Components wiring
FTP state is the central piece which every other component has access to. It provides the
command factory dependency which in turn creates a
command.
FTP command
First stop in our journey will be a command implementation. Something dead simple:
X-TIME command that replies with the server current time. Optional parameter specifies the date format.
case class XTimeCommand(param: String, session: Session) extends Command {
override def exec: Reply = {
val sdf = new SimpleDateFormat(
if (param.isEmpty) "dd/MM/yyyy HH:mm:ss" else param)
val date = sdf.format(new Date)
Reply(200, s"Server time $date")
}
}
All commands must extend the
Command trait and take user's
Session as the mandatory argument. The optional argument
param is a text user enters after command's name, e.g.
X-TIME ddMMyyyy where
X-TIME is the command's name and
ddMMyyyy is the parameter. The
exec method returns a
Reply.
Command factory
Now that the command is ready, the
command factory needs to create it as the response to user's
X-TIME input. For that, a new implementation of the factory is needed. It is very easy, just extend the default
command factory as this.
class CustomCommandFactory extends DefaultCommandFactory {
def mycmd(name: String, param: String, session: Session): Option[Command] =
Option(name match {
case "X-TIME" => XTimeCommand(param, session)
case _ => null
})
override def cmd(name: String, param: String, session: Session): Command =
mycmd(name, param, session) getOrElse super.cmd(name, param, session)
}
Our new factory has the
mycmd method which creates a new command if a user sends
X-TIME input to the server. Please note that this method is a copy/paste from the
command factory itself, I did not write anything new. If a command cannot be created then the factory falls back for the default method.
FTP state
The new
command factory needs to be provided by the
FTP state. Extend it!
class CustomFtpState(...) extends FtpState(...) {
override val commandFactory = new CustomCommandFactory
}
The real implementation takes many
parameters, but I did not feel like listing them and the parameters may
change with the release.
The final piece
The
new components are ready and wired, now what? How to tell the server to
use those? The final piece of this puzzle is a launcher which will
start the server with the new
FTP state. Here is the source.
class CustomLauncher extends Launcher {
override def createFtpState(system: ActorSystem): FtpState = {
// omettied code to read settings
new CustomFtpState(...)
}
}
object main {
def main(args: Array[String]) = new CustomLauncher().start()
}
Test the new command
Now it's time to test what we have accomplished, start the server! Type
sbt run and choose the new
main method. Connect to the server with telnet:
telnet localhost 2021
Connected
$ X-TIME
200 Server time 02/12/2015 14:56:25
$ X-TIME yyyyMMdd
200 Server time 20151202
Summary
In this chapter I explained how to extend Akka-FTP
components and start the server with new dependencies. This is the
basics of extending the Akka-FTP and you should follow those steps to
plug-in your own add-ons to the server. Enough for today, thanks for
reading!