/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.commons.net.ftp.parser;

import java.io.File;
import java.text.ParseException;

import org.apache.commons.net.ftp.FTPClientConfig;
import org.apache.commons.net.ftp.FTPFile;

Version:$Id: OS400FTPEntryParser.java 1752660 2016-07-14 13:25:39Z sebb $
Example *FILE/*MEM FTP entries, when the current
working directory is a file of file system QSYS:
------------------------------------------------
$ cwd /qsys.lib/rpgunit.lib/rpgunitc1.file
  250-NAMEFMT set to 1.
  250 "/QSYS.LIB/RPGUNIT.LIB/RPGUNITC1.FILE" is current directory.
$ dir
  227 Entering Passive Mode (10,200,36,33,40,249).
  125 List started.
  QPGMR          135168 22.06.13 13:18:19 *FILE
  QPGMR                                   *MEM       MKCMD.MBR
  QPGMR                                   *MEM       RUCALLTST.MBR
  QPGMR                                   *MEM       RUCMDHLP.MBR
  QPGMR                                   *MEM       RUCRTTST.MBR
  250 List completed.
Example *FILE entry of an OS/400 save file:
---------------------------------------------------
$ cwd /qsys.lib/rpgunit.lib
  250 "/QSYS.LIB/RPGUNIT.LIB" is current library.
$ dir rpgunit.file
  227 Entering Passive Mode (10,200,36,33,188,106).
  125 List started.
  QPGMR        16347136 29.06.13 15:45:09 *FILE      RPGUNIT.SAVF
  250 List completed.
Example *STMF/*DIR FTP entries, when the
current working directory is in file system "root":
---------------------------------------------------
$ cwd /home/raddatz
  250 "/home/raddatz" is current directory.
$ dir test*
  227 Entering Passive Mode (10,200,36,33,200,189).
  125 List started.
  RADDATZ           200 21.05.11 12:31:18 *STMF      TEST_RG_02_CRLF.properties
  RADDATZ           187 08.05.11 12:31:40 *STMF      TEST_RG_02_LF.properties
  RADDATZ           187 08.05.11 12:31:52 *STMF      TEST_RG_02_CR.properties
  RADDATZ          8192 04.07.13 09:04:14 *DIR       testDir1/
  RADDATZ          8192 04.07.13 09:04:17 *DIR       testDir2/
  250 List completed.
Example 1, using ANT to list specific members of a file:
--------------------------------------------------------
     <echo/>
     <echo>Listing members of a file:</echo>
     <ftp action="list"
          server="${ftp.server}"
          userid="${ftp.user}"
          password="${ftp.password}"
          binary="false"
          verbose="true"
          remotedir="/QSYS.LIB/RPGUNIT.LIB/RPGUNITY1.FILE"
          systemTypeKey="OS/400"
          listing="ftp-listing.txt"
          >
         <fileset dir="./i5-downloads-file" casesensitive="false">
             <include name="run*.mbr" />
         </fileset>
     </ftp>
Output:
-------
  [echo] Listing members of a file:
   [ftp] listing files
   [ftp] listing RUN.MBR
   [ftp] listing RUNNER.MBR
   [ftp] listing RUNNERBND.MBR
   [ftp] 3 files listed
Example 2, using ANT to list specific members of all files of a library:
------------------------------------------------------------------------
     <echo/>
     <echo>Listing members of all files of a library:</echo>
     <ftp action="list"
          server="${ftp.server}"
          userid="${ftp.user}"
          password="${ftp.password}"
          binary="false"
          verbose="true"
          remotedir="/QSYS.LIB/RPGUNIT.LIB"
          systemTypeKey="OS/400"
          listing="ftp-listing.txt"
          >
         <fileset dir="./i5-downloads-lib" casesensitive="false">
             <include name="**\run*.mbr" />
         </fileset>
     </ftp>
Output:
-------
  [echo] Listing members of all files of a library:
   [ftp] listing files
   [ftp] listing RPGUNIT1.FILE\RUN.MBR
   [ftp] listing RPGUNIT1.FILE\RUNRMT.MBR
   [ftp] listing RPGUNITT1.FILE\RUNT.MBR
   [ftp] listing RPGUNITY1.FILE\RUN.MBR
   [ftp] listing RPGUNITY1.FILE\RUNNER.MBR
   [ftp] listing RPGUNITY1.FILE\RUNNERBND.MBR
   [ftp] 6 files listed
Example 3, using ANT to download specific members of a file:
------------------------------------------------------------
     <echo/>
     <echo>Downloading members of a file:</echo>
     <ftp action="get"
          server="${ftp.server}"
          userid="${ftp.user}"
          password="${ftp.password}"
          binary="false"
          verbose="true"
          remotedir="/QSYS.LIB/RPGUNIT.LIB/RPGUNITY1.FILE"
          systemTypeKey="OS/400"
          >
         <fileset dir="./i5-downloads-file" casesensitive="false">
             <include name="run*.mbr" />
         </fileset>
     </ftp>
Output:
-------
  [echo] Downloading members of a file:
   [ftp] getting files
   [ftp] transferring RUN.MBR to C:\workspaces\rdp_080\workspace\ANT - FTP\i5-downloads-file\RUN.MBR
   [ftp] transferring RUNNER.MBR to C:\workspaces\rdp_080\workspace\ANT - FTP\i5-downloads-file\RUNNER.MBR
   [ftp] transferring RUNNERBND.MBR to C:\workspaces\rdp_080\workspace\ANT - FTP\i5-downloads-file\RUNNERBND.MBR
   [ftp] 3 files retrieved
Example 4, using ANT to download specific members of all files of a library:
----------------------------------------------------------------------------
     <echo/>
     <echo>Downloading members of all files of a library:</echo>
     <ftp action="get"
          server="${ftp.server}"
          userid="${ftp.user}"
          password="${ftp.password}"
          binary="false"
          verbose="true"
          remotedir="/QSYS.LIB/RPGUNIT.LIB"
          systemTypeKey="OS/400"
          >
         <fileset dir="./i5-downloads-lib" casesensitive="false">
             <include name="**\run*.mbr" />
         </fileset>
     </ftp>
Output:
-------
  [echo] Downloading members of all files of a library:
   [ftp] getting files
   [ftp] transferring RPGUNIT1.FILE\RUN.MBR to C:\work\rdp_080\space\ANT - FTP\i5-downloads\RPGUNIT1.FILE\RUN.MBR
   [ftp] transferring RPGUNIT1.FILE\RUNRMT.MBR to C:\work\rdp_080\space\ANT - FTP\i5-downloads\RPGUNIT1.FILE\RUNRMT.MBR
   [ftp] transferring RPGUNITT1.FILE\RUNT.MBR to C:\work\rdp_080\space\ANT - FTP\i5-downloads\RPGUNITT1.FILE\RUNT.MBR
   [ftp] transferring RPGUNITY1.FILE\RUN.MBR to C:\work\rdp_080\space\ANT - FTP\i5-downloads\RPGUNITY1.FILE\RUN.MBR
   [ftp] transferring RPGUNITY1.FILE\RUNNER.MBR to C:\work\rdp_080\space\ANT - FTP\i5-downloads\RPGUNITY1.FILE\RUNNER.MBR
   [ftp] transferring RPGUNITY1.FILE\RUNNERBND.MBR to C:\work\rdp_080\space\ANT - FTP\i5-downloads\RPGUNITY1.FILE\RUNNERBND.MBR
   [ftp] 6 files retrieved
Example 5, using ANT to download a save file of a library:
----------------------------------------------------------
     <ftp action="get"
          server="${ftp.server}"
          userid="${ftp.user}"
          password="${ftp.password}"
          binary="true"
          verbose="true"
          remotedir="/QSYS.LIB/RPGUNIT.LIB"
          systemTypeKey="OS/400"
          >
       <fileset dir="./i5-downloads-savf" casesensitive="false">
           <include name="RPGUNIT.SAVF" />
       </fileset>
     </ftp>
Output:
-------
  [echo] Downloading save file:
   [ftp] getting files
   [ftp] transferring RPGUNIT.SAVF to C:\workspaces\rdp_080\workspace\net-Test\i5-downloads-lib\RPGUNIT.SAVF
   [ftp] 1 files retrieved
/** * @version $Id: OS400FTPEntryParser.java 1752660 2016-07-14 13:25:39Z sebb $ * <pre> * Example *FILE/*MEM FTP entries, when the current * working directory is a file of file system QSYS: * ------------------------------------------------ * * $ cwd /qsys.lib/rpgunit.lib/rpgunitc1.file * 250-NAMEFMT set to 1. * 250 "/QSYS.LIB/RPGUNIT.LIB/RPGUNITC1.FILE" is current directory. * $ dir * 227 Entering Passive Mode (10,200,36,33,40,249). * 125 List started. * QPGMR 135168 22.06.13 13:18:19 *FILE * QPGMR *MEM MKCMD.MBR * QPGMR *MEM RUCALLTST.MBR * QPGMR *MEM RUCMDHLP.MBR * QPGMR *MEM RUCRTTST.MBR * 250 List completed. * * * Example *FILE entry of an OS/400 save file: * --------------------------------------------------- * * $ cwd /qsys.lib/rpgunit.lib * 250 "/QSYS.LIB/RPGUNIT.LIB" is current library. * $ dir rpgunit.file * 227 Entering Passive Mode (10,200,36,33,188,106). * 125 List started. * QPGMR 16347136 29.06.13 15:45:09 *FILE RPGUNIT.SAVF * 250 List completed. * * * Example *STMF/*DIR FTP entries, when the * current working directory is in file system "root": * --------------------------------------------------- * * $ cwd /home/raddatz * 250 "/home/raddatz" is current directory. * $ dir test* * 227 Entering Passive Mode (10,200,36,33,200,189). * 125 List started. * RADDATZ 200 21.05.11 12:31:18 *STMF TEST_RG_02_CRLF.properties * RADDATZ 187 08.05.11 12:31:40 *STMF TEST_RG_02_LF.properties * RADDATZ 187 08.05.11 12:31:52 *STMF TEST_RG_02_CR.properties * RADDATZ 8192 04.07.13 09:04:14 *DIR testDir1/ * RADDATZ 8192 04.07.13 09:04:17 *DIR testDir2/ * 250 List completed. * * * Example 1, using ANT to list specific members of a file: * -------------------------------------------------------- * * &lt;echo/&gt; * &lt;echo&gt;Listing members of a file:&lt;/echo&gt; * * &lt;ftp action="list" * server="${ftp.server}" * userid="${ftp.user}" * password="${ftp.password}" * binary="false" * verbose="true" * remotedir="/QSYS.LIB/RPGUNIT.LIB/RPGUNITY1.FILE" * systemTypeKey="OS/400" * listing="ftp-listing.txt" * &gt; * &lt;fileset dir="./i5-downloads-file" casesensitive="false"&gt; * &lt;include name="run*.mbr" /&gt; * &lt;/fileset&gt; * &lt;/ftp&gt; * * Output: * ------- * * [echo] Listing members of a file: * [ftp] listing files * [ftp] listing RUN.MBR * [ftp] listing RUNNER.MBR * [ftp] listing RUNNERBND.MBR * [ftp] 3 files listed * * * Example 2, using ANT to list specific members of all files of a library: * ------------------------------------------------------------------------ * * &lt;echo/&gt; * &lt;echo&gt;Listing members of all files of a library:&lt;/echo&gt; * * &lt;ftp action="list" * server="${ftp.server}" * userid="${ftp.user}" * password="${ftp.password}" * binary="false" * verbose="true" * remotedir="/QSYS.LIB/RPGUNIT.LIB" * systemTypeKey="OS/400" * listing="ftp-listing.txt" * &gt; * &lt;fileset dir="./i5-downloads-lib" casesensitive="false"&gt; * &lt;include name="**\run*.mbr" /&gt; * &lt;/fileset&gt; * &lt;/ftp&gt; * * Output: * ------- * * [echo] Listing members of all files of a library: * [ftp] listing files * [ftp] listing RPGUNIT1.FILE\RUN.MBR * [ftp] listing RPGUNIT1.FILE\RUNRMT.MBR * [ftp] listing RPGUNITT1.FILE\RUNT.MBR * [ftp] listing RPGUNITY1.FILE\RUN.MBR * [ftp] listing RPGUNITY1.FILE\RUNNER.MBR * [ftp] listing RPGUNITY1.FILE\RUNNERBND.MBR * [ftp] 6 files listed * * * Example 3, using ANT to download specific members of a file: * ------------------------------------------------------------ * * &lt;echo/&gt; * &lt;echo&gt;Downloading members of a file:&lt;/echo&gt; * * &lt;ftp action="get" * server="${ftp.server}" * userid="${ftp.user}" * password="${ftp.password}" * binary="false" * verbose="true" * remotedir="/QSYS.LIB/RPGUNIT.LIB/RPGUNITY1.FILE" * systemTypeKey="OS/400" * &gt; * &lt;fileset dir="./i5-downloads-file" casesensitive="false"&gt; * &lt;include name="run*.mbr" /&gt; * &lt;/fileset&gt; * &lt;/ftp&gt; * * Output: * ------- * * [echo] Downloading members of a file: * [ftp] getting files * [ftp] transferring RUN.MBR to C:\workspaces\rdp_080\workspace\ANT - FTP\i5-downloads-file\RUN.MBR * [ftp] transferring RUNNER.MBR to C:\workspaces\rdp_080\workspace\ANT - FTP\i5-downloads-file\RUNNER.MBR * [ftp] transferring RUNNERBND.MBR to C:\workspaces\rdp_080\workspace\ANT - FTP\i5-downloads-file\RUNNERBND.MBR * [ftp] 3 files retrieved * * * Example 4, using ANT to download specific members of all files of a library: * ---------------------------------------------------------------------------- * * &lt;echo/&gt; * &lt;echo&gt;Downloading members of all files of a library:&lt;/echo&gt; * * &lt;ftp action="get" * server="${ftp.server}" * userid="${ftp.user}" * password="${ftp.password}" * binary="false" * verbose="true" * remotedir="/QSYS.LIB/RPGUNIT.LIB" * systemTypeKey="OS/400" * &gt; * &lt;fileset dir="./i5-downloads-lib" casesensitive="false"&gt; * &lt;include name="**\run*.mbr" /&gt; * &lt;/fileset&gt; * &lt;/ftp&gt; * * Output: * ------- * * [echo] Downloading members of all files of a library: * [ftp] getting files * [ftp] transferring RPGUNIT1.FILE\RUN.MBR to C:\work\rdp_080\space\ANT - FTP\i5-downloads\RPGUNIT1.FILE\RUN.MBR * [ftp] transferring RPGUNIT1.FILE\RUNRMT.MBR to C:\work\rdp_080\space\ANT - FTP\i5-downloads\RPGUNIT1.FILE\RUNRMT.MBR * [ftp] transferring RPGUNITT1.FILE\RUNT.MBR to C:\work\rdp_080\space\ANT - FTP\i5-downloads\RPGUNITT1.FILE\RUNT.MBR * [ftp] transferring RPGUNITY1.FILE\RUN.MBR to C:\work\rdp_080\space\ANT - FTP\i5-downloads\RPGUNITY1.FILE\RUN.MBR * [ftp] transferring RPGUNITY1.FILE\RUNNER.MBR to C:\work\rdp_080\space\ANT - FTP\i5-downloads\RPGUNITY1.FILE\RUNNER.MBR * [ftp] transferring RPGUNITY1.FILE\RUNNERBND.MBR to C:\work\rdp_080\space\ANT - FTP\i5-downloads\RPGUNITY1.FILE\RUNNERBND.MBR * [ftp] 6 files retrieved * * * Example 5, using ANT to download a save file of a library: * ---------------------------------------------------------- * * &lt;ftp action="get" * server="${ftp.server}" * userid="${ftp.user}" * password="${ftp.password}" * binary="true" * verbose="true" * remotedir="/QSYS.LIB/RPGUNIT.LIB" * systemTypeKey="OS/400" * &gt; * &lt;fileset dir="./i5-downloads-savf" casesensitive="false"&gt; * &lt;include name="RPGUNIT.SAVF" /&gt; * &lt;/fileset&gt; * &lt;/ftp&gt; * * Output: * ------- * [echo] Downloading save file: * [ftp] getting files * [ftp] transferring RPGUNIT.SAVF to C:\workspaces\rdp_080\workspace\net-Test\i5-downloads-lib\RPGUNIT.SAVF * [ftp] 1 files retrieved * * </pre> */
public class OS400FTPEntryParser extends ConfigurableFTPFileEntryParserImpl { private static final String DEFAULT_DATE_FORMAT = "yy/MM/dd HH:mm:ss"; //01/11/09 12:30:24 private static final String REGEX = "(\\S+)\\s+" // user + "(?:(\\d+)\\s+)?" // size, empty for members + "(?:(\\S+)\\s+(\\S+)\\s+)?" // date stuff, empty for members + "(\\*STMF|\\*DIR|\\*FILE|\\*MEM)\\s+" // *STMF/*DIR/*FILE/*MEM + "(?:(\\S+)\\s*)?"; // filename, missing, when CWD is a *FILE
The default constructor for a OS400FTPEntryParser object.
Throws:
  • IllegalArgumentException – Thrown if the regular expression is unparseable. Should not be seen under normal conditions. It it is seen, this is a sign that REGEX is not a valid regular expression.
/** * The default constructor for a OS400FTPEntryParser object. * * @throws IllegalArgumentException * Thrown if the regular expression is unparseable. Should not be seen * under normal conditions. It it is seen, this is a sign that * <code>REGEX</code> is not a valid regular expression. */
public OS400FTPEntryParser() { this(null); }
This constructor allows the creation of an OS400FTPEntryParser object with something other than the default configuration.
Params:
  • config – The configuration object used to configure this parser.
Throws:
  • IllegalArgumentException – Thrown if the regular expression is unparseable. Should not be seen under normal conditions. It it is seen, this is a sign that REGEX is not a valid regular expression.
Since:1.4
/** * This constructor allows the creation of an OS400FTPEntryParser object * with something other than the default configuration. * * @param config The {@link FTPClientConfig configuration} object used to * configure this parser. * @throws IllegalArgumentException * Thrown if the regular expression is unparseable. Should not be seen * under normal conditions. It it is seen, this is a sign that * <code>REGEX</code> is not a valid regular expression. * @since 1.4 */
public OS400FTPEntryParser(FTPClientConfig config) { super(REGEX); configure(config); } @Override public FTPFile parseFTPEntry(String entry) { FTPFile file = new FTPFile(); file.setRawListing(entry); int type; if (matches(entry)) { String usr = group(1); String filesize = group(2); String datestr = ""; if (!isNullOrEmpty(group(3)) || !isNullOrEmpty(group(4))) { datestr = group(3)+" "+group(4); } String typeStr = group(5); String name = group(6); boolean mustScanForPathSeparator = true; try { file.setTimestamp(super.parseTimestamp(datestr)); } catch (ParseException e) { // intentionally do nothing } if (typeStr.equalsIgnoreCase("*STMF")) { type = FTPFile.FILE_TYPE; if (isNullOrEmpty(filesize) || isNullOrEmpty(name)) { return null; } } else if (typeStr.equalsIgnoreCase("*DIR")) { type = FTPFile.DIRECTORY_TYPE; if (isNullOrEmpty(filesize) || isNullOrEmpty(name)) { return null; } } else if (typeStr.equalsIgnoreCase("*FILE")) { // File, defines the structure of the data (columns of a row) // but the data is stored in one or more members. Typically a // source file contains multiple members whereas it is // recommended (but not enforced) to use one member per data // file. // Save files are a special type of files which are used // to save objects, e.g. for backups. if (name != null && name.toUpperCase().endsWith(".SAVF")) { mustScanForPathSeparator = false; type = FTPFile.FILE_TYPE; } else { return null; } } else if (typeStr.equalsIgnoreCase("*MEM")) { mustScanForPathSeparator = false; type = FTPFile.FILE_TYPE; if (isNullOrEmpty(name)) { return null; } if (!(isNullOrEmpty(filesize) && isNullOrEmpty(datestr))) { return null; } // Quick and dirty bug fix to make SelectorUtils work. // Class SelectorUtils uses 'File.separator' to splitt // a given path into pieces. But actually it had to // use the separator of the FTP server, which is a forward // slash in case of an AS/400. name = name.replace('/', File.separatorChar); } else { type = FTPFile.UNKNOWN_TYPE; } file.setType(type); file.setUser(usr); try { file.setSize(Long.parseLong(filesize)); } catch (NumberFormatException e) { // intentionally do nothing } if (name.endsWith("/")) { name = name.substring(0, name.length() - 1); } if (mustScanForPathSeparator) { int pos = name.lastIndexOf('/'); if (pos > -1) { name = name.substring(pos + 1); } } file.setName(name); return file; } return null; }
Params:
  • string – String value that is checked for null or empty.
Returns:true for null or empty values, else false.
/** * * @param string String value that is checked for <code>null</code> * or empty. * @return <code>true</code> for <code>null</code> or empty values, * else <code>false</code>. */
private boolean isNullOrEmpty(String string) { if (string == null || string.length() == 0) { return true; } return false; }
Defines a default configuration to be used when this class is instantiated without a FTPClientConfig parameter being specified.
Returns:the default configuration for this parser.
/** * Defines a default configuration to be used when this class is * instantiated without a {@link FTPClientConfig FTPClientConfig} * parameter being specified. * @return the default configuration for this parser. */
@Override protected FTPClientConfig getDefaultConfiguration() { return new FTPClientConfig( FTPClientConfig.SYST_OS400, DEFAULT_DATE_FORMAT, null); } }