    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
    018    package org.apache.commons.net.ftp.parser;
    019    import java.io.BufferedReader;
    020    import java.io.IOException;
    021    import java.text.ParseException;
    022    import java.util.StringTokenizer;
    023
    024    import org.apache.commons.net.ftp.FTPClientConfig;
    025    import 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     * @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 1299238 2012-03-10 17:12:28Z sebb $
    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*"                                                   //1  file and version
    060            + "(\\d+)/\\d+\\s*"                                                 //2  size/allocated
    061            +"(\\S+)\\s+(\\S+)\\s+"                                             //3+4 date and time
    062            + "\\[(([0-9$A-Za-z_]+)|([0-9$A-Za-z_]+),([0-9$a-zA-Z_]+))\\]?\\s*" //5(6,7,8) owner
    063            + "\\([a-zA-Z]*,([a-zA-Z]*),([a-zA-Z]*),([a-zA-Z]*)\\)";            //9,10,11 Permissions (O,G,W)
    064        // TODO - perhaps restrict permissions to [RWED]* ?
    065
    066
    067
    068        /**
    069         * Constructor for a VMSFTPEntryParser object.
    070         *
    071         * @exception IllegalArgumentException
    072         * Thrown if the regular expression is unparseable.  Should not be seen
    073         * under normal conditions.  It it is seen, this is a sign that
    074         * <code>REGEX</code> is  not a valid regular expression.
    075         */
    076        public VMSFTPEntryParser()
    077        {
    078            this(null);
    079        }
    080
    081        /**
    082         * This constructor allows the creation of a VMSFTPEntryParser object with
    083         * something other than the default configuration.
    084         *
    085         * @param config The {@link FTPClientConfig configuration} object used to
    086         * configure this parser.
    087         * @exception IllegalArgumentException
    088         * Thrown if the regular expression is unparseable.  Should not be seen
    089         * under normal conditions.  It it is seen, this is a sign that
    090         * <code>REGEX</code> is  not a valid regular expression.
    091         * @since 1.4
    092         */
    093        public VMSFTPEntryParser(FTPClientConfig config)
    094        {
    095            super(REGEX);
    096            configure(config);
    097        }
    098
    099        /**
    100         * Parses a line of a VMS FTP server file listing and converts it into a
    101         * usable format in the form of an <code> FTPFile </code> instance.  If the
    102         * file listing line doesn't describe a file, <code> null </code> is
    103         * returned, otherwise a <code> FTPFile </code> instance representing the
    104         * files in the directory is returned.
    105         * <p>
    106         * @param entry A line of text from the file listing
    107         * @return An FTPFile instance corresponding to the supplied entry
    108         */
    109        public FTPFile parseFTPEntry(String entry)
    110        {
    111            //one block in VMS equals 512 bytes
    112            long longBlock = 512;
    113
    114            if (matches(entry))
    115            {
    116                FTPFile f = new FTPFile();
    117                f.setRawListing(entry);
    118                String name = group(1);
    119                String size = group(2);
    120                String datestr = group(3)+" "+group(4);
    121                String owner = group(5);
    122                String permissions[] = new String[3];
    123                permissions[0]= group(9);
    124                permissions[1]= group(10);
    125                permissions[2]= group(11);
    126                try
    127                {
    128                    f.setTimestamp(super.parseTimestamp(datestr));
    129                }
    130                catch (ParseException e)
    131                {
    132                     // intentionally do nothing
    133                }
    134
    135
    136                String grp;
    137                String user;
    138                StringTokenizer t = new StringTokenizer(owner, ",");
    139                switch (t.countTokens()) {
    140                    case 1:
    141                        grp  = null;
    142                        user = t.nextToken();
    143                        break;
    144                    case 2:
    145                        grp  = t.nextToken();
    146                        user = t.nextToken();
    147                        break;
    148                    default:
    149                        grp  = null;
    150                        user = null;
    151                }
    152
    153                if (name.lastIndexOf(".DIR") != -1)
    154                {
    155                    f.setType(FTPFile.DIRECTORY_TYPE);
    156                }
    157                else
    158                {
    159                    f.setType(FTPFile.FILE_TYPE);
    160                }
    161                //set FTPFile name
    162                //Check also for versions to be returned or not
    163                if (isVersioning())
    164                {
    165                    f.setName(name);
    166                }
    167                else
    168                {
    169                    name = name.substring(0, name.lastIndexOf(";"));
    170                    f.setName(name);
    171                }
    172                //size is retreived in blocks and needs to be put in bytes
    173                //for us humans and added to the FTPFile array
    174                long sizeInBytes = Long.parseLong(size) * longBlock;
    175                f.setSize(sizeInBytes);
    176
    177                f.setGroup(grp);
    178                f.setUser(user);
    179                //set group and owner
    180
    181                //Set file permission.
    182                //VMS has (SYSTEM,OWNER,GROUP,WORLD) users that can contain
    183                //R (read) W (write) E (execute) D (delete)
    184
    185                //iterate for OWNER GROUP WORLD permissions
    186                for (int access = 0; access < 3; access++)
    187                {
    188                    String permission = permissions[access];
    189
    190                    f.setPermission(access, FTPFile.READ_PERMISSION, permission.indexOf('R')>=0);
    191                    f.setPermission(access, FTPFile.WRITE_PERMISSION, permission.indexOf('W')>=0);
    192                    f.setPermission(access, FTPFile.EXECUTE_PERMISSION, permission.indexOf('E')>=0);
    193                }
    194
    195                return f;
    196            }
    197            return null;
    198        }
    199
    200
    201        /**
    202         * Reads the next entry using the supplied BufferedReader object up to
    203         * whatever delemits one entry from the next.   This parser cannot use
    204         * the default implementation of simply calling BufferedReader.readLine(),
    205         * because one entry may span multiple lines.
    206         *
    207         * @param reader The BufferedReader object from which entries are to be
    208         * read.
    209         *
    210         * @return A string representing the next ftp entry or null if none found.
    211         * @exception IOException thrown on any IO Error reading from the reader.
    212         */
    213        @Override
    214        public String readNextEntry(BufferedReader reader) throws IOException
    215        {
    216            String line = reader.readLine();
    217            StringBuilder entry = new StringBuilder();
    218            while (line != null)
    219            {
    220                if (line.startsWith("Directory") || line.startsWith("Total")) {
    221                    line = reader.readLine();
    222                    continue;
    223                }
    224
    225                entry.append(line);
    226                if (line.trim().endsWith(")"))
    227                {
    228                    break;
    229                }
    230                line = reader.readLine();
    231            }
    232            return (entry.length() == 0 ? null : entry.toString());
    233        }
    234
    235        protected boolean isVersioning() {
    236            return false;
    237        }
    238
    239        /**
    240         * Defines a default configuration to be used when this class is
    241         * instantiated without a {@link  FTPClientConfig  FTPClientConfig}
    242         * parameter being specified.
    243         * @return the default configuration for this parser.
    244         */
    245        @Override
    246        protected FTPClientConfig getDefaultConfiguration() {
    247            return new FTPClientConfig(
    248                    FTPClientConfig.SYST_VMS,
    249                    DEFAULT_DATE_FORMAT,
    250                    null, null, null, null);
    251        }
    252
    253        // DEPRECATED METHODS - for API compatibility only - DO NOT USE
    254
    255        /**
    256         * DO NOT USE
    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     */