001 /* 002 * Copyright 2001-2005 The Apache Software Foundation 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package org.apache.commons.net.ftp.parser; 017 import java.io.BufferedReader; 018 import java.io.IOException; 019 import java.io.InputStream; 020 import java.text.ParseException; 021 import java.util.StringTokenizer; 022 023 import org.apache.commons.net.ftp.FTPClientConfig; 024 import org.apache.commons.net.ftp.FTPFile; 025 import org.apache.commons.net.ftp.FTPListParseEngine; 026 027 /** 028 * Implementation FTPFileEntryParser and FTPFileListParser for VMS Systems. 029 * This is a sample of VMS LIST output 030 * 031 * "1-JUN.LIS;1 9/9 2-JUN-1998 07:32:04 [GROUP,OWNER] (RWED,RWED,RWED,RE)", 032 * "1-JUN.LIS;2 9/9 2-JUN-1998 07:32:04 [GROUP,OWNER] (RWED,RWED,RWED,RE)", 033 * "DATA.DIR;1 1/9 2-JUN-1998 07:32:04 [GROUP,OWNER] (RWED,RWED,RWED,RE)", 034 * <P><B> 035 * Note: VMSFTPEntryParser can only be instantiated through the 036 * DefaultFTPParserFactory by classname. It will not be chosen 037 * by the autodetection scheme. 038 * </B> 039 * <P> 040 * 041 * @author <a href="Winston.Ojeda@qg.com">Winston Ojeda</a> 042 * @author <a href="mailto:scohen@apache.org">Steve Cohen</a> 043 * @author <a href="sestegra@free.fr">Stephane ESTE-GRACIAS</a> 044 * @version $Id: VMSFTPEntryParser.java 155429 2005-02-26 13:13:04Z dirkv $ 045 * 046 * @see org.apache.commons.net.ftp.FTPFileEntryParser FTPFileEntryParser (for usage instructions) 047 * @see org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory 048 */ 049 public class VMSFTPEntryParser extends ConfigurableFTPFileEntryParserImpl 050 { 051 052 private static final String DEFAULT_DATE_FORMAT 053 = "d-MMM-yyyy HH:mm:ss"; //9-NOV-2001 12:30:24 054 055 /** 056 * this is the regular expression used by this parser. 057 */ 058 private static final String REGEX = 059 "(.*;[0-9]+)\\s*" 060 + "(\\d+)/\\d+\\s*" 061 +"(\\S+)\\s+(\\S+)\\s+" 062 + "\\[(([0-9$A-Za-z_]+)|([0-9$A-Za-z_]+),([0-9$a-zA-Z_]+))\\]?\\s*" 063 + "\\([a-zA-Z]*,[a-zA-Z]*,[a-zA-Z]*,[a-zA-Z]*\\)"; 064 065 066 067 /** 068 * Constructor for a VMSFTPEntryParser object. 069 * 070 * @exception IllegalArgumentException 071 * Thrown if the regular expression is unparseable. Should not be seen 072 * under normal conditions. It it is seen, this is a sign that 073 * <code>REGEX</code> is not a valid regular expression. 074 */ 075 public VMSFTPEntryParser() 076 { 077 this(null); 078 } 079 080 /** 081 * This constructor allows the creation of a VMSFTPEntryParser object with 082 * something other than the default configuration. 083 * 084 * @param config The {@link FTPClientConfig configuration} object used to 085 * configure this parser. 086 * @exception IllegalArgumentException 087 * Thrown if the regular expression is unparseable. Should not be seen 088 * under normal conditions. It it is seen, this is a sign that 089 * <code>REGEX</code> is not a valid regular expression. 090 * @since 1.4 091 */ 092 public VMSFTPEntryParser(FTPClientConfig config) 093 { 094 super(REGEX); 095 configure(config); 096 } 097 098 099 100 /*** 101 * Parses an FTP server file listing and converts it into a usable format 102 * in the form of an array of <code> FTPFile </code> instances. If the 103 * file list contains no files, <code> null </code> should be 104 * returned, otherwise an array of <code> FTPFile </code> instances 105 * representing the files in the directory is returned. 106 * <p> 107 * @param listStream The InputStream from which the file list should be 108 * read. 109 * @return The list of file information contained in the given path. null 110 * if the list could not be obtained or if there are no files in 111 * the directory. 112 * @exception IOException If an I/O error occurs reading the listStream. 113 ***/ 114 public FTPFile[] parseFileList(InputStream listStream) throws IOException { 115 FTPListParseEngine engine = new FTPListParseEngine(this); 116 engine.readServerList(listStream); 117 return engine.getFiles(); 118 } 119 120 121 122 /** 123 * Parses a line of a VMS FTP server file listing and converts it into a 124 * usable format in the form of an <code> FTPFile </code> instance. If the 125 * file listing line doesn't describe a file, <code> null </code> is 126 * returned, otherwise a <code> FTPFile </code> instance representing the 127 * files in the directory is returned. 128 * <p> 129 * @param entry A line of text from the file listing 130 * @return An FTPFile instance corresponding to the supplied entry 131 */ 132 public FTPFile parseFTPEntry(String entry) 133 { 134 //one block in VMS equals 512 bytes 135 long longBlock = 512; 136 137 if (matches(entry)) 138 { 139 FTPFile f = new FTPFile(); 140 f.setRawListing(entry); 141 String name = group(1); 142 String size = group(2); 143 String datestr = group(3)+" "+group(4); 144 String owner = group(5); 145 try 146 { 147 f.setTimestamp(super.parseTimestamp(datestr)); 148 } 149 catch (ParseException e) 150 { 151 return null; // this is a parsing failure too. 152 } 153 154 155 String grp; 156 String user; 157 StringTokenizer t = new StringTokenizer(owner, ","); 158 switch (t.countTokens()) { 159 case 1: 160 grp = null; 161 user = t.nextToken(); 162 break; 163 case 2: 164 grp = t.nextToken(); 165 user = t.nextToken(); 166 break; 167 default: 168 grp = null; 169 user = null; 170 } 171 172 if (name.lastIndexOf(".DIR") != -1) 173 { 174 f.setType(FTPFile.DIRECTORY_TYPE); 175 } 176 else 177 { 178 f.setType(FTPFile.FILE_TYPE); 179 } 180 //set FTPFile name 181 //Check also for versions to be returned or not 182 if (isVersioning()) 183 { 184 f.setName(name); 185 } 186 else 187 { 188 name = name.substring(0, name.lastIndexOf(";")); 189 f.setName(name); 190 } 191 //size is retreived in blocks and needs to be put in bytes 192 //for us humans and added to the FTPFile array 193 long sizeInBytes = Long.parseLong(size) * longBlock; 194 f.setSize(sizeInBytes); 195 196 f.setGroup(grp); 197 f.setUser(user); 198 //set group and owner 199 //Since I don't need the persmissions on this file (RWED), I'll 200 //leave that for further development. 'Cause it will be a bit 201 //elaborate to do it right with VMSes World, Global and so forth. 202 return f; 203 } 204 return null; 205 } 206 207 208 /** 209 * Reads the next entry using the supplied BufferedReader object up to 210 * whatever delemits one entry from the next. This parser cannot use 211 * the default implementation of simply calling BufferedReader.readLine(), 212 * because one entry may span multiple lines. 213 * 214 * @param reader The BufferedReader object from which entries are to be 215 * read. 216 * 217 * @return A string representing the next ftp entry or null if none found. 218 * @exception IOException thrown on any IO Error reading from the reader. 219 */ 220 public String readNextEntry(BufferedReader reader) throws IOException 221 { 222 String line = reader.readLine(); 223 StringBuffer entry = new StringBuffer(); 224 while (line != null) 225 { 226 if (line.startsWith("Directory") || line.startsWith("Total")) { 227 line = reader.readLine(); 228 continue; 229 } 230 231 entry.append(line); 232 if (line.trim().endsWith(")")) 233 { 234 break; 235 } 236 line = reader.readLine(); 237 } 238 return (entry.length() == 0 ? null : entry.toString()); 239 } 240 241 protected boolean isVersioning() { 242 return false; 243 } 244 245 /** 246 * Defines a default configuration to be used when this class is 247 * instantiated without a {@link FTPClientConfig FTPClientConfig} 248 * parameter being specified. 249 * @return the default configuration for this parser. 250 */ 251 protected FTPClientConfig getDefaultConfiguration() { 252 return new FTPClientConfig( 253 FTPClientConfig.SYST_VMS, 254 DEFAULT_DATE_FORMAT, 255 null, null, null, null); 256 } 257 258 259 } 260 261 /* Emacs configuration 262 * Local variables: ** 263 * mode: java ** 264 * c-basic-offset: 4 ** 265 * indent-tabs-mode: nil ** 266 * End: ** 267 */