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 */