Return-Path: Delivered-To: apmail-jakarta-commons-dev-archive@www.apache.org Received: (qmail 32200 invoked from network); 2 Sep 2006 13:45:20 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 2 Sep 2006 13:45:20 -0000 Received: (qmail 13644 invoked by uid 500); 2 Sep 2006 13:45:18 -0000 Delivered-To: apmail-jakarta-commons-dev-archive@jakarta.apache.org Received: (qmail 13572 invoked by uid 500); 2 Sep 2006 13:45:18 -0000 Mailing-List: contact commons-dev-help@jakarta.apache.org; run by ezmlm Precedence: bulk List-Unsubscribe: List-Help: List-Post: List-Id: "Jakarta Commons Developers List" Reply-To: "Jakarta Commons Developers List" Delivered-To: mailing list commons-dev@jakarta.apache.org Received: (qmail 13533 invoked by uid 500); 2 Sep 2006 13:45:18 -0000 Received: (qmail 13529 invoked by uid 99); 2 Sep 2006 13:45:17 -0000 Received: from asf.osuosl.org (HELO asf.osuosl.org) (140.211.166.49) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 02 Sep 2006 06:45:17 -0700 X-ASF-Spam-Status: No, hits=-9.4 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received-SPF: pass (asf.osuosl.org: local policy) Received: from [140.211.166.113] (HELO eris.apache.org) (140.211.166.113) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 02 Sep 2006 06:45:13 -0700 Received: by eris.apache.org (Postfix, from userid 65534) id A7C481A981A; Sat, 2 Sep 2006 06:44:53 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r439598 - in /jakarta/commons/proper/net/branches/JDK_1_5_BRANCH/src: main/java/examples/FTPSExample.java main/java/org/apache/commons/net/ftp/parser/MVSFTPEntryParser.java test/java/org/apache/commons/net/ftp/parser/MVSFTPEntryParserTest.java Date: Sat, 02 Sep 2006 13:44:53 -0000 To: commons-cvs@jakarta.apache.org From: rwinston@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20060902134453.A7C481A981A@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N Author: rwinston Date: Sat Sep 2 06:44:52 2006 New Revision: 439598 URL: http://svn.apache.org/viewvc?rev=439598&view=rev Log: Added new MVSFTPEntryParser.java Modified: jakarta/commons/proper/net/branches/JDK_1_5_BRANCH/src/main/java/examples/FTPSExample.java jakarta/commons/proper/net/branches/JDK_1_5_BRANCH/src/main/java/org/apache/commons/net/ftp/parser/MVSFTPEntryParser.java jakarta/commons/proper/net/branches/JDK_1_5_BRANCH/src/test/java/org/apache/commons/net/ftp/parser/MVSFTPEntryParserTest.java Modified: jakarta/commons/proper/net/branches/JDK_1_5_BRANCH/src/main/java/examples/FTPSExample.java URL: http://svn.apache.org/viewvc/jakarta/commons/proper/net/branches/JDK_1_5_BRANCH/src/main/java/examples/FTPSExample.java?rev=439598&r1=439597&r2=439598&view=diff ============================================================================== --- jakarta/commons/proper/net/branches/JDK_1_5_BRANCH/src/main/java/examples/FTPSExample.java (original) +++ jakarta/commons/proper/net/branches/JDK_1_5_BRANCH/src/main/java/examples/FTPSExample.java Sat Sep 2 06:44:52 2006 @@ -53,6 +53,7 @@ int base = 0; boolean storeFile = false, binaryTransfer = false, error = false; String server, username, password, remote, local; + String protocol = "SSL"; // SSL/TLS FTPSClient ftps; for (base = 0; base < args.length; base++) @@ -77,7 +78,7 @@ remote = args[base++]; local = args[base]; - ftps = new FTPSClient(); + ftps = new FTPSClient(protocol); ftps.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out))); Modified: jakarta/commons/proper/net/branches/JDK_1_5_BRANCH/src/main/java/org/apache/commons/net/ftp/parser/MVSFTPEntryParser.java URL: http://svn.apache.org/viewvc/jakarta/commons/proper/net/branches/JDK_1_5_BRANCH/src/main/java/org/apache/commons/net/ftp/parser/MVSFTPEntryParser.java?rev=439598&r1=439597&r2=439598&view=diff ============================================================================== --- jakarta/commons/proper/net/branches/JDK_1_5_BRANCH/src/main/java/org/apache/commons/net/ftp/parser/MVSFTPEntryParser.java (original) +++ jakarta/commons/proper/net/branches/JDK_1_5_BRANCH/src/main/java/org/apache/commons/net/ftp/parser/MVSFTPEntryParser.java Sat Sep 2 06:44:52 2006 @@ -1,5 +1,5 @@ /* - * Copyright 2005 The Apache Software Foundation + * Copyright 2001-2006 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,221 +22,215 @@ import org.apache.commons.net.ftp.FTPFile; /** - * Implementation of FTPFileEntryParser and FTPFileListParser for IBM zOS/MVS Systems. - * - * @author Henrik Sorensen + * Implementation of FTPFileEntryParser and FTPFileListParser for IBM zOS/MVS + * Systems. * - * wagely based on earlier work done by: + * @author Henrik Sorensen * @author Jeff Nadler * @author William Noto - + * * @version $Id$ - * @see org.apache.commons.net.ftp.FTPFileEntryParser FTPFileEntryParser (for usage instructions) + * @see org.apache.commons.net.ftp.FTPFileEntryParser FTPFileEntryParser (for + * usage instructions) */ public class MVSFTPEntryParser extends ConfigurableFTPFileEntryParserImpl { - private static final boolean DEBUG_PARSER = true; // false; - public static final int UNKNOWN_LIST_TYPE = -1; - public static final int FILE_LIST_TYPE = 0; - public static final int MEMBER_LIST_TYPE = 1; - public static final int UNIX_LIST_TYPE = 2; - public static final int JES_LEVEL1_LIST_TYPE = 3; - public static final int JES_LEVEL2_LIST_TYPE = 4; + static final int UNKNOWN_LIST_TYPE = -1; + static final int FILE_LIST_TYPE = 0; + static final int MEMBER_LIST_TYPE = 1; + static final int UNIX_LIST_TYPE = 2; + static final int JES_LEVEL_1_LIST_TYPE = 3; + static final int JES_LEVEL_2_LIST_TYPE = 4; + private int isType = UNKNOWN_LIST_TYPE; + /** + * Fallback parser for Unix-style listings + */ private UnixFTPEntryParser unixFTPEntryParser; /** - * Dates are ignored for file lists, but are used for member - * lists where possible + * Dates are ignored for file lists, but are used for member lists where + * possible */ - static final String DEFAULT_DATE_FORMAT = "yyyy/MM/dd HH:mm"; // 2001/09/18 13:52 + static final String DEFAULT_DATE_FORMAT = "yyyy/MM/dd HH:mm"; // 2001/09/18 + // 13:52 /** - * Matches these entries: - * Volume Unit Referred Ext Used Recfm Lrecl BlkSz Dsorg Dsname - * B10142 3390 2006/03/20 2 31 F 80 80 PS MDI.OKL.WORK - * - */ - /*public static final String REGEX_FILELIST = "\\S+\\s+" + //volume ignored - "\\S+\\s+" + //unit - ignored - "\\S+\\s+" + //access date - ignored - "\\S+\\s+" + //extents -ignored - "\\S+\\s+" + //used - ignored - "[FV]\\S*\\s+" + //recfm - must start with F or V - "\\S+\\s+" + //logical record length -ignored - "\\S+\\s+" + //block size - ignored - "(PS|PO|PO-E)\\s+" + // Dataset organisation. Many exist - //but only support: PS, PO, PO-E - "(\\S+)\\s*"; // Dataset Name (file name)*/ - public static final String REGEX_FILELIST = "(.*)\\s+([^\\s]+)\\s*"; - - /** - * Matches these entries: - * Name VV.MM Created Changed Size Init Mod Id - * TBSHELF 01.03 2002/09/12 2002/10/11 09:37 11 11 0 KIL001 - */ - private static final String REGEX_MEMBERLIST = "(\\S+)\\s+" + //name - "\\S+\\s+" + //version, modification (ignored) - "\\S+\\s+" + //create date (ignored) - "(\\S+)\\s+" + // modification date - "(\\S+)\\s+" + // modification time - "\\S+\\s+" + //size in lines (ignored) - "\\S+\\s+" + //size in lines at creation(ignored) - "\\S+\\s+" + //lines modified (ignored) - "\\S+\\s*"; // id of user who modified (ignored) - - /** - * Matches these entries, note: no header: - * IBMUSER1 JOB01906 OUTPUT 3 Spool Files - * 012345678901234567890123456789012345678901234 - * 1 2 3 4 - */ - private static final String REGEX_JESLEVEL1LIST = "(\\S+)\\s+" + //job name ignored - "(\\S+)\\s+" + //job number - "(\\S+)\\s+" + //job status (OUTPUT,INPUT,ACTIVE) - "(\\S+)\\s+" + //number of spool files - "(\\S+)\\s+" + //Text "Spool" ignored - "(\\S+)\\s*" //Text "Files" ignored + * Matches these entries: Volume Unit Referred Ext Used Recfm Lrecl BlkSz + * Dsorg Dsname B10142 3390 2006/03/20 2 31 F 80 80 PS MDI.OKL.WORK + * + */ + static final String FILE_LIST_REGEX = "\\S+\\s+" + // volume + // ignored + "\\S+\\s+" + // unit - ignored + "\\S+\\s+" + // access date - ignored + "\\S+\\s+" + // extents -ignored + "\\S+\\s+" + // used - ignored + "[FV]\\S*\\s+" + // recfm - must start with F or V + "\\S+\\s+" + // logical record length -ignored + "\\S+\\s+" + // block size - ignored + "(PS|PO|PO-E)\\s+" + // Dataset organisation. Many exist + // but only support: PS, PO, PO-E + "(\\S+)\\s*"; // Dataset Name (file name) + + /** + * Matches these entries: Name VV.MM Created Changed Size Init Mod Id + * TBSHELF 01.03 2002/09/12 2002/10/11 09:37 11 11 0 KIL001 + */ + static final String MEMBER_LIST_REGEX = "(\\S+)\\s+" + // name + "\\S+\\s+" + // version, modification (ignored) + "\\S+\\s+" + // create date (ignored) + "(\\S+)\\s+" + // modification date + "(\\S+)\\s+" + // modification time + "\\S+\\s+" + // size in lines (ignored) + "\\S+\\s+" + // size in lines at creation(ignored) + "\\S+\\s+" + // lines modified (ignored) + "\\S+\\s*"; // id of user who modified (ignored) + + /** + * Matches these entries, note: no header: IBMUSER1 JOB01906 OUTPUT 3 Spool + * Files 012345678901234567890123456789012345678901234 1 2 3 4 + */ + static final String JES_LEVEL_1_LIST_REGEX = "(\\S+)\\s+" + // job + // name + // ignored + "(\\S+)\\s+" + // job number + "(\\S+)\\s+" + // job status (OUTPUT,INPUT,ACTIVE) + "(\\S+)\\s+" + // number of spool files + "(\\S+)\\s+" + // Text "Spool" ignored + "(\\S+)\\s*" // Text "Files" ignored ; /** - * TODO: the JES INTERFACE LEVEL 2 parser is still work in progress. - * Matches these entries: - * 1 2 3 4 - * 012345678901234567890123456789012345678901234567890 - *ftp> quote site filetype=jes - 200 SITE command was accepted - ftp> ls - 200 Port request OK. - 125 List started OK for JESJOBNAME=IBMUSER*, JESSTATUS=ALL and JESOWNER=IBMUSER - JOBNAME JOBID OWNER STATUS CLASS - IBMUSER1 JOB01906 IBMUSER OUTPUT A RC=0000 3 spool files - IBMUSER TSU01830 IBMUSER OUTPUT TSU ABEND=522 3 spool files - 250 List completed successfully. - ftp> ls job01906 - 200 Port request OK. - 125 List started OK for JESJOBNAME=IBMUSER*, JESSTATUS=ALL and JESOWNER=IBMUSER - JOBNAME JOBID OWNER STATUS CLASS - IBMUSER1 JOB01906 IBMUSER OUTPUT A RC=0000 - -------- - ID STEPNAME PROCSTEP C DDNAME BYTE-COUNT - 001 JES2 A JESMSGLG 858 - 002 JES2 A JESJCL 128 - 003 JES2 A JESYSMSG 443 - 3 spool files - 250 List completed successfully. - */ - - private static final String REGEX_JESLEVEL2LIST = "(\\S+)\\s+" + //job name ignored - "(\\S+)\\s+" + //job number - "(\\S+)\\s+" + //job status (OUTPUT,INPUT,ACTIVE) - "(\\S+)\\s+" + //number of spool files - "(\\S+)\\s+" + //Text "Spool" ignored - "(\\S+)\\s*" //Text "Files" ignored + * JES INTERFACE LEVEL 2 parser Matches these entries: JOBNAME JOBID OWNER + * STATUS CLASS IBMUSER1 JOB01906 IBMUSER OUTPUT A RC=0000 3 spool files + * IBMUSER TSU01830 IBMUSER OUTPUT TSU ABEND=522 3 spool files + * 012345678901234567890123456789012345678901234 1 2 3 4 + * 012345678901234567890123456789012345678901234567890 + */ + + static final String JES_LEVEL_2_LIST_REGEX = "(\\S+)\\s+" + // job + // name + // ignored + "(\\S+)\\s+" + // job number + "(\\S+)\\s+" + // owner ignored + "(\\S+)\\s+" + // job status (OUTPUT,INPUT,ACTIVE) ignored + "(\\S+)\\s+" + // job class ignored + "(\\S+).*" // rest ignored ; - /* --------------------------------------------------------------------- - * Very brief and incomplete description of the zOS/MVS-filesystem. - * (Note: "zOS" is the operating system on the mainframe, - * and is the new name for MVS) - * - * The filesystem on the mainframe does not have hierarchal structure as - * for example the unix filesystem. - * For a more comprehensive description, please refer to the IBM manuals + /* + * --------------------------------------------------------------------- + * Very brief and incomplete description of the zOS/MVS-filesystem. (Note: + * "zOS" is the operating system on the mainframe, and is the new name for + * MVS) + * + * The filesystem on the mainframe does not have hierarchal structure as for + * example the unix filesystem. For a more comprehensive description, please + * refer to the IBM manuals * - * @LINK: http://publibfp.boulder.ibm.com/cgi-bin/bookmgr/BOOKS/dgt2d440/CONTENTS + * @LINK: + * http://publibfp.boulder.ibm.com/cgi-bin/bookmgr/BOOKS/dgt2d440/CONTENTS * * - * Dataset names - * ============= + * Dataset names ============= * - * A dataset name consist of a number of qualifiers separated by '.', - * each qualifier can be at most 8 characters, and the total length - * of a dataset can be max 44 characters including the dots. + * A dataset name consist of a number of qualifiers separated by '.', each + * qualifier can be at most 8 characters, and the total length of a dataset + * can be max 44 characters including the dots. * * - * Dataset organisation - * ==================== + * Dataset organisation ==================== * - * A dataset represents a piece of storage allocated on one or more disks. - * The structure of the storage is described with the field dataset organinsation (DSORG). - * There are a number of dataset organisations, but only two are usable for FTP transfer. + * A dataset represents a piece of storage allocated on one or more disks. + * The structure of the storage is described with the field dataset + * organinsation (DSORG). There are a number of dataset organisations, but + * only two are usable for FTP transfer. * - * DSORG: - * PS: sequential, or flat file - * PO: partitioned dataset - * PO-E: extended partitioned dataset + * DSORG: PS: sequential, or flat file PO: partitioned dataset PO-E: + * extended partitioned dataset * - * The PS file is just a flat file, as you would find it on the unix - * file system. + * The PS file is just a flat file, as you would find it on the unix file + * system. * - * The PO and PO-E files, can be compared to a single level directory structure. - * A PO file consist of a number of dataset members, or files if you - * will. It is possible to CD into the file, and to retrieve the + * The PO and PO-E files, can be compared to a single level directory + * structure. A PO file consist of a number of dataset members, or files if + * you will. It is possible to CD into the file, and to retrieve the * individual members. * * - * Dataset record format - * ===================== + * Dataset record format ===================== * * The physical layout of the dataset is described on the dataset itself. - * There are a number of record formats (RECFM), but just a few is relavant for - * the FTP transfer. + * There are a number of record formats (RECFM), but just a few is relavant + * for the FTP transfer. + * + * Any one beginning with either F or V can safely used by FTP transfer. All + * others should only be used with great care, so this version will just + * ignore the other record formats. F means a fixed number of records per + * allocated storage, and V means a variable number of records. * - * Any one beginning with either F or V can safely used by FTP transfer. - * All others should only be used with great care, so this version will just - * ignore the other record formats. - * F means a fixed number of records per allocated storage, and V means a variable - * number of records. - * - * - * Other notes - * =========== - * - * The file system supports automatically backup and retrieval of datasets. If a - * file is backed up, the ftp LIST command will return: - * ARCIVE Not Direct Access Device KJ.IOP998.ERROR.PL.UNITTEST - * - * - * Implementation notes - * ==================== - * - * Only datasets that have dsorg PS, PO or PO-E and have recfm - * beginning with F or V, is fully parsed. - * - * The following fields in FTPFile is used: - * FTPFile.Rawlisting: Always set. - * FTPFile.Type: DIRECTORY_TYPE or FILE_TYPE or UNKNOWN - * FTPFile.Name: name + * + * Other notes =========== + * + * The file system supports automatically backup and retrieval of datasets. + * If a file is backed up, the ftp LIST command will return: ARCIVE Not + * Direct Access Device KJ.IOP998.ERROR.PL.UNITTEST + * + * + * Implementation notes ==================== + * + * Only datasets that have dsorg PS, PO or PO-E and have recfm beginning + * with F or V, is fully parsed. + * + * The following fields in FTPFile is used: FTPFile.Rawlisting: Always set. + * FTPFile.Type: DIRECTORY_TYPE or FILE_TYPE or UNKNOWN FTPFile.Name: name * FTPFile.Timestamp: change time or null * + * + * + * Additional information ====================== + * + * The MVS ftp server supports a number of features via the FTP interface. + * The features are controlled with the FTP command quote site filetype= + * SEQ is the default and used for normal file transfer JES is used to + * interact with the Job Entry Subsystem (JES) similar to a job scheduler + * DB2 is used to interact with a DB2 subsystem + * + * This parser supports SEQ and JES. + * + * + * + * + * + * */ /** * The sole constructor for a MVSFTPEntryParser object. - * + * */ public MVSFTPEntryParser() { super(""); // note the regex is set in preParse. + super.configure(null); // configure parser with default configurations } /** - * Parses a line of an z/OS - MVS FTP server file listing and converts it into a - * usable format in the form of an FTPFile instance. If the - * file listing line doesn't describe a file, then null is returned. - * Otherwise a FTPFile instance representing the file is returned. + * Parses a line of an z/OS - MVS FTP server file listing and converts it + * into a usable format in the form of an FTPFile instance. + * If the file listing line doesn't describe a file, then + * null is returned. Otherwise a FTPFile + * instance representing the file is returned. * - * @param entry A line of text from the file listing + * @param entry + * A line of text from the file listing * @return An FTPFile instance corresponding to the supplied entry */ public FTPFile parseFTPEntry(String entry) { - boolean isParsed; + boolean isParsed = false; FTPFile f = new FTPFile(); - logPrintln("MVSFTPEntryParser entry >" + entry + "<"); - - isParsed = false; if (isType == FILE_LIST_TYPE) isParsed = parseFileList(f, entry); else if (isType == MEMBER_LIST_TYPE) { @@ -245,127 +239,101 @@ isParsed = parseSimpleEntry(f, entry); } else if (isType == UNIX_LIST_TYPE) { isParsed = parseUnixList(f, entry); - } else if (isType == JES_LEVEL1_LIST_TYPE) { + } else if (isType == JES_LEVEL_1_LIST_TYPE) { isParsed = parseJeslevel1List(f, entry); + } else if (isType == JES_LEVEL_2_LIST_TYPE) { + isParsed = parseJeslevel2List(f, entry); } - if (isParsed) - logPrintln("Name " - + f.getName() - + ", type " - + f.getType() - + ", timestamp " - + (f.getTimestamp() != null ? f.getTimestamp().getTime() - .toString() : "null") + ", rawlisting " - + f.getRawListing()); - else { - logPrintln("Entry did not parse ..."); - f = null; /* as per calling convention, parser must return null */ - } - + if (!isParsed) + f = null; + return f; } /** - * Parse entries representing a dataset list. - * Only datasets with DSORG PS or PO or PO-E - * and with RECFM F* or V* will be parsed. - * - * Format of ZOS/MVS file list: - * 0 1 2 3 4 5 6 7 8 9 - * Volume Unit Referred Ext Used Recfm Lrecl BlkSz Dsorg Dsname - * B10142 3390 2006/03/20 2 31 F 80 80 PS MDI.OKL.WORK - * ARCIVE Not Direct Access Device KJ.IOP998.ERROR.PL.UNITTEST - * B1N231 3390 2006/03/20 1 15 VB 256 27998 PO PLU - * B1N231 3390 2006/03/20 1 15 VB 256 27998 PO-E PLB - * - * ----------------------------------- - * [0] Volume - * [1] Unit - * [2] Referred - * [3] Ext: number of extents - * [4] Used - * [5] Recfm: Record format - * [6] Lrecl: Logical record length - * [7] BlkSz: Block size - * [8] Dsorg: Dataset organisation. Many exists but only support: PS, PO, PO-E - * [9] Dsname: Dataset name + * Parse entries representing a dataset list. Only datasets with DSORG PS or + * PO or PO-E and with RECFM F* or V* will be parsed. + * + * Format of ZOS/MVS file list: 1 2 3 4 5 6 7 8 9 10 Volume Unit Referred + * Ext Used Recfm Lrecl BlkSz Dsorg Dsname B10142 3390 2006/03/20 2 31 F 80 + * 80 PS MDI.OKL.WORK ARCIVE Not Direct Access Device + * KJ.IOP998.ERROR.PL.UNITTEST B1N231 3390 2006/03/20 1 15 VB 256 27998 PO + * PLU B1N231 3390 2006/03/20 1 15 VB 256 27998 PO-E PLB + * + * ----------------------------------- Group within Regex [1] Volume [2] + * Unit [3] Referred [4] Ext: number of extents [5] Used [6] Recfm: Record + * format [7] Lrecl: Logical record length [8] BlkSz: Block size [9] Dsorg: + * Dataset organisation. Many exists but only support: PS, PO, PO-E [10] + * Dsname: Dataset name * * Note: When volume is ARCIVE, it means the dataset is stored somewhere in - * a tape archive. These entries is currently not supported by this - * parser. A null value is returned. - * - * @param f: will be updated with Name, Type, Timestamp if parsed. + * a tape archive. These entries is currently not supported by this parser. + * A null value is returned. + * + * @param f: + * will be updated with Name, Type, Timestamp if parsed. * @param zosDirectoryEntry * @return true: entry was parsed, false: entry was not parsed. */ private boolean parseFileList(FTPFile file, String entry) { - logPrintln("MvsFilelistFTPEntryParser " + entry); if (matches(entry)) { file.setRawListing(entry); String name = group(2); String dsorg = group(1); - logPrint(" parsed name " + name + ", dsorg " + dsorg); file.setName(name); - //DSORG + // DSORG if ("PS".equals(dsorg)) { file.setType(FTPFile.FILE_TYPE); - logPrintln("... is a file "); - } else if ("PO".equals(dsorg) || "PO-E".equals(dsorg)) { - // regex already ruled out anything other than - // PO or PO-E + } + else if ("PO".equals(dsorg) || "PO-E".equals(dsorg)) { + // regex already ruled out anything other than PO or PO-E file.setType(FTPFile.DIRECTORY_TYPE); - logPrintln("... is a directory "); - } else { - logPrintln("... is currently not supported."); + } + else { return false; } - + return true; } - + return false; } /** * Parse entries within a partitioned dataset. * - * Format of a memberlist within a PDS: - * 0 1 2 3 4 5 6 7 8 - * Name VV.MM Created Changed Size Init Mod Id - * TBSHELF 01.03 2002/09/12 2002/10/11 09:37 11 11 0 KIL001 - * TBTOOL 01.12 2002/09/12 2004/11/26 19:54 51 28 0 KIL001 - * - * ------------------------------------------- - * [0] Name - * [1] VV.MM: Version . modification - * [2] Created: yyyy / MM / dd - * [3,4] Changed: yyyy / MM / dd HH:mm - * [5] Size: number of lines - * [6] Init: number of lines when first created - * [7] Mod: number of modified lines a last save - * [8] Id: User id for last update + * Format of a memberlist within a PDS: 1 2 3 4 5 6 7 8 9 Name VV.MM Created + * Changed Size Init Mod Id TBSHELF 01.03 2002/09/12 2002/10/11 09:37 11 11 + * 0 KIL001 TBTOOL 01.12 2002/09/12 2004/11/26 19:54 51 28 0 KIL001 + * + * ------------------------------------------- [1] Name [2] VV.MM: Version . + * modification [3] Created: yyyy / MM / dd [4,5] Changed: yyyy / MM / dd + * HH:mm [6] Size: number of lines [7] Init: number of lines when first + * created [8] Mod: number of modified lines a last save [9] Id: User id for + * last update * * - * @param f: will be updated with Name, Type and Timestamp if parsed. + * @param f: + * will be updated with Name, Type and Timestamp if parsed. * @param zosDirectoryEntry * @return true: entry was parsed, false: entry was not parsed. */ private boolean parseMemberList(FTPFile file, String entry) { - - logPrintln("MvsMemberlistFTPEntryParser " + entry); if (matches(entry)) { file.setRawListing(entry); String name = group(1); String datestr = group(2) + " " + group(3); - logPrintln(" parsed name " + name + ", datestr " + datestr); file.setName(name); file.setType(FTPFile.FILE_TYPE); try { file.setTimestamp(super.parseTimestamp(datestr)); - } catch (ParseException e) { // just ignore parsing errors. - //return null; // this is a parsing failure too. + } catch (ParseException e) { + e.printStackTrace(); + // just ignore parsing errors. + // TODO check this is ok + return false; // this is a parsing failure too. } return true; } @@ -374,33 +342,28 @@ } /** - * Assigns the name to the first word of the entry. - * Only to be used from a safe context, for example from - * a memberlist, where the regex for some reason fails. - * Then just assign the name field of FTPFile. + * Assigns the name to the first word of the entry. Only to be used from a + * safe context, for example from a memberlist, where the regex for some + * reason fails. Then just assign the name field of FTPFile. + * * @param file * @param entry * @return */ private boolean parseSimpleEntry(FTPFile file, String entry) { - - logPrint("SimpleEntryParser " + entry); if (entry != null && entry.length() > 0) { file.setRawListing(entry); String name = entry.split(" ")[0]; - logPrintln(" parsed name " + name); file.setName(name); file.setType(FTPFile.FILE_TYPE); - return true; } - return false; } /** - * Parse the entry as a standard unix file. - * Using the UnixFTPEntryParser. + * Parse the entry as a standard unix file. Using the UnixFTPEntryParser. + * * @param file * @param entry * @return true: entry is parsed, false: entry could not be parsed. @@ -413,44 +376,53 @@ } /** - * Parse entries within a partitioned dataset. - * - * Format of a memberlist within a PDS: - * 0 1 2 3 4 5 6 7 8 - * Name VV.MM Created Changed Size Init Mod Id - * TBSHELF 01.03 2002/09/12 2002/10/11 09:37 11 11 0 KIL001 - * TBTOOL 01.12 2002/09/12 2004/11/26 19:54 51 28 0 KIL001 - * - * ------------------------------------------- - * [0] Name - * [1] VV.MM: Version . modification - * [2] Created: yyyy / MM / dd - * [3,4] Changed: yyyy / MM / dd HH:mm - * [5] Size: number of lines - * [6] Init: number of lines when first created - * [7] Mod: number of modified lines a last save - * [8] Id: User id for last update + * Matches these entries, note: no header: [1] [2] [3] [4] [5] IBMUSER1 + * JOB01906 OUTPUT 3 Spool Files + * 012345678901234567890123456789012345678901234 1 2 3 4 + * ------------------------------------------- Group in regex [1] Job name + * [2] Job number [3] Job status (INPUT,ACTIVE,OUTPUT) [4] Number of sysout + * files [5] The string "Spool Files" * * - * @param f: will be updated with Name, Type and Timestamp if parsed. + * @param f: + * will be updated with Name, Type and Timestamp if parsed. * @param zosDirectoryEntry * @return true: entry was parsed, false: entry was not parsed. */ private boolean parseJeslevel1List(FTPFile file, String entry) { - - logPrintln("JES Level 1 listFTPEntryParser >" + entry + "<"); if (matches(entry)) { - logPrintln("JES Level 1 matches = true"); - logPrintln("group(0)=" + group(0)); - logPrintln("group(1)=" + group(1)); - logPrintln("group(2)=" + group(2)); - logPrintln("group(3)=" + group(3)); - logPrintln("group(4)=" + group(4)); if (group(3).equalsIgnoreCase("OUTPUT")) { file.setRawListing(entry); String name = group(2); /* Job Number, used by GET */ - logPrintln(" parsed name " + name); + file.setName(name); + file.setType(FTPFile.FILE_TYPE); + return true; + } + } + return false; + } + + /** + * Matches these entries, note: no header: [1] [2] [3] [4] [5] JOBNAME JOBID + * OWNER STATUS CLASS IBMUSER1 JOB01906 IBMUSER OUTPUT A RC=0000 3 spool + * files IBMUSER TSU01830 IBMUSER OUTPUT TSU ABEND=522 3 spool files + * 012345678901234567890123456789012345678901234 1 2 3 4 + * ------------------------------------------- Group in regex [1] Job name + * [2] Job number [3] Owner [4] Job status (INPUT,ACTIVE,OUTPUT) [5] Job + * Class [6] The rest + * + * + * @param f: + * will be updated with Name, Type and Timestamp if parsed. + * @param zosDirectoryEntry + * @return true: entry was parsed, false: entry was not parsed. + */ + private boolean parseJeslevel2List(FTPFile file, String entry) { + if (matches(entry)) { + if (group(4).equalsIgnoreCase("OUTPUT")) { + file.setRawListing(entry); + String name = group(2); /* Job Number, used by GET */ file.setName(name); file.setType(FTPFile.FILE_TYPE); return true; @@ -462,67 +434,49 @@ /** * preParse is called as part of the interface. Per definition is is called - * before the parsing takes place. - * Three kind of lists is recognize: - * z/OS-MVS File lists - * z/OS-MVS Member lists - * unix file lists + * before the parsing takes place. Three kind of lists is recognize: + * z/OS-MVS File lists z/OS-MVS Member lists unix file lists */ public List preParse(List orig) { - // simply remove the header line. Composite logic will take care of the two different types of + // simply remove the header line. Composite logic will take care of the + // two different types of // list in short order. if (orig != null && orig.size() > 0) { String header = (String) orig.get(0); if (header.indexOf("Volume") >= 0 && header.indexOf("Dsname") >= 0) { - setParseType(FILE_LIST_TYPE); - } - else if (header.indexOf("Name") >= 0 && header.indexOf("Id") >= 0) { - setParseType(MEMBER_LIST_TYPE); - } - else if (header.indexOf("total") == 0) { - setParseType(UNIX_LIST_TYPE); - } - else if (header.indexOf("Spool Files") >= 30) { - setParseType(JES_LEVEL1_LIST_TYPE); + setType(FILE_LIST_TYPE); + super.setRegex(FILE_LIST_REGEX); + } else if (header.indexOf("Name") >= 0 && header.indexOf("Id") >= 0) { + setType(MEMBER_LIST_TYPE); + super.setRegex(MEMBER_LIST_REGEX); + } else if (header.indexOf("total") == 0) { + setType(UNIX_LIST_TYPE); + unixFTPEntryParser = new UnixFTPEntryParser(); + } else if (header.indexOf("Spool Files") >= 30) { + setType(JES_LEVEL_1_LIST_TYPE); + super.setRegex(JES_LEVEL_1_LIST_REGEX); + } else if (header.indexOf("JOBNAME") == 0 + && header.indexOf("JOBID") > 8) {// header contains JOBNAME JOBID OWNER // STATUS CLASS + setType(JES_LEVEL_2_LIST_TYPE); + super.setRegex(JES_LEVEL_2_LIST_REGEX); + } else { + setType(UNKNOWN_LIST_TYPE); + } + + if (isType != JES_LEVEL_1_LIST_TYPE) { // remove header is necessary orig.remove(0); - } - else if (header.indexOf("JOBNAME") == 0 - && header.indexOf("JOBID") > 8) {// header contains JOBNAME JOBID OWNER STATUS CLASS - setParseType(JES_LEVEL2_LIST_TYPE); - } - else { - isType = UNKNOWN_LIST_TYPE; } } + return orig; } /** - * - * @param parseType - * @throws IllegalArgumentException + * Explicitly set the type of listing being processed. + * @param type The listing type. */ - public void setParseType(int parseType) throws IllegalArgumentException { - if (parseType == FILE_LIST_TYPE) { - super.setRegex(REGEX_FILELIST); - } - else if (parseType == MEMBER_LIST_TYPE) { - super.setRegex(REGEX_MEMBERLIST); - } - else if (parseType == UNIX_LIST_TYPE) { - unixFTPEntryParser = new UnixFTPEntryParser(); - } - else if (parseType == JES_LEVEL1_LIST_TYPE) { - super.setRegex(REGEX_JESLEVEL1LIST); - } - else if (parseType == JES_LEVEL2_LIST_TYPE) { - super.setRegex(REGEX_JESLEVEL2LIST); - } - else { - throw new IllegalArgumentException("Argument must be a valid type!"); - } - - isType = parseType; + void setType(int type) { + isType = type; } /* @@ -533,17 +487,4 @@ DEFAULT_DATE_FORMAT, null, null, null, null); } - /** - * poor-mans logging ... - * @param string - */ - private void logPrint(String string) { - if (DEBUG_PARSER) - System.out.print(string); - } - - private void logPrintln(String string) { - if (DEBUG_PARSER) - System.out.println(string); - } } Modified: jakarta/commons/proper/net/branches/JDK_1_5_BRANCH/src/test/java/org/apache/commons/net/ftp/parser/MVSFTPEntryParserTest.java URL: http://svn.apache.org/viewvc/jakarta/commons/proper/net/branches/JDK_1_5_BRANCH/src/test/java/org/apache/commons/net/ftp/parser/MVSFTPEntryParserTest.java?rev=439598&r1=439597&r2=439598&view=diff ============================================================================== --- jakarta/commons/proper/net/branches/JDK_1_5_BRANCH/src/test/java/org/apache/commons/net/ftp/parser/MVSFTPEntryParserTest.java (original) +++ jakarta/commons/proper/net/branches/JDK_1_5_BRANCH/src/test/java/org/apache/commons/net/ftp/parser/MVSFTPEntryParserTest.java Sat Sep 2 06:44:52 2006 @@ -16,102 +16,229 @@ package org.apache.commons.net.ftp.parser; +import java.util.ArrayList; +import java.util.List; + import junit.framework.TestSuite; import org.apache.commons.net.ftp.FTPFile; import org.apache.commons.net.ftp.FTPFileEntryParser; /** + * Changed on August 31, 2006
+ * Test suite addapted to new MVSFTPEntryParser.java. + * @author Henrik Sorensen + * * Created on Apr 6, 2005
* @author William Noto - * @version $Id: NTFTPEntryParserTest.java,v 1.16 2005/01/02 03:17:50 scohen Exp $ + * @version $Id: MVSFTPEntryParserTest.java,v 1.16 2005/01/02 03:17:50 scohen Exp $ */ -public class MVSFTPEntryParserTest extends FTPParseTestFramework -{ - private static final String [] goodsamples = - { - "Migrated file1.I", - "Migrated file2.I", - "PSMLC1 3390 2005/04/04 1 1 VB 27994 27998 PS file3.I", - "PSMLB9 3390 2005/04/04 1 1 VB 27994 27998 PS file4.I.BU", - "PSMLB6 3390 2005/04/05 1 1 VB 27994 27998 PS file3.I.BU", - "PSMLC6 3390 2005/04/05 1 1 VB 27994 27998 PS file6.I", - "Migrated file6.O", - "PSMLB7 3390 2005/04/04 1 1 VB 27994 27998 PS file7.O", - "PSMLC6 3390 2005/04/05 1 1 VB 27994 27998 PS file7.O.BU", - "FPFS42 3390 2004/06/23 1 1 FB 128 6144 PS INCOMING.RPTBM023.D061704", - "FPFS41 3390 2004/06/23 1 1 FB 128 6144 PS INCOMING.RPTBM056.D061704", - "FPFS25 3390 2004/06/23 1 1 FB 128 6144 PS INCOMING.WTM204.D061704", - }; - - private static final String [] badsamples = - { - "MigratedP201.$FTXPBI1.$CF2ITB.$AAB0402.I", - "PSMLC133902005/04/041VB2799427998PSfile1.I", - "file2.O", - }; - - /** - * @see junit.framework.TestCase#TestCase(String) - */ - public MVSFTPEntryParserTest (String name) - { - super(name); - } - - /* (non-Javadoc) - * @see org.apache.commons.net.ftp.parser.CompositeFTPParseTestFramework#getBadListings() - */ - protected String[] getBadListing() { - return badsamples; - } - /* (non-Javadoc) - * @see org.apache.commons.net.ftp.parser.CompositeFTPParseTestFramework#getGoodListings() - */ - protected String[] getGoodListing() { - return goodsamples; - } - - - /** - * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getParser() - */ - protected FTPFileEntryParser getParser() - { - return new CompositeFileEntryParser(new FTPFileEntryParser[] - { - new MVSFTPEntryParser(), - }); - } - - /** - * Method suite. - * - * @return TestSuite - */ - public static TestSuite suite() - { - return(new TestSuite(MVSFTPEntryParserTest.class)); - } - - public void testParseFieldsOnDirectory() throws Exception - { - // I don't really know how to test this because the MVS system that I - // connect with does not allow me to create directories. - } - - /* (non-Javadoc) - * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#testParseFieldsOnFile() - */ - public void testParseFieldsOnFile() throws Exception { - FTPFile file = getParser().parseFTPEntry("Migrated file1.I"); - assertNotNull("Could not parse entry.", file); - assertTrue("Should have been a file.", file.isFile()); - assertEquals("file1.I", file.getName()); - - FTPFile file2 = getParser().parseFTPEntry("PSMLC1 3390 2005/04/04 1 1 VB 27994 27998 PS file2.I"); - assertNotNull("Could not parse entry.", file2); - assertTrue("Should have been a file.", file2.isFile()); - assertEquals("file2.I", file2.getName()); - } +public class MVSFTPEntryParserTest extends FTPParseTestFramework { + static List saveftpfiles; + + private static final String[] goodsamplesDatasetList = { /* Note, if the string begins with SAVE, the parsed entry is stored in the List saveftpfiles */ + // "Volume Unit Referred Ext Used Recfm Lrecl BlkSz Dsorg Dsname", + "SAVE00 3390 2004/06/23 1 1 FB 128 6144 PS INCOMING.RPTBM023.D061704", + "SAVE01 3390 2004/06/23 1 1 FB 128 6144 PO INCOMING.RPTBM024.D061704", + "SAVE02 3390 2004/06/23 1 1 FB 128 6144 PO-E INCOMING.RPTBM025.D061704", + "PSMLC1 3390 2005/04/04 1 1 VB 27994 27998 PS file3.I", + "PSMLB9 3390 2005/04/04 1 1 VB 27994 27998 PS file4.I.BU", + "PSMLB6 3390 2005/04/05 1 1 VB 27994 27998 PS file3.I.BU", + "PSMLC6 3390 2005/04/05 1 1 VB 27994 27998 PS file6.I", + "PSMLB7 3390 2005/04/04 1 1 VB 27994 27998 PS file7.O", + "PSMLC6 3390 2005/04/05 1 1 VB 27994 27998 PS file7.O.BU", + "FPFS49 3390 2004/06/23 1 1 FB 128 6144 PO-E INCOMING.RPTBM026.D061704", + "FPFS41 3390 2004/06/23 1 1 FB 128 6144 PS INCOMING.RPTBM056.D061704", + "FPFS25 3390 2004/06/23 1 1 FB 128 6144 PS INCOMING.WTM204.D061704", }; + + private static final String[] goodsamplesMemberList = {/* Note, if the string begins with SAVE, the parsed entry is stored in the List saveftpfiles */ + "Name VV.MM Created Changed Size Init Mod Id", + "SAVE03 01.03 2002/09/12 2002/10/11 09:37 11 11 0 KIL001", + "SAVE04 ", // no statistics + "TBSHELF1 01.03 2002/09/12 2002/10/11 09:37 11 11 0 KIL001", + "TBSHELF2 01.03 2002/09/12 2002/10/11 09:37 11 11 0 KIL001", + "TBSHELF3 01.03 2002/09/12 2002/10/11 09:37 11 11 0 KIL001", + "TBSHELF4 01.03 2002/09/12 2002/10/11 09:37 11 11 0 KIL001", }; + + private static final String[] goodsamplesJES1List = { /* no header for JES1 (JES Interface level 1) */ + /* Note, if the string begins with SAVE, the parsed entry is stored in the List saveftpfiles */ + "IBMUSER1 JOB01906 OUTPUT 3 Spool Files", }; + + private static final String[] goodsamplesJES2List = { /* JES2 (JES Interface level 2) */ + /* Note, if the string begins with SAVE, the parsed entry is stored in the List saveftpfiles */ + //"JOBNAME JOBID OWNER STATUS CLASS", + "IBMUSER2 JOB01906 IBMUSER OUTPUT A RC=0000 3 spool files", + "IBMUSER TSU01830 IBMUSER OUTPUT TSU ABEND=522 3 spool files", }; + + private static final String[] badsamples = { + "MigratedP201.$FTXPBI1.$CF2ITB.$AAB0402.I", + "PSMLC133902005/04/041VB2799427998PSfile1.I", "file2.O", }; + + /** + * @see junit.framework.TestCase#TestCase(String) + */ + public MVSFTPEntryParserTest(String name) { + super(name); + if (saveftpfiles == null) + saveftpfiles = new ArrayList(); + } + + /* (non-Javadoc) + * @see org.apache.commons.net.ftp.parser.CompositeFTPParseTestFramework#getBadListings() + */ + protected String[] getBadListing() { + return badsamples; + } + + /* (non-Javadoc) + * @see org.apache.commons.net.ftp.parser.CompositeFTPParseTestFramework#getGoodListings() + */ + protected String[] getGoodListing() { + return goodsamplesDatasetList; + } + + /** + * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getAllGoodListings() + */ + protected List getAllGoodListings() { + List l = new ArrayList(); + l.add(goodsamplesDatasetList); + l.add(goodsamplesMemberList); + l.add(goodsamplesJES1List); + l.add(goodsamplesJES2List); + + return l; + } + + /** + * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#doAdditionalGoodTests() + */ + /* Add the parsed files for more testing later */ + protected void doAdditionalGoodTests(String test, FTPFile f) { + if (test.startsWith("SAVE")) { //System.out.println("saving ftpfile name ="+f.getName()); + saveftpfiles.add(f); + } + } + + /** + * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getParser() + */ + protected FTPFileEntryParser getParser() { + return new MVSFTPEntryParser(); + } + + /** + * Method suite. + * + * @return TestSuite + */ + public static TestSuite suite() { + return (new TestSuite(MVSFTPEntryParserTest.class)); + } + + /* + * note the testGoodListing has to be the first test invoked, because + * some FTPFile entries are saved for the later tests + * + * (non-Javadoc) + * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#testGoodListing() + */ + @Override + public void testGoodListing() throws Exception { + String[] goodsamples = getGoodListing(); + MVSFTPEntryParser parser = new MVSFTPEntryParser(); + parser.setType(MVSFTPEntryParser.FILE_LIST_TYPE); + parser.setRegex(MVSFTPEntryParser.FILE_LIST_REGEX); + for (String test : goodsamples) { + FTPFile f = parser.parseFTPEntry(test); + assertNotNull("Failed to parse " + test, f); + doAdditionalGoodTests(test, f); + } + } + + public void testMemberListing() throws Exception { + MVSFTPEntryParser parser = new MVSFTPEntryParser(); + parser.setType(MVSFTPEntryParser.MEMBER_LIST_TYPE); + parser.setRegex(MVSFTPEntryParser.MEMBER_LIST_REGEX); + for (String test : goodsamplesMemberList) { + FTPFile f = parser.parseFTPEntry(test); + assertNotNull("Failed to parse " + test, f); + doAdditionalGoodTests(test, f); + } + } + + public void testJesLevel1Listing() { + MVSFTPEntryParser parser = new MVSFTPEntryParser(); + parser.setType(MVSFTPEntryParser.JES_LEVEL_1_LIST_TYPE); + parser.setRegex(MVSFTPEntryParser.JES_LEVEL_1_LIST_REGEX); + for (String test : goodsamplesJES1List) { + FTPFile f = parser.parseFTPEntry(test); + assertNotNull("Failed to parse " + test, f); + doAdditionalGoodTests(test, f); + } + } + + public void testJesLevel2Listing() { + MVSFTPEntryParser parser = new MVSFTPEntryParser(); + parser.setType(MVSFTPEntryParser.JES_LEVEL_2_LIST_TYPE); + parser.setRegex(MVSFTPEntryParser.JES_LEVEL_2_LIST_REGEX); + for (String test : goodsamplesJES2List) { + FTPFile f = parser.parseFTPEntry(test); + assertNotNull("Failed to parse " + test, f); + doAdditionalGoodTests(test, f); + } + } + + public void testParseFieldsOnDirectory() throws Exception { + MVSFTPEntryParser parser = new MVSFTPEntryParser(); + parser.setType(MVSFTPEntryParser.FILE_LIST_TYPE); + parser.setRegex(MVSFTPEntryParser.FILE_LIST_REGEX); + + FTPFile file = parser + .parseFTPEntry("SAVE01 3390 2004/06/23 1 1 FB 128 6144 PO INCOMING.RPTBM024.D061704"); + assertNotNull("Could not parse entry.", file); + assertTrue("Should have been a directory.", file.isDirectory()); + assertEquals("INCOMING.RPTBM024.D061704", file.getName()); + + file = parser + .parseFTPEntry("SAVE02 3390 2004/06/23 1 1 FB 128 6144 PO-E INCOMING.RPTBM025.D061704"); + assertNotNull("Could not parse entry.", file); + assertTrue("Should have been a directory.", file.isDirectory()); + assertEquals("INCOMING.RPTBM025.D061704", file.getName()); + + } + + /* (non-Javadoc) + * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#testParseFieldsOnFile() + */ + public void testParseFieldsOnFile() throws Exception { + FTPFile file = null; + + MVSFTPEntryParser parser = new MVSFTPEntryParser(); + + parser.setRegex(MVSFTPEntryParser.FILE_LIST_REGEX); + parser.setType(MVSFTPEntryParser.FILE_LIST_TYPE); + + file = parser.parseFTPEntry("SAVE00 3390 2004/06/23 1 1 FB 128 6144 PS INCOMING.RPTBM023.D061704"); + assertNotNull("Could not parse entry.", file); + assertTrue("Should have been a file.", file.isFile()); + assertEquals("INCOMING.RPTBM023.D061704", file.getName()); + assertNull("Timestamp should not have been set.", file.getTimestamp()); + + parser.setType(MVSFTPEntryParser.MEMBER_LIST_TYPE); + parser.setRegex(MVSFTPEntryParser.MEMBER_LIST_REGEX); + + file = parser.parseFTPEntry("SAVE03 01.03 2002/09/12 2002/10/11 09:37 11 11 0 KIL001"); + assertNotNull("Could not parse entry.", file); + assertTrue("Should have been a file.", file.isFile()); + assertEquals("SAVE03", file.getName()); + assertNotNull("Timestamp should have been set.", file.getTimestamp()); + + file = parser.parseFTPEntry("SAVE04 "); + assertNotNull("Could not parse entry.", file); + assertTrue("Should have been a file.", file.isFile()); + assertEquals("SAVE04", file.getName()); + assertNull("Timestamp should not have been set.", file.getTimestamp()); + + } } --------------------------------------------------------------------- To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org For additional commands, e-mail: commons-dev-help@jakarta.apache.org