You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by se...@apache.org on 2012/01/04 23:10:18 UTC
svn commit: r1227346 - in /commons/proper/net/trunk/src: changes/
main/java/org/apache/commons/net/ftp/
main/java/org/apache/commons/net/ftp/parser/
test/java/org/apache/commons/net/ftp/parser/
Author: sebb
Date: Wed Jan 4 22:10:17 2012
New Revision: 1227346
URL: http://svn.apache.org/viewvc?rev=1227346&view=rev
Log:
NET-436 - Support for SYST "Mac OS" listing
Added:
commons/proper/net/trunk/src/main/java/org/apache/commons/net/ftp/parser/MacOsPeterFTPEntryParser.java (with props)
commons/proper/net/trunk/src/test/java/org/apache/commons/net/ftp/parser/MacOsPeterFTPEntryParserTest.java (with props)
Modified:
commons/proper/net/trunk/src/changes/changes.xml
commons/proper/net/trunk/src/main/java/org/apache/commons/net/ftp/FTPClientConfig.java
commons/proper/net/trunk/src/main/java/org/apache/commons/net/ftp/parser/DefaultFTPFileEntryParserFactory.java
commons/proper/net/trunk/src/test/java/org/apache/commons/net/ftp/parser/DefaultFTPFileEntryParserFactoryTest.java
Modified: commons/proper/net/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/net/trunk/src/changes/changes.xml?rev=1227346&r1=1227345&r2=1227346&view=diff
==============================================================================
--- commons/proper/net/trunk/src/changes/changes.xml (original)
+++ commons/proper/net/trunk/src/changes/changes.xml Wed Jan 4 22:10:17 2012
@@ -59,6 +59,9 @@ The <action> type attribute can be add,u
<release version="3.1-SNAPSHOT" date="TBA" description="
TBA
">
+ <action issue="NET-436" dev="sebb" type="add">
+ Support for SYST "Mac OS" listing - "MACOS Peter's Server"
+ </action>
<action issue="NET-425" dev="sebb" type="add">
_openDataConnection_, __storeFile, and __storeFileStream should be protected and take String for FTP command.
Likewise for receiveFile and receiveFileStream.
Modified: commons/proper/net/trunk/src/main/java/org/apache/commons/net/ftp/FTPClientConfig.java
URL: http://svn.apache.org/viewvc/commons/proper/net/trunk/src/main/java/org/apache/commons/net/ftp/FTPClientConfig.java?rev=1227346&r1=1227345&r2=1227346&view=diff
==============================================================================
--- commons/proper/net/trunk/src/main/java/org/apache/commons/net/ftp/FTPClientConfig.java (original)
+++ commons/proper/net/trunk/src/main/java/org/apache/commons/net/ftp/FTPClientConfig.java Wed Jan 4 22:10:17 2012
@@ -205,6 +205,15 @@ public class FTPClientConfig
*/
public static final String SYST_NETWARE = "NETWARE";
+ /**
+ * Identifier by which a Mac pre OS-X -based ftp server is known throughout
+ * the commons-net ftp system.
+ *
+ * @since 3.1
+ */
+ // Full string is "MACOS Peter's Server"; the substring below should be enough
+ public static final String SYST_MACOS_PETER = "MACOS PETER"; // NET-436
+
private final String serverSystemKey;
private String defaultDateFormatStr = null;
private String recentDateFormatStr = null;
Modified: commons/proper/net/trunk/src/main/java/org/apache/commons/net/ftp/parser/DefaultFTPFileEntryParserFactory.java
URL: http://svn.apache.org/viewvc/commons/proper/net/trunk/src/main/java/org/apache/commons/net/ftp/parser/DefaultFTPFileEntryParserFactory.java?rev=1227346&r1=1227345&r2=1227346&view=diff
==============================================================================
--- commons/proper/net/trunk/src/main/java/org/apache/commons/net/ftp/parser/DefaultFTPFileEntryParserFactory.java (original)
+++ commons/proper/net/trunk/src/main/java/org/apache/commons/net/ftp/parser/DefaultFTPFileEntryParserFactory.java Wed Jan 4 22:10:17 2012
@@ -149,6 +149,10 @@ public class DefaultFTPFileEntryParserFa
{
parser = new NetwareFTPEntryParser(config);
}
+ else if (ukey.indexOf(FTPClientConfig.SYST_MACOS_PETER) >= 0)
+ {
+ parser = new MacOsPeterFTPEntryParser(config);
+ }
else if (ukey.indexOf(FTPClientConfig.SYST_L8) >= 0)
{
// L8 normally means Unix, but move it to the end for some L8 systems that aren't.
Added: commons/proper/net/trunk/src/main/java/org/apache/commons/net/ftp/parser/MacOsPeterFTPEntryParser.java
URL: http://svn.apache.org/viewvc/commons/proper/net/trunk/src/main/java/org/apache/commons/net/ftp/parser/MacOsPeterFTPEntryParser.java?rev=1227346&view=auto
==============================================================================
--- commons/proper/net/trunk/src/main/java/org/apache/commons/net/ftp/parser/MacOsPeterFTPEntryParser.java (added)
+++ commons/proper/net/trunk/src/main/java/org/apache/commons/net/ftp/parser/MacOsPeterFTPEntryParser.java Wed Jan 4 22:10:17 2012
@@ -0,0 +1,278 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.ftp.parser;
+import java.text.ParseException;
+
+import org.apache.commons.net.ftp.FTPClientConfig;
+import org.apache.commons.net.ftp.FTPFile;
+
+/**
+ * Implementation FTPFileEntryParser and FTPFileListParser for pre MacOS-X Systems.
+ *
+ * @version $Id$
+ * @see org.apache.commons.net.ftp.FTPFileEntryParser FTPFileEntryParser (for usage instructions)
+ * @since 3.1
+ */
+public class MacOsPeterFTPEntryParser extends ConfigurableFTPFileEntryParserImpl
+{
+
+ static final String DEFAULT_DATE_FORMAT
+ = "MMM d yyyy"; //Nov 9 2001
+
+ static final String DEFAULT_RECENT_DATE_FORMAT
+ = "MMM d HH:mm"; //Nov 9 20:06
+
+ /**
+ * this is the regular expression used by this parser.
+ *
+ * Permissions:
+ * r the file is readable
+ * w the file is writable
+ * x the file is executable
+ * - the indicated permission is not granted
+ * L mandatory locking occurs during access (the set-group-ID bit is
+ * on and the group execution bit is off)
+ * s the set-user-ID or set-group-ID bit is on, and the corresponding
+ * user or group execution bit is also on
+ * S undefined bit-state (the set-user-ID bit is on and the user
+ * execution bit is off)
+ * t the 1000 (octal) bit, or sticky bit, is on [see chmod(1)], and
+ * execution is on
+ * T the 1000 bit is turned on, and execution is off (undefined bit-
+ * state)
+ * e z/OS external link bit
+ */
+ private static final String REGEX =
+ "([bcdelfmpSs-])" // type (1)
+ + "(((r|-)(w|-)([xsStTL-]))((r|-)(w|-)([xsStTL-]))((r|-)(w|-)([xsStTL-])))\\+?\\s+" // permission
+ + "("
+ + "(folder\\s+)"
+ + "|"
+ + "((\\d+)\\s+(\\d+)\\s+)" // resource size & data size
+ + ")"
+ + "(\\d+)\\s+" // size
+ /*
+ * numeric or standard format date:
+ * yyyy-mm-dd (expecting hh:mm to follow)
+ * MMM [d]d
+ * [d]d MMM
+ * N.B. use non-space for MMM to allow for languages such as German which use
+ * diacritics (e.g. umlaut) in some abbreviations.
+ */
+ + "((?:\\d+[-/]\\d+[-/]\\d+)|(?:\\S{3}\\s+\\d{1,2})|(?:\\d{1,2}\\s+\\S{3}))\\s+"
+ /*
+ year (for non-recent standard format) - yyyy
+ or time (for numeric or recent standard format) [h]h:mm
+ */
+ + "(\\d+(?::\\d+)?)\\s+"
+
+ + "(\\S*)(\\s*.*)"; // the rest
+
+
+ /**
+ * The default constructor for a UnixFTPEntryParser object.
+ *
+ * @exception IllegalArgumentException
+ * Thrown if the regular expression is unparseable. Should not be seen
+ * under normal conditions. It it is seen, this is a sign that
+ * <code>REGEX</code> is not a valid regular expression.
+ */
+ public MacOsPeterFTPEntryParser()
+ {
+ this(null);
+ }
+
+ /**
+ * This constructor allows the creation of a UnixFTPEntryParser object with
+ * something other than the default configuration.
+ *
+ * @param config The {@link FTPClientConfig configuration} object used to
+ * configure this parser.
+ * @exception IllegalArgumentException
+ * Thrown if the regular expression is unparseable. Should not be seen
+ * under normal conditions. It it is seen, this is a sign that
+ * <code>REGEX</code> is not a valid regular expression.
+ * @since 1.4
+ */
+ public MacOsPeterFTPEntryParser(FTPClientConfig config)
+ {
+ super(REGEX);
+ configure(config);
+ }
+
+ /**
+ * Parses a line of a unix (standard) FTP server file listing and converts
+ * it into a usable format in the form of an <code> FTPFile </code>
+ * instance. If the file listing line doesn't describe a file,
+ * <code> null </code> is returned, otherwise a <code> FTPFile </code>
+ * instance representing the files in the directory is returned.
+ * <p>
+ * @param entry A line of text from the file listing
+ * @return An FTPFile instance corresponding to the supplied entry
+ */
+ public FTPFile parseFTPEntry(String entry) {
+ FTPFile file = new FTPFile();
+ file.setRawListing(entry);
+ int type;
+ boolean isDevice = false;
+
+ if (matches(entry))
+ {
+ String typeStr = group(1);
+ String hardLinkCount = "0";
+ String usr = null;
+ String grp = null;
+ String filesize = group(20);
+ String datestr = group(21) + " " + group(22);
+ String name = group(23);
+ String endtoken = group(24);
+
+ try
+ {
+ file.setTimestamp(super.parseTimestamp(datestr));
+ }
+ catch (ParseException e)
+ {
+ // intentionally do nothing
+ }
+
+ // A 'whiteout' file is an ARTIFICIAL entry in any of several types of
+ // 'translucent' filesystems, of which a 'union' filesystem is one.
+
+ // bcdelfmpSs-
+ switch (typeStr.charAt(0))
+ {
+ case 'd':
+ type = FTPFile.DIRECTORY_TYPE;
+ break;
+ case 'e': // NET-39 => z/OS external link
+ type = FTPFile.SYMBOLIC_LINK_TYPE;
+ break;
+ case 'l':
+ type = FTPFile.SYMBOLIC_LINK_TYPE;
+ break;
+ case 'b':
+ case 'c':
+ isDevice = true;
+ // break; - fall through
+ //$FALL-THROUGH$ TODO change this if DEVICE_TYPE implemented
+ case 'f':
+ case '-':
+ type = FTPFile.FILE_TYPE;
+ break;
+ default: // e.g. ? and w = whiteout
+ type = FTPFile.UNKNOWN_TYPE;
+ }
+
+ file.setType(type);
+
+ int g = 4;
+ for (int access = 0; access < 3; access++, g += 4)
+ {
+ // Use != '-' to avoid having to check for suid and sticky bits
+ file.setPermission(access, FTPFile.READ_PERMISSION,
+ (!group(g).equals("-")));
+ file.setPermission(access, FTPFile.WRITE_PERMISSION,
+ (!group(g + 1).equals("-")));
+
+ String execPerm = group(g + 2);
+ if (!execPerm.equals("-") && !Character.isUpperCase(execPerm.charAt(0)))
+ {
+ file.setPermission(access, FTPFile.EXECUTE_PERMISSION, true);
+ }
+ else
+ {
+ file.setPermission(access, FTPFile.EXECUTE_PERMISSION, false);
+ }
+ }
+
+ if (!isDevice)
+ {
+ try
+ {
+ file.setHardLinkCount(Integer.parseInt(hardLinkCount));
+ }
+ catch (NumberFormatException e)
+ {
+ // intentionally do nothing
+ }
+ }
+
+ file.setUser(usr);
+ file.setGroup(grp);
+
+ try
+ {
+ file.setSize(Long.parseLong(filesize));
+ }
+ catch (NumberFormatException e)
+ {
+ // intentionally do nothing
+ }
+
+ if (null == endtoken)
+ {
+ file.setName(name);
+ }
+ else
+ {
+ // oddball cases like symbolic links, file names
+ // with spaces in them.
+ name += endtoken;
+ if (type == FTPFile.SYMBOLIC_LINK_TYPE)
+ {
+
+ int end = name.indexOf(" -> ");
+ // Give up if no link indicator is present
+ if (end == -1)
+ {
+ file.setName(name);
+ }
+ else
+ {
+ file.setName(name.substring(0, end));
+ file.setLink(name.substring(end + 4));
+ }
+
+ }
+ else
+ {
+ file.setName(name);
+ }
+ }
+ return file;
+ }
+ return null;
+ }
+
+ /**
+ * Defines a default configuration to be used when this class is
+ * instantiated without a {@link FTPClientConfig FTPClientConfig}
+ * parameter being specified.
+ * @return the default configuration for this parser.
+ */
+ @Override
+ protected FTPClientConfig getDefaultConfiguration() {
+ return new FTPClientConfig(
+ FTPClientConfig.SYST_UNIX,
+ DEFAULT_DATE_FORMAT,
+ DEFAULT_RECENT_DATE_FORMAT,
+ null, null, null);
+ }
+
+}
Propchange: commons/proper/net/trunk/src/main/java/org/apache/commons/net/ftp/parser/MacOsPeterFTPEntryParser.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: commons/proper/net/trunk/src/main/java/org/apache/commons/net/ftp/parser/MacOsPeterFTPEntryParser.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Modified: commons/proper/net/trunk/src/test/java/org/apache/commons/net/ftp/parser/DefaultFTPFileEntryParserFactoryTest.java
URL: http://svn.apache.org/viewvc/commons/proper/net/trunk/src/test/java/org/apache/commons/net/ftp/parser/DefaultFTPFileEntryParserFactoryTest.java?rev=1227346&r1=1227345&r2=1227346&view=diff
==============================================================================
--- commons/proper/net/trunk/src/test/java/org/apache/commons/net/ftp/parser/DefaultFTPFileEntryParserFactoryTest.java (original)
+++ commons/proper/net/trunk/src/test/java/org/apache/commons/net/ftp/parser/DefaultFTPFileEntryParserFactoryTest.java Wed Jan 4 22:10:17 2012
@@ -139,6 +139,7 @@ public class DefaultFTPFileEntryParserFa
checkParserClass(factory, FTPClientConfig.SYST_OS2, OS2FTPEntryParser.class);
checkParserClass(factory, FTPClientConfig.SYST_UNIX, UnixFTPEntryParser.class);
checkParserClass(factory, FTPClientConfig.SYST_VMS, VMSFTPEntryParser.class);
+ checkParserClass(factory, FTPClientConfig.SYST_MACOS_PETER, MacOsPeterFTPEntryParser.class);
checkParserClass(factory, "WINDOWS", NTFTPEntryParser.class); // Same as SYST_NT
// This is the way it works at present; config matching is exact
Added: commons/proper/net/trunk/src/test/java/org/apache/commons/net/ftp/parser/MacOsPeterFTPEntryParserTest.java
URL: http://svn.apache.org/viewvc/commons/proper/net/trunk/src/test/java/org/apache/commons/net/ftp/parser/MacOsPeterFTPEntryParserTest.java?rev=1227346&view=auto
==============================================================================
--- commons/proper/net/trunk/src/test/java/org/apache/commons/net/ftp/parser/MacOsPeterFTPEntryParserTest.java (added)
+++ commons/proper/net/trunk/src/test/java/org/apache/commons/net/ftp/parser/MacOsPeterFTPEntryParserTest.java Wed Jan 4 22:10:17 2012
@@ -0,0 +1,160 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.net.ftp.parser;
+
+import java.util.Calendar;
+
+import org.apache.commons.net.ftp.FTPFile;
+import org.apache.commons.net.ftp.FTPFileEntryParser;
+
+public class MacOsPeterFTPEntryParserTest extends FTPParseTestFramework {
+
+ private static final String[] badsamples = {
+ "drwxr-xr-x 123 folder 0 Jan 4 14:49 Steak",
+ };
+
+ private static final String[] goodsamples =
+ {
+ "-rw-r--r-- 54149 27826 81975 Jul 22 2010 09.jpg",
+ "drwxr-xr-x folder 0 Jan 4 14:51 Alias_to_Steak",
+ "-rw-r--r-- 78440 49231 127671 Jul 22 2010 Filename with whitespace.jpg",
+ "-rw-r--r-- 78440 49231 127671 Jul 22 14:51 Filename with whitespace.jpg",
+ "-rw-r--r-- 0 108767 108767 Jul 22 2010 presentation03.jpg",
+ "-rw-r--r-- 58679 60393 119072 Jul 22 2010 presentation04.jpg",
+ "-rw-r--r-- 82543 51433 133976 Jul 22 2010 presentation06.jpg",
+ "-rw-r--r-- 83616 1430976 1514592 Jul 22 2010 presentation10.jpg",
+ "-rw-r--r-- 0 66990 66990 Jul 22 2010 presentation11.jpg",
+ "drwxr-xr-x folder 0 Jan 4 14:49 Steak",
+ "-rwx------ 0 12713 12713 Jul 8 2009 Twitter_Avatar.png",
+ };
+
+ /**
+ * @see junit.framework.TestCase#TestCase(String)
+ */
+ public MacOsPeterFTPEntryParserTest(String name) {
+ super(name);
+ }
+
+ /**
+ * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getBadListing()
+ */
+ @Override
+ protected String[] getBadListing() {
+ return (badsamples);
+ }
+
+ /**
+ * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getGoodListing()
+ */
+ @Override
+ protected String[] getGoodListing() {
+ return (goodsamples);
+ }
+
+ @Override
+ protected FTPFileEntryParser getParser() {
+ return (new MacOsPeterFTPEntryParser());
+ }
+
+ @Override
+ public void testParseFieldsOnDirectory() throws Exception {
+ FTPFile f = getParser().parseFTPEntry(
+ "drwxr-xr-x folder 0 Mar 2 15:13 Alias_to_Steak");
+ assertNotNull("Could not parse entry.", f);
+ assertTrue("Should have been a directory.", f.isDirectory());
+ checkPermissions(f);
+ assertEquals(0, f.getHardLinkCount());
+ assertNull(f.getUser());
+ assertNull(f.getGroup());
+ assertEquals(0, f.getSize());
+ assertEquals("Alias_to_Steak", f.getName());
+
+ Calendar cal = Calendar.getInstance();
+ cal.set(Calendar.MONTH, Calendar.MARCH);
+
+ cal.set(Calendar.DATE, 1);
+ cal.set(Calendar.HOUR_OF_DAY, 0);
+ cal.set(Calendar.MINUTE, 0);
+ cal.set(Calendar.SECOND, 0);
+ if (f.getTimestamp().getTime().before(cal.getTime())) {
+ cal.add(Calendar.YEAR, -1);
+ }
+ cal.set(Calendar.DATE, 2);
+ cal.set(Calendar.HOUR_OF_DAY, 15);
+ cal.set(Calendar.MINUTE, 13);
+
+ assertEquals(df.format(cal.getTime()), df.format(f.getTimestamp()
+ .getTime()));
+ }
+
+ @Override
+ public void testParseFieldsOnFile() throws Exception {
+ FTPFile f = getParser().parseFTPEntry(
+ "-rwxr-xr-x 78440 49231 127671 Jul 2 14:51 Filename with whitespace.jpg"
+ );
+ assertNotNull("Could not parse entry.", f);
+ assertTrue("Should have been a file.", f.isFile());
+ checkPermissions(f);
+ assertEquals(0, f.getHardLinkCount());
+ assertNull(f.getUser());
+ assertNull(f.getGroup());
+ assertEquals("Filename with whitespace.jpg", f.getName());
+ assertEquals(127671L, f.getSize());
+
+ Calendar cal = Calendar.getInstance();
+ cal.set(Calendar.MONTH, Calendar.JULY);
+
+ cal.set(Calendar.DATE, 1);
+ cal.set(Calendar.HOUR_OF_DAY, 0);
+ cal.set(Calendar.MINUTE, 0);
+ cal.set(Calendar.SECOND, 0);
+ if (f.getTimestamp().getTime().before(cal.getTime())) {
+ cal.add(Calendar.YEAR, -1);
+ }
+ cal.set(Calendar.DATE, 2);
+ cal.set(Calendar.HOUR_OF_DAY, 14);
+ cal.set(Calendar.MINUTE, 51);
+ assertEquals(df.format(cal.getTime()), df.format(f.getTimestamp().getTime()));
+ }
+
+ /**
+ * Method checkPermissions.
+ * Verify that the persmissions were properly set.
+ * @param f
+ */
+ private void checkPermissions(FTPFile f) {
+ assertTrue("Should have user read permission.", f.hasPermission(
+ FTPFile.USER_ACCESS, FTPFile.READ_PERMISSION));
+ assertTrue("Should have user write permission.", f.hasPermission(
+ FTPFile.USER_ACCESS, FTPFile.WRITE_PERMISSION));
+ assertTrue("Should have user execute permission.", f.hasPermission(
+ FTPFile.USER_ACCESS, FTPFile.EXECUTE_PERMISSION));
+ assertTrue("Should have group read permission.", f.hasPermission(
+ FTPFile.GROUP_ACCESS, FTPFile.READ_PERMISSION));
+ assertTrue("Should NOT have group write permission.", !f.hasPermission(
+ FTPFile.GROUP_ACCESS, FTPFile.WRITE_PERMISSION));
+ assertTrue("Should have group execute permission.", f.hasPermission(
+ FTPFile.GROUP_ACCESS, FTPFile.EXECUTE_PERMISSION));
+ assertTrue("Should have world read permission.", f.hasPermission(
+ FTPFile.WORLD_ACCESS, FTPFile.READ_PERMISSION));
+ assertTrue("Should NOT have world write permission.", !f.hasPermission(
+ FTPFile.WORLD_ACCESS, FTPFile.WRITE_PERMISSION));
+ assertTrue("Should have world execute permission.", f.hasPermission(
+ FTPFile.WORLD_ACCESS, FTPFile.EXECUTE_PERMISSION));
+ }
+
+}
Propchange: commons/proper/net/trunk/src/test/java/org/apache/commons/net/ftp/parser/MacOsPeterFTPEntryParserTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: commons/proper/net/trunk/src/test/java/org/apache/commons/net/ftp/parser/MacOsPeterFTPEntryParserTest.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision