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  
19  package org.apache.commons.net.ftp.parser;
20  
21  import java.io.File;
22  import java.io.FileInputStream;
23  import java.io.FilenameFilter;
24  import java.io.InputStream;
25  import java.util.Arrays;
26  import java.util.Calendar;
27  import java.util.Comparator;
28  import java.util.TimeZone;
29  
30  import org.apache.commons.net.ftp.FTP;
31  import org.apache.commons.net.ftp.FTPClientConfig;
32  import org.apache.commons.net.ftp.FTPFile;
33  import org.apache.commons.net.ftp.FTPFileFilters;
34  import org.apache.commons.net.ftp.FTPListParseEngine;
35  
36  import org.junit.Test;
37  
38  /**
39   * Attempt comparison of LIST and MLSD listings
40   *
41   * TODO - needs some work.
42   */
43  public class MLSDComparison {
44  
45      private final Comparator<FTPFile> cmp = new Comparator<FTPFile>() {
46  //        @Override
47          public int compare(FTPFile o1, FTPFile o2) {
48                  String n1 = o1.getName();
49                  String n2 = o2.getName();
50                  return n1.compareTo(n2);
51              }
52      };
53  
54      @Test
55      public void testFile() throws Exception{
56          File path = new File(DownloadListings.DOWNLOAD_DIR);
57          FilenameFilter filter = new FilenameFilter(){
58  //            @Override
59              public boolean accept(File dir, String name) {
60                  return name.endsWith("_mlsd.txt");
61              }
62  
63          };
64          for (File mlsd : path.listFiles(filter)){
65              System.out.println(mlsd);
66              InputStream is = new FileInputStream(mlsd);
67              FTPListParseEngine engine = new FTPListParseEngine(MLSxEntryParser.getInstance());
68              engine.readServerList(is, FTP.DEFAULT_CONTROL_ENCODING);
69              FTPFile [] mlsds = engine.getFiles(FTPFileFilters.ALL);
70              is.close();
71              File list = new File(mlsd.getParentFile(),mlsd.getName().replace("_mlsd", "_list"));
72  
73              System.out.println(list);
74              is = new FileInputStream(list);
75              FTPClientConfig cfg = new FTPClientConfig();
76              cfg.setServerTimeZoneId("GMT");
77              UnixFTPEntryParser parser = new UnixFTPEntryParser(cfg);
78              engine = new FTPListParseEngine(parser);
79              engine.readServerList(is, FTP.DEFAULT_CONTROL_ENCODING);
80              FTPFile [] lists = engine.getFiles(FTPFileFilters.ALL);
81              is.close();
82              compareSortedLists(mlsds, lists);
83          }
84      }
85  
86      private void compareSortedLists(FTPFile[] lst, FTPFile[] mlst){
87          Arrays.sort(lst, cmp );
88          Arrays.sort(mlst, cmp );
89          FTPFile first, second;
90          int firstl=lst.length;
91          int secondl=mlst.length;
92          int one=0, two=0;
93          first = lst[one++];
94          second = mlst[two++];
95          int cmp;
96          while (one < firstl || two < secondl) {
97  //            String fs1 = first.toFormattedString();
98  //            String fs2 = second.toFormattedString();
99              String rl1 = first.getRawListing();
100             String rl2 = second.getRawListing();
101             cmp = first.getName().compareTo(second.getName());
102             if (cmp == 0) {
103                 if (first.getName().endsWith("HEADER.html")){
104                     cmp = 0;
105                 }
106                 if (!areEquivalent(first, second)){
107 //                    System.out.println(rl1);
108 //                    System.out.println(fs1);
109                     long tdiff = first.getTimestamp().getTimeInMillis()-second.getTimestamp().getTimeInMillis();
110                     System.out.println("Minutes diff "+tdiff/(1000*60));
111 //                    System.out.println(fs2);
112 //                    System.out.println(rl2);
113 //                    System.out.println();
114 //                    fail();
115                 }
116                 if (one < firstl) {
117                     first = lst[one++];
118                 }
119                 if (two < secondl) {
120                     second = mlst[two++];
121                 }
122             } else if (cmp < 0) {
123                 if (!first.getName().startsWith(".")) { // skip hidden files
124                     System.out.println("1: "+rl1);
125                 }
126                 if (one < firstl) {
127                     first = lst[one++];
128                 }
129             } else {
130                 System.out.println("2: "+rl2);
131                 if (two < secondl) {
132                     second = mlst[two++];
133                 }
134             }
135         }
136     }
137     /**
138      * Compare two instances to see if they are the same,
139      * ignoring any uninitialised fields.
140      *
141      * @param b
142      * @return true if the initialised fields are the same
143      * @since 3.0
144      */
145     public boolean areEquivalent(FTPFile a, FTPFile b) {
146         return
147             a.getName().equals(b.getName()) &&
148             areSame(a.getSize(), b.getSize(), -1L) &&
149 //            areSame(a.getUser(), b.getUser()) &&
150 //            areSame(a.getGroup(), b.getGroup()) &&
151             areSame(a.getTimestamp(), b.getTimestamp()) &&
152 //            areSame(a.getType(), b.getType(), UNKNOWN_TYPE) &&
153 //            areSame(a.getHardLinkCount(), b.getHardLinkCount(), 0) &&
154 //            areSame(a._permissions, b._permissions)
155             true
156             ;
157     }
158 
159     // compare permissions: default is all false, but that is also a possible
160     // state, so this may miss some differences
161 //    private boolean areSame(boolean[][] a, boolean[][] b) {
162 //        return isDefault(a) || isDefault(b) || Arrays.deepEquals(a, b);
163 //    }
164 
165     // Is the array in its default state?
166 //    private boolean isDefault(boolean[][] a) {
167 //        for(boolean[] r : a){
168 //            for(boolean rc : r){
169 //                if (rc) { // not default
170 //                    return false;
171 //                }
172 //            }
173 //        }
174 //        return true;
175 //    }
176 
177 
178     private boolean areSame(Calendar a, Calendar b) {
179         return a == null || b == null || areSameDateTime(a, b);
180     }
181 
182     private boolean areSameDateTime(Calendar a, Calendar b) {
183         TimeZone UTC = TimeZone.getTimeZone("UTC");
184         Calendar ac = Calendar.getInstance(UTC);
185         ac.setTime(a.getTime());
186         Calendar bc = Calendar.getInstance(UTC);
187         bc.setTime(b.getTime());
188         return isSameDay(ac, bc) && isSameTime(ac, bc);
189     }
190 
191     private boolean isSameDay(Calendar a, Calendar b) {
192         int ad = a.get(Calendar.DAY_OF_MONTH);
193         int bd = b.get(Calendar.DAY_OF_MONTH);
194         return
195             a.get(Calendar.YEAR) == b.get(Calendar.YEAR) &&
196             a.get(Calendar.MONTH) == b.get(Calendar.MONTH) &&
197             ad == bd
198             ;
199     }
200     private boolean isSameTime(Calendar a, Calendar b) {
201         int ah = a.get(Calendar.HOUR_OF_DAY);
202         int bh = b.get(Calendar.HOUR_OF_DAY);
203         int am = a.get(Calendar.MINUTE);
204         int bm = b.get(Calendar.MINUTE);
205         int as = a.get(Calendar.SECOND);
206         int bs = b.get(Calendar.SECOND);
207         return
208             (ah == 0 && am == 0 && as ==0) ||
209             (bh == 0 && bm == 0 && bs ==0) ||
210             (ah == bh && am == bm) // ignore seconds
211             ;
212     }
213 
214 
215     private boolean areSame(long a, long b, long d) {
216         return a == d || b == d || a == b;
217     }
218 
219 //    private boolean areSame(int a, int b, int d) {
220 //        return a == d || b == d || a == b;
221 //    }
222 //
223 //    private boolean areSame(String a, String b) {
224 //        return a.length() == 0 || b.length() == 0 || a.equals(b);
225 //    }
226 }