001    /*
002     * ftp4j - A pure Java FTP client library
003     * 
004     * Copyright (C) 2008-2009 Carlo Pelliccia (www.sauronsoftware.it)
005     * 
006     * This program is free software: you can redistribute it and/or modify
007     * it under the terms of the GNU Lesser General Public License version
008     * 2.1, as published by the Free Software Foundation.
009     *
010     * This program is distributed in the hope that it will be useful,
011     * but WITHOUT ANY WARRANTY; without even the implied warranty of
012     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013     * GNU General Public License for more details.
014     *
015     * You should have received a copy of the GNU Lesser General Public
016     * License version 2.1 along with this program.
017     * If not, see <http://www.gnu.org/licenses/>.
018     */
019    package it.sauronsoftware.ftp4j.listparsers;
020    
021    import it.sauronsoftware.ftp4j.FTPFile;
022    import it.sauronsoftware.ftp4j.FTPListParseException;
023    import it.sauronsoftware.ftp4j.FTPListParser;
024    
025    import java.text.DateFormat;
026    import java.text.ParseException;
027    import java.text.SimpleDateFormat;
028    import java.util.Calendar;
029    import java.util.Date;
030    import java.util.GregorianCalendar;
031    import java.util.Locale;
032    import java.util.regex.Matcher;
033    import java.util.regex.Pattern;
034    
035    /**
036     * This parser can handle the result of a list ftp command as it is a UNIX "ls
037     * -l" command response.
038     * 
039     * @author Carlo Pelliccia
040     */
041    public class UnixListParser implements FTPListParser {
042    
043            private static final Pattern PATTERN = Pattern
044                            .compile("^([dl\\-])[r\\-][w\\-][x\\-][r\\-][w\\-][x\\-][r\\-][w\\-][x\\-]\\s+"
045                                            + "(?:\\d+\\s+)?\\S+\\s*\\S+\\s+(\\d+)\\s+(?:(\\w{3})\\s+(\\d{1,2}))\\s+"
046                                            + "(?:(\\d{4})|(?:(\\d{1,2}):(\\d{1,2})))\\s+"
047                                            + "([^\\\\/*?\"<>|]+)(?: -> ([^\\\\*?\"<>|]+))?$");
048    
049            private static final DateFormat DATE_FORMAT = new SimpleDateFormat(
050                            "MMM dd yyyy HH:mm", Locale.US);
051    
052            public FTPFile[] parse(String[] lines) throws FTPListParseException {
053                    int size = lines.length;
054                    if (size == 0) {
055                            return new FTPFile[0];
056                    }
057                    // Removes the "total" line used in MAC style.
058                    if (lines[0].startsWith("total")) {
059                            size--;
060                            String[] lines2 = new String[size];
061                            for (int i = 0; i < size; i++) {
062                                    lines2[i] = lines[i + 1];
063                            }
064                            lines = lines2;
065                    }
066                    // Ok, starts parsing.
067                    int currentYear = new GregorianCalendar().get(Calendar.YEAR);
068                    FTPFile[] ret = new FTPFile[size];
069                    for (int i = 0; i < size; i++) {
070                            Matcher m = PATTERN.matcher(lines[i]);
071                            if (m.matches()) {
072                                    ret[i] = new FTPFile();
073                                    // Retrieve the data.
074                                    String typeString = m.group(1);
075                                    String sizeString = m.group(2);
076                                    String monthString = m.group(3);
077                                    String dayString = m.group(4);
078                                    String yearString = m.group(5);
079                                    String hourString = m.group(6);
080                                    String minuteString = m.group(7);
081                                    String nameString = m.group(8);
082                                    String linkedString = m.group(9);
083                                    // Parse the data.
084                                    if (typeString.equals("-")) {
085                                            ret[i].setType(FTPFile.TYPE_FILE);
086                                    } else if (typeString.equals("d")) {
087                                            ret[i].setType(FTPFile.TYPE_DIRECTORY);
088                                    } else if (typeString.equals("l")) {
089                                            ret[i].setType(FTPFile.TYPE_LINK);
090                                            ret[i].setLink(linkedString);
091                                    } else {
092                                            throw new FTPListParseException();
093                                    }
094                                    long fileSize;
095                                    try {
096                                            fileSize = Long.parseLong(sizeString);
097                                    } catch (Throwable t) {
098                                            throw new FTPListParseException();
099                                    }
100                                    ret[i].setSize(fileSize);
101                                    if (dayString.length() == 1) {
102                                            dayString = "0" + dayString;
103                                    }
104                                    StringBuffer mdString = new StringBuffer();
105                                    mdString.append(monthString);
106                                    mdString.append(' ');
107                                    mdString.append(dayString);
108                                    mdString.append(' ');
109                                    if (yearString == null) {
110                                            mdString.append(currentYear);
111                                    } else {
112                                            mdString.append(yearString);
113                                    }
114                                    mdString.append(' ');
115                                    if (hourString != null && minuteString != null) {
116                                            if (hourString.length() == 1) {
117                                                    hourString = "0" + hourString;
118                                            }
119                                            if (minuteString.length() == 1) {
120                                                    minuteString = "0" + minuteString;
121                                            }
122                                            mdString.append(hourString);
123                                            mdString.append(':');
124                                            mdString.append(minuteString);
125                                    } else {
126                                            mdString.append("00:00");
127                                    }
128                                    Date md;
129                                    try {
130                                            md = DATE_FORMAT.parse(mdString.toString());
131                                    } catch (ParseException e) {
132                                            throw new FTPListParseException();
133                                    }
134                                    ret[i].setModifiedDate(md);
135                                    ret[i].setName(nameString);
136                            } else {
137                                    throw new FTPListParseException();
138                            }
139                    }
140                    return ret;
141            }
142    
143    }