View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.net.ftp.parser;
19  import java.io.BufferedReader;
20  import java.io.IOException;
21  import java.io.InputStream;
22  import java.text.ParseException;
23  import java.util.StringTokenizer;
24  
25  import org.apache.commons.net.ftp.FTPClientConfig;
26  import org.apache.commons.net.ftp.FTPFile;
27  import org.apache.commons.net.ftp.FTPListParseEngine;
28  
29  /**
30   * Implementation FTPFileEntryParser and FTPFileListParser for VMS Systems.
31   * This is a sample of VMS LIST output
32   *
33   *  "1-JUN.LIS;1              9/9           2-JUN-1998 07:32:04  [GROUP,OWNER]    (RWED,RWED,RWED,RE)",
34   *  "1-JUN.LIS;2              9/9           2-JUN-1998 07:32:04  [GROUP,OWNER]    (RWED,RWED,RWED,RE)",
35   *  "DATA.DIR;1               1/9           2-JUN-1998 07:32:04  [GROUP,OWNER]    (RWED,RWED,RWED,RE)",
36   * <P><B>
37   * Note: VMSFTPEntryParser can only be instantiated through the
38   * DefaultFTPParserFactory by classname.  It will not be chosen
39   * by the autodetection scheme.
40   * </B>
41   * <P>
42   *
43   * @author  <a href="Winston.Ojeda@qg.com">Winston Ojeda</a>
44   * @author <a href="mailto:scohen@apache.org">Steve Cohen</a>
45   * @author <a href="sestegra@free.fr">Stephane ESTE-GRACIAS</a>
46   * @version $Id: VMSFTPEntryParser.java 658518 2008-05-21 01:04:30Z sebb $
47   *
48   * @see org.apache.commons.net.ftp.FTPFileEntryParser FTPFileEntryParser (for usage instructions)
49   * @see org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory
50   */
51  public class VMSFTPEntryParser extends ConfigurableFTPFileEntryParserImpl
52  {
53  
54      private static final String DEFAULT_DATE_FORMAT 
55          = "d-MMM-yyyy HH:mm:ss"; //9-NOV-2001 12:30:24
56  
57      /**
58       * this is the regular expression used by this parser.
59       */
60      private static final String REGEX =
61          "(.*;[0-9]+)\\s*"                                                   //1  file and version
62          + "(\\d+)/\\d+\\s*"                                                 //2  size/allocated
63          +"(\\S+)\\s+(\\S+)\\s+"                                             //3+4 date and time
64          + "\\[(([0-9$A-Za-z_]+)|([0-9$A-Za-z_]+),([0-9$a-zA-Z_]+))\\]?\\s*" //5(6,7,8) owner
65          + "\\([a-zA-Z]*,([a-zA-Z]*),([a-zA-Z]*),([a-zA-Z]*)\\)";            //9,10,11 Permissions (O,G,W)
66      // TODO - perhaps restrict permissions to [RWED]* ?
67  
68  
69  
70      /**
71       * Constructor for a VMSFTPEntryParser object.
72       *
73       * @exception IllegalArgumentException
74       * Thrown if the regular expression is unparseable.  Should not be seen
75       * under normal conditions.  It it is seen, this is a sign that
76       * <code>REGEX</code> is  not a valid regular expression.
77       */
78      public VMSFTPEntryParser()
79      {
80          this(null);
81      }
82  
83      /**
84       * This constructor allows the creation of a VMSFTPEntryParser object with
85       * something other than the default configuration.
86       *
87       * @param config The {@link FTPClientConfig configuration} object used to 
88       * configure this parser.
89       * @exception IllegalArgumentException
90       * Thrown if the regular expression is unparseable.  Should not be seen
91       * under normal conditions.  It it is seen, this is a sign that
92       * <code>REGEX</code> is  not a valid regular expression.
93       * @since 1.4
94       */
95      public VMSFTPEntryParser(FTPClientConfig config)
96      {
97          super(REGEX);
98          configure(config);
99      }
100 
101 
102 
103     /***
104      * Parses an FTP server file listing and converts it into a usable format
105      * in the form of an array of <code> FTPFile </code> instances.  If the
106      * file list contains no files, <code> null </code> should be
107      * returned, otherwise an array of <code> FTPFile </code> instances
108      * representing the files in the directory is returned.
109      * <p>
110      * @param listStream The InputStream from which the file list should be
111      *        read.
112      * @return The list of file information contained in the given path.  null
113      *     if the list could not be obtained or if there are no files in
114      *     the directory.
115      * @exception IOException  If an I/O error occurs reading the listStream.
116      ***/
117     public FTPFile[] parseFileList(InputStream listStream) throws IOException {
118         FTPListParseEngine engine = new FTPListParseEngine(this);
119         engine.readServerList(listStream);
120         return engine.getFiles();
121     }
122 
123 
124 
125     /**
126      * Parses a line of a VMS FTP server file listing and converts it into a
127      * usable format in the form of an <code> FTPFile </code> instance.  If the
128      * file listing line doesn't describe a file, <code> null </code> is
129      * returned, otherwise a <code> FTPFile </code> instance representing the
130      * files in the directory is returned.
131      * <p>
132      * @param entry A line of text from the file listing
133      * @return An FTPFile instance corresponding to the supplied entry
134      */
135     public FTPFile parseFTPEntry(String entry)
136     {
137         //one block in VMS equals 512 bytes
138         long longBlock = 512;
139 
140         if (matches(entry))
141         {
142             FTPFile f = new FTPFile();
143             f.setRawListing(entry);
144             String name = group(1);
145             String size = group(2);
146             String datestr = group(3)+" "+group(4);
147             String owner = group(5);
148             String permissions[] = new String[3];
149             permissions[0]= group(9);
150             permissions[1]= group(10);
151             permissions[2]= group(11);
152             try
153             {
154                 f.setTimestamp(super.parseTimestamp(datestr));
155             }
156             catch (ParseException e)
157             {
158                  // intentionally do nothing
159             }
160 
161 
162             String grp;
163             String user;
164             StringTokenizer t = new StringTokenizer(owner, ",");
165             switch (t.countTokens()) {
166                 case 1:
167                     grp  = null;
168                     user = t.nextToken();
169                     break;
170                 case 2:
171                     grp  = t.nextToken();
172                     user = t.nextToken();
173                     break;
174                 default:
175                     grp  = null;
176                     user = null;
177             }
178 
179             if (name.lastIndexOf(".DIR") != -1)
180             {
181                 f.setType(FTPFile.DIRECTORY_TYPE);
182             }
183             else
184             {
185                 f.setType(FTPFile.FILE_TYPE);
186             }
187             //set FTPFile name
188             //Check also for versions to be returned or not
189             if (isVersioning())
190             {
191                 f.setName(name);
192             }
193             else
194             {
195                 name = name.substring(0, name.lastIndexOf(";"));
196                 f.setName(name);
197             }
198             //size is retreived in blocks and needs to be put in bytes
199             //for us humans and added to the FTPFile array
200             long sizeInBytes = Long.parseLong(size) * longBlock;
201             f.setSize(sizeInBytes);
202 
203             f.setGroup(grp);
204             f.setUser(user);
205             //set group and owner
206 
207             //Set file permission. 
208             //VMS has (SYSTEM,OWNER,GROUP,WORLD) users that can contain
209             //R (read) W (write) E (execute) D (delete)
210 
211             //iterate for OWNER GROUP WORLD permissions 
212             for (int access = 0; access < 3; access++)
213             {
214                 String permission = permissions[access];
215 
216                 f.setPermission(access, FTPFile.READ_PERMISSION, permission.indexOf('R')>=0);
217                 f.setPermission(access, FTPFile.WRITE_PERMISSION, permission.indexOf('W')>=0);
218                 f.setPermission(access, FTPFile.EXECUTE_PERMISSION, permission.indexOf('E')>=0);
219             }
220 
221             return f;
222         }
223         return null;
224     }
225 
226 
227     /**
228      * Reads the next entry using the supplied BufferedReader object up to
229      * whatever delemits one entry from the next.   This parser cannot use
230      * the default implementation of simply calling BufferedReader.readLine(),
231      * because one entry may span multiple lines.
232      *
233      * @param reader The BufferedReader object from which entries are to be
234      * read.
235      *
236      * @return A string representing the next ftp entry or null if none found.
237      * @exception IOException thrown on any IO Error reading from the reader.
238      */
239     @Override
240     public String readNextEntry(BufferedReader reader) throws IOException
241     {
242         String line = reader.readLine();
243         StringBuffer entry = new StringBuffer();
244         while (line != null)
245         {
246             if (line.startsWith("Directory") || line.startsWith("Total")) {
247                 line = reader.readLine();
248                 continue;
249             }
250 
251             entry.append(line);
252             if (line.trim().endsWith(")"))
253             {
254                 break;
255             }
256             line = reader.readLine();
257         }
258         return (entry.length() == 0 ? null : entry.toString());
259     }
260 
261     protected boolean isVersioning() {
262         return false;
263     }
264     
265     /**
266      * Defines a default configuration to be used when this class is
267      * instantiated without a {@link  FTPClientConfig  FTPClientConfig}
268      * parameter being specified.
269      * @return the default configuration for this parser.
270      */
271     @Override
272     protected FTPClientConfig getDefaultConfiguration() {
273         return new FTPClientConfig(
274                 FTPClientConfig.SYST_VMS,
275                 DEFAULT_DATE_FORMAT,
276                 null, null, null, null);
277     }
278 
279 
280 }
281 
282 /* Emacs configuration
283  * Local variables:        **
284  * mode:             java  **
285  * c-basic-offset:   4     **
286  * indent-tabs-mode: nil   **
287  * End:                    **
288  */