001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018package org.apache.commons.net.ftp.parser; 019import java.io.BufferedReader; 020import java.io.IOException; 021import java.text.ParseException; 022import java.util.StringTokenizer; 023 024import org.apache.commons.net.ftp.FTPClientConfig; 025import org.apache.commons.net.ftp.FTPFile; 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 * 042 * @see org.apache.commons.net.ftp.FTPFileEntryParser FTPFileEntryParser (for usage instructions) 043 * @see org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory 044 */ 045public class VMSFTPEntryParser extends ConfigurableFTPFileEntryParserImpl 046{ 047 048 private static final String DEFAULT_DATE_FORMAT 049 = "d-MMM-yyyy HH:mm:ss"; //9-NOV-2001 12:30:24 050 051 /** 052 * this is the regular expression used by this parser. 053 */ 054 private static final String REGEX = 055 "(.*?;[0-9]+)\\s*" //1 file and version 056 + "(\\d+)(?:/\\d+)?\\s*" //2 size/allocated 057 +"(\\S+)\\s+(\\S+)\\s+" //3+4 date and time 058 + "\\[(([0-9$A-Za-z_]+)|([0-9$A-Za-z_]+),([0-9$a-zA-Z_]+))\\]?\\s*" //5(6,7,8) owner 059 + "\\([a-zA-Z]*,([a-zA-Z]*),([a-zA-Z]*),([a-zA-Z]*)\\)"; //9,10,11 Permissions (O,G,W) 060 // TODO - perhaps restrict permissions to [RWED]* ? 061 062 063 064 /** 065 * Constructor for a VMSFTPEntryParser object. 066 * 067 * @throws IllegalArgumentException 068 * Thrown if the regular expression is unparseable. Should not be seen 069 * under normal conditions. It it is seen, this is a sign that 070 * <code>REGEX</code> is not a valid regular expression. 071 */ 072 public VMSFTPEntryParser() 073 { 074 this(null); 075 } 076 077 /** 078 * This constructor allows the creation of a VMSFTPEntryParser object with 079 * something other than the default configuration. 080 * 081 * @param config The {@link FTPClientConfig configuration} object used to 082 * configure this parser. 083 * @throws IllegalArgumentException 084 * Thrown if the regular expression is unparseable. Should not be seen 085 * under normal conditions. It it is seen, this is a sign that 086 * <code>REGEX</code> is not a valid regular expression. 087 * @since 1.4 088 */ 089 public VMSFTPEntryParser(FTPClientConfig config) 090 { 091 super(REGEX); 092 configure(config); 093 } 094 095 /** 096 * Parses a line of a VMS FTP server file listing and converts it into a 097 * usable format in the form of an <code> FTPFile </code> instance. If the 098 * file listing line doesn't describe a file, <code> null </code> is 099 * returned, otherwise a <code> FTPFile </code> instance representing the 100 * files in the directory is returned. 101 * 102 * @param entry A line of text from the file listing 103 * @return An FTPFile instance corresponding to the supplied entry 104 */ 105 @Override 106 public FTPFile parseFTPEntry(String entry) 107 { 108 //one block in VMS equals 512 bytes 109 long longBlock = 512; 110 111 if (matches(entry)) 112 { 113 FTPFile f = new FTPFile(); 114 f.setRawListing(entry); 115 String name = group(1); 116 String size = group(2); 117 String datestr = group(3)+" "+group(4); 118 String owner = group(5); 119 String permissions[] = new String[3]; 120 permissions[0]= group(9); 121 permissions[1]= group(10); 122 permissions[2]= group(11); 123 try 124 { 125 f.setTimestamp(super.parseTimestamp(datestr)); 126 } 127 catch (ParseException e) 128 { 129 // intentionally do nothing 130 } 131 132 133 String grp; 134 String user; 135 StringTokenizer t = new StringTokenizer(owner, ","); 136 switch (t.countTokens()) { 137 case 1: 138 grp = null; 139 user = t.nextToken(); 140 break; 141 case 2: 142 grp = t.nextToken(); 143 user = t.nextToken(); 144 break; 145 default: 146 grp = null; 147 user = null; 148 } 149 150 if (name.lastIndexOf(".DIR") != -1) 151 { 152 f.setType(FTPFile.DIRECTORY_TYPE); 153 } 154 else 155 { 156 f.setType(FTPFile.FILE_TYPE); 157 } 158 //set FTPFile name 159 //Check also for versions to be returned or not 160 if (isVersioning()) 161 { 162 f.setName(name); 163 } 164 else 165 { 166 name = name.substring(0, name.lastIndexOf(';')); 167 f.setName(name); 168 } 169 //size is retreived in blocks and needs to be put in bytes 170 //for us humans and added to the FTPFile array 171 long sizeInBytes = Long.parseLong(size) * longBlock; 172 f.setSize(sizeInBytes); 173 174 f.setGroup(grp); 175 f.setUser(user); 176 //set group and owner 177 178 //Set file permission. 179 //VMS has (SYSTEM,OWNER,GROUP,WORLD) users that can contain 180 //R (read) W (write) E (execute) D (delete) 181 182 //iterate for OWNER GROUP WORLD permissions 183 for (int access = 0; access < 3; access++) 184 { 185 String permission = permissions[access]; 186 187 f.setPermission(access, FTPFile.READ_PERMISSION, permission.indexOf('R')>=0); 188 f.setPermission(access, FTPFile.WRITE_PERMISSION, permission.indexOf('W')>=0); 189 f.setPermission(access, FTPFile.EXECUTE_PERMISSION, permission.indexOf('E')>=0); 190 } 191 192 return f; 193 } 194 return null; 195 } 196 197 198 /** 199 * Reads the next entry using the supplied BufferedReader object up to 200 * whatever delemits one entry from the next. This parser cannot use 201 * the default implementation of simply calling BufferedReader.readLine(), 202 * because one entry may span multiple lines. 203 * 204 * @param reader The BufferedReader object from which entries are to be 205 * read. 206 * 207 * @return A string representing the next ftp entry or null if none found. 208 * @throws IOException thrown on any IO Error reading from the reader. 209 */ 210 @Override 211 public String readNextEntry(BufferedReader reader) throws IOException 212 { 213 String line = reader.readLine(); 214 StringBuilder entry = new StringBuilder(); 215 while (line != null) 216 { 217 if (line.startsWith("Directory") || line.startsWith("Total")) { 218 line = reader.readLine(); 219 continue; 220 } 221 222 entry.append(line); 223 if (line.trim().endsWith(")")) 224 { 225 break; 226 } 227 line = reader.readLine(); 228 } 229 return (entry.length() == 0 ? null : entry.toString()); 230 } 231 232 protected boolean isVersioning() { 233 return false; 234 } 235 236 /** 237 * Defines a default configuration to be used when this class is 238 * instantiated without a {@link FTPClientConfig FTPClientConfig} 239 * parameter being specified. 240 * @return the default configuration for this parser. 241 */ 242 @Override 243 protected FTPClientConfig getDefaultConfiguration() { 244 return new FTPClientConfig( 245 FTPClientConfig.SYST_VMS, 246 DEFAULT_DATE_FORMAT, 247 null); 248 } 249 250 // DEPRECATED METHODS - for API compatibility only - DO NOT USE 251 252 /** 253 * DO NOT USE 254 * @param listStream the stream 255 * @return the array of files 256 * @throws IOException on error 257 * @deprecated (2.2) No other FTPFileEntryParser implementations have this method. 258 */ 259 @Deprecated 260 public FTPFile[] parseFileList(java.io.InputStream listStream) throws IOException { 261 org.apache.commons.net.ftp.FTPListParseEngine engine = new org.apache.commons.net.ftp.FTPListParseEngine(this); 262 engine.readServerList(listStream, null); 263 return engine.getFiles(); 264 } 265 266} 267 268/* Emacs configuration 269 * Local variables: ** 270 * mode: java ** 271 * c-basic-offset: 4 ** 272 * indent-tabs-mode: nil ** 273 * End: ** 274 */