JSCAPE Secure FTP Server - Writing Custom Actions
JSCAPE Secure FTP Server has over 35 built-in actions that you may use in triggers for responding to events. These actions may be as simple as renaming a file upon upload or more complex like PGP encrypting a file upon upload and then forwarding it as an attachment to an email recipient. While JSCAPE Secure FTP Server has most of the actions you will ever need, it also allows you to create your own custom actions using the JSCAPE Secure FTP Server Action API. This article will demonstrate how to create your own custom actions using the API and how to use them in the JSCAPE Secure FTP Server Manager application.
For this article our objective will be to create a simple action that performs a search and replace on text within a file using the Action API provided by JSCAPE Secure FTP Server.
We will start by creating a new class named ReplaceTextAction which will be responsible for executing this action. This class will rely on several classes found in the JSCAPE Secure FTP Server Action API. Therefore, in order to compile the new class you must add the data.jar library to your classpath within your IDE. The data.jar library may be found in your JSCAPE Secure FTP Server installation directory.
The functional requirements for the ReplaceTextAction class are that given a search string, replacement string, source file and optional destination file that we perform a search and replace on the source file and store the results in the destination file, overwriting the source file if the optional destination file is not specified. Using these requirements we will begin by adding four private String variables to the ReplaceTextAction class along with getter and setter methods for managing these variables.
In order for JSCAPE Secure FTP Server to recognize this class as a valid action we must have it extend the abstract com.jscape.inet.mft.workflow.AbstractAction class and implement the execute() method which will be invoked when executing this action. The com.jscape.inet.mft.workflow.AbstractAction class is found in the data.jar file that you added to your classpath earlier. Within the execute() method we will add the code for performing the search and replace using the variables defined earlier.
JSCAPE Secure FTP Server uses reflection on action classes to build the GUI screens used in collecting action variable data. This is very useful in that when defining actions you do not have to define separate GUI screens for collecting the data as they are automatically generated using reflection and information found in the action class itself. However, in order for JSCAPE Secure FTP Server to generate these GUI panels automatically there are some rules that you must follow.
- Classes must have an empty constructor. This allows JSCAPE Secure FTP Server to create an instance without having to know what class constructor it should use.
- Exposed class variables must be primitives e.g. String, int, long, boolean etc.
- Exposed class variables must have corresponding getter and setter methods using Java naming conventions. For example, the String variable destinationFile would have getter and setter methods of getDestinationFile and setDestinationFile respectively.
By default all class variable data is obtained using standard text fields in the action GUI panel. While functional, this may not be very user-friendly, especially in cases where you want to validate user input. Fortunately the JSCAPE Secure FTP Server API is very flexible, allowing you to specify what type of input components are used in the GUI panel for each variable. Components such as a choice box, file chooser, password field, text field or true/false radio buttons may be used in your GUI panel by defining property descriptors for each variable. Using these same property descriptors you can also define what variables are required and the order in which the variable input components are listed when displaying the GUI panel.
Below find the full source code used for creating the ReplaceTextAction class.
Download Source
001 package test.com.jscape.action;
002
003 import com.jscape.inet.mft.workflow.AbstractAction;
004
005 import com.jscape.util.reflection.PropertyDescriptor;
006 import com.jscape.util.reflection.types.FileField;
007
008 import java.io.*;
009
010 /**
011 * Example action which performs a text search and replace within a file.
012 */
013 public class ReplaceTextAction extends AbstractAction {
014
015 // description of action
016 private static final String DESCRIPTION = "Performs search and replace of text.";
017
018 // descriptors used to build GUI
019 private static final PropertyDescriptor[] DESCRIPTORS = {
020 new PropertyDescriptor("SourceFile", true, new FileField()),
021 new PropertyDescriptor("DestinationFile", false, new FileField()),
022 new PropertyDescriptor("Search", true),
023 new PropertyDescriptor("Replace", true)
024 };
025
026 // data variables
027 private String search;
028 private String replace;
029 private String sourceFile;
030 private String destinationFile;
031
032 /**
033 * Executes task.
034 * @throws Exception if an error occurs
035 */
036 public void execute() throws Exception {
037 // option source file
038 BufferedInputStream bin = new BufferedInputStream(new FileInputStream(
039 sourceFile));
040
041 // temporary buffer to store converted output
042 ByteArrayOutputStream bout = new ByteArrayOutputStream();
043
044 // read data into buffer
045 int i = 0;
046
047 while ((i = bin.read()) != -1) {
048 bout.write(i);
049 }
050
051 // close input stream
052 bin.close();
053
054 // convert buffer to string and perform search and replace
055 String st = new String(bout.toByteArray());
056 st = st.replaceAll(search, replace);
057
058 // write results to output file
059 FileOutputStream fout = null;
060
061 if ((destinationFile != null) && (destinationFile.length() > 0)) {
062 fout = new FileOutputStream(destinationFile);
063 } else {
064 fout = new FileOutputStream(sourceFile);
065 }
066
067 fout.write(st.getBytes());
068
069 // close output streams
070 bout.close();
071 fout.close();
072 }
073
074 /**
075 * Gets description.
076 * @return description
077 */
078 public String getDescription() {
079 return DESCRIPTION;
080 }
081
082 /**
083 * Gets property descriptors.
084 * @return property descriptors
085 */
086 public PropertyDescriptor[] getPropertyDescriptors() {
087 return DESCRIPTORS;
088 }
089
090 /**
091 * Gets destination file.
092 * @return the destinationFile
093 */
094 public String getDestinationFile() {
095 return destinationFile;
096 }
097
098 /**
099 * Sets destination file.
100 * @param destinationFile the destinationFile to set
101 */
102 public void setDestinationFile(String destinationFile) {
103 this.destinationFile = destinationFile;
104 }
105
106 /**
107 * Gets text to replace.
108 * @return the replace
109 */
110 public String getReplace() {
111 return replace;
112 }
113
114 /**
115 * Sets text to replace.
116 * @param replace the replace to set
117 */
118 public void setReplace(String replace) {
119 this.replace = replace;
120 }
121
122 /**
123 * Gets text to find.
124 * @return the search
125 */
126 public String getSearch() {
127 return search;
128 }
129
130 /**
131 * Sets text to find.
132 * @param search the search to set
133 */
134 public void setSearch(String search) {
135 this.search = search;
136 }
137
138 /**
139 * Gets source file.
140 * @return the sourceFile
141 */
142 public String getSourceFile() {
143 return sourceFile;
144 }
145
146 /**
147 * Sets source file.
148 * @param sourceFile the sourceFile to set
149 */
150 public void setSourceFile(String sourceFile) {
151 this.sourceFile = sourceFile;
152 }
153 }
Lines 3-6. Add necessary import statements.
Line 13. Extend AbstractAction class to identify this class as an action to JSCAPE Secure FTP Server.
Line 16. The description displayed in the Description column when listing this action in the JSCAPE Secure FTP Server Manager.
Lines 19-24. Property descriptors which indicate the order of input fields, whether they are required and what type of GUI component is used. In lines 20-21 a FileField instance is used to indicate that a file browser component should be displayed, allowing the user to select a file.
Lines 27-30. Private variables for holding data.
Lines 36-72. Code to execute when executing this action. This method overrides the abstract execute() method found in the parent AbstractAction class.
Lines 78-152. Getter and setter methods for managing action variables.
In order for the action to be recognized by JSCAPE Secure FTP Server you must first create a JAR file that contains the action and any other associated classes. From a shell prompt and from the directory that contains your compiled class files run the following command.
The result will be a JAR file named replace.jar. Next you must place this JAR file in the lib\actions directory of your JSCAPE Secure FTP Server installation and restart both your JSCAPE Secure FTP Server service and the JSCAPE Secure FTP Server Manager. To verify that the action was successfully installed, go to the Triggers node of your domain using JSCAPE Secure FTP Server Manager and select the Actions tab which displays a list of all actions installed. This action will now be made available for use in any triggers that you create.
Now that you have your action installed it may be used when defining a trigger. Below is a screenshot of the GUI panel that is automatically generated from the ReplaceTextAction class created earlier.
For a comprehensive tutorial on triggers and how to use actions please see the tutorial Managed File Transfer - Business Example.
In this article you learned how you could create custom actions using the JSCAPE Secure FTP Server API and how to use them within triggers. Using JSCAPE Secure FTP Server, the more than 35 built in actions and API for creating your own actions you can easily implement a managed file transfer solution.
To see what else JSCAPE Secure FTP Server has to offer Download JSCAPE Secure FTP Server.
|