Our Products:   CompleteFTP  edtFTPnet/Free  edtFTPnet/PRO  edtFTPj/Free  edtFTPj/PRO
0 votes
4.5k views
in Java FTP by (160 points)
Hi,

I run your library with my LGPL plugin for eclipse, I've selected yours because the API and design seems very nicely laid out.

I had one problem today, in that my locale is Spanish, but the server I want to connect and upload/download from, is english, so what was happening is this

in UnixFileParser.java you set the locale for the SimpleDateFormat objects to: Locale.getDefault()

which will return an object: new Locale("es","ES"), or similar

now, times on the server are in English, so the Month, for example, will be "Aug" for August, but in Spanish, August is Agosto, which means it cannot match a string with Aug in it, because it doesnt match any month in the locale settings.

The solution, was to override this with: new Locale("en","GB") and now the code runs perfectly.

I have a patch for this now, which chnges how you deal with the SimpleDateFormat objects, it makes the code a little simpler and works fine with my servers now, maybe someone else can test this out also. You can find it at the bottom of this posting

Thanks!

Chris

INSTRUCTIONS FOR PATCH
Cut and paste all the text between the <diff...> tags and paste it into a file called "UnixFileParser.diff" put it into the same directory as the original UnixFileParser.java and run "patch -p0 < UnixFileParser.diff" to make the updates, please backup the original file first, just in case something bad happens (tm)

<diff -> start here>
--- UnixFileParser.java 2007-08-06 15:05:58.000000000 +0200
+++ UnixFileParser.java.new 2007-08-06 15:17:10.000000000 +0200
@@ -85,6 +85,7 @@
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
+import java.util.Vector;

/**
* Represents a remote Unix file parser
@@ -120,34 +121,9 @@
private final static char DIRECTORY_CHAR = 'd';

/**
- * Date formatter 1 with no HH:mm
+ * The set of timeFormatter objects which shall be used to decode the date time's in the FTP results
*/
- private SimpleDateFormat noHHmmFormatter1;
-
- /**
- * Date formatter 2 with no HH:mm
- */
- private SimpleDateFormat noHHmmFormatter2;
-
- /**
- * Date formatter with no HH:mm
- */
- private SimpleDateFormat noHHmmFormatter;
-
- /**
- * Date formatter 1 with HH:mm
- */
- private SimpleDateFormat hhmmFormatter1;
-
- /**
- * Date formatter 2 with HH:mm
- */
- private SimpleDateFormat hhmmFormatter2;
-
- /**
- * Date formatter with HH:mm
- */
- private SimpleDateFormat hhmmFormatter;
+ protected Vector timeFormatter;

/**
* Minimum number of expected fields
@@ -158,6 +134,10 @@
* Constructor
*/
public UnixFileParser() {
+ timeFormatter = new Vector();
+
+ // Always put English at the top, because it's the most common
+ setLocale(new Locale("en","GB"));
setLocale(Locale.getDefault());
}

@@ -167,13 +147,11 @@
* @param locale locale to set
*/
public void setLocale(Locale locale) {
- noHHmmFormatter1 = new SimpleDateFormat("MMM-dd-yyyy", locale);
- noHHmmFormatter2 = new SimpleDateFormat("dd-MMM-yyyy", locale);
- noHHmmFormatter = noHHmmFormatter1;
- hhmmFormatter1 = new SimpleDateFormat("MMM-dd-yyyy-HH:mm", locale);
- hhmmFormatter2 = new SimpleDateFormat("dd-MMM-yyyy-HH:mm", locale);
- hhmmFormatter = hhmmFormatter1;
- }
+ timeFormatter.add(new SimpleDateFormat("MMM-dd-yyyy", locale));
+ timeFormatter.add(new SimpleDateFormat("dd-MMM-yyyy", locale));
+ timeFormatter.add(new SimpleDateFormat("MMM-dd-yyyy-HH:mm", locale));
+ timeFormatter.add(new SimpleDateFormat("dd-MMM-yyyy-HH:mm", locale));
+ }

/**
* Is this a Unix format listing?
@@ -267,31 +245,36 @@
stamp.append('-').append(fields[index++]).append('-');

String field = fields[index++];
- if (field.indexOf(':') < 0) {
- stamp.append(field); // year
- try {
- lastModified = noHHmmFormatter.parse(stamp.toString());
- }
- catch (ParseException ignore) {
- noHHmmFormatter = (noHHmmFormatter == noHHmmFormatter1 ? noHHmmFormatter2 : noHHmmFormatter1);
- lastModified = noHHmmFormatter.parse(stamp.toString());
- }
- }
- else { // add the year ourselves as not present
- Calendar cal = Calendar.getInstance();
- int year = cal.get(Calendar.YEAR);
- stamp.append(year).append('-').append(field);
- try {
- lastModified = hhmmFormatter.parse(stamp.toString());
- }
- catch (ParseException ignore) {
- hhmmFormatter = (hhmmFormatter == hhmmFormatter1 ? hhmmFormatter2 : hhmmFormatter1);
- lastModified = hhmmFormatter.parse(stamp.toString());
- }
-
- // can't be in the future - must be the previous year
- // add 2 days just to allow for different time zones
- cal.add(Calendar.DATE, 2);
+
+ boolean foundYear = false;
+ if(field.indexOf(':') < 0){
+ stamp.append(field); // year
+ foundYear = true;
+ }else{
+ Calendar cal = Calendar.getInstance();
+ int year = cal.get(Calendar.YEAR);
+ stamp.append(year).append('-').append(field);
+ }
+
+ for(int a=0;a<timeFormatter.size();a++){
+ SimpleDateFormat sdf = (SimpleDateFormat)timeFormatter.elementAt(a);
+
+ try{
+ lastModified = sdf.parse(stamp.toString());
+ break;
+ }catch(ParseException ignore){
+ // If you are on the last timeFormatter and you have STILL cannot parse the date, then pass the ParseException up the tree
+ // There is nothing more you can do.
+ System.out.println("Parse Attempt: "+a+", out of "+timeFormatter.size()+" attempts");
+ if(a == timeFormatter.size()-1) throw new ParseException(ignore.getMessage(), ignore.getErrorOffset());
+ }
+ }
+
+ // can't be in the future - must be the previous year
+ // add 2 days just to allow for different time zones
+ if(foundYear == true){
+ Calendar cal = Calendar.getInstance();
+ cal.add(Calendar.DATE, 2);
if (lastModified.after(cal.getTime())) {
cal.setTime(lastModified);
cal.add(Calendar.YEAR, -1);
@@ -350,4 +333,3 @@
return file;
}
}
-
<diff -> end here>

3 Answers

0 votes
by (162k points)
Thanks for your patch.

There is a method on FTPClient called setParserLocale() which should actually do what you want.
0 votes
by (160 points)
hey there,

the problem with that method is that sometimes your servers ARE in non-english locales, but sometimes they are not, it's safer I think, to ALWAYS have a set of SimpleDateFormat objects which are for english, THEN the ones you specify in addition and process your times through all of them

that way, you can catch the 99% of the time they are in english, with no extra cost, or code, plus the 1% of the time where it is in another locale.

the extra processing is miniscule.
0 votes
by (162k points)
Thanks, we're taking a close look at this.

Categories

...