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 * https://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 package org.apache.commons.net.ftp;
18
19 import java.io.IOException;
20 import java.time.Duration;
21 import java.time.Instant;
22 import java.util.Calendar;
23 import java.util.TreeSet;
24
25 import junit.framework.TestCase;
26
27 /**
28 * This test was contributed in a different form by W. McDonald Buck of Boulder, Colorado, to help fix some bugs with the FTPClientConfig in a real world
29 * setting. It is a perfect functional test for the Time Zone functionality of FTPClientConfig.
30 *
31 * A publicly accessible FTP server at the US National Oceanographic and Atmospheric Adminstration houses a directory which contains 300 files, named sn.0000 to
32 * sn.0300. Every ten minutes or so the next file in sequence is rewritten with new data. Thus, the directory contains observations for more than 24 hours of
33 * data. Since the server has its clock set to GMT this is an excellent functional test for any machine in a different time zone.
34 *
35 * Noteworthy is the fact that the FTP routines in some web browsers don't work as well as this. They can't, since they have no way of knowing the server's time
36 * zone. Depending on the local machine's position relative to GMT and the time of day, the browsers may decide that a timestamp would be in the future if given
37 * the current year, so they assume the year to be last year. This illustrates the value of FTPClientConfig's time zone functionality.
38 */
39 public class FTPClientConfigFunctionalTest extends TestCase {
40
41 private final FTPClient ftpClient = new FTPClient();
42 private FTPClientConfig ftpClientConfig;
43
44 /**
45 */
46 public FTPClientConfigFunctionalTest() {
47
48 }
49
50 public FTPClientConfigFunctionalTest(final String arg0) {
51 super(arg0);
52 }
53
54 private TreeSet<FTPFile> getSortedSet(final FTPFile[] files) {
55 // create a TreeSet which will sort each element
56 // as it is added.
57 final TreeSet<FTPFile> sorted = new TreeSet<>((o1, o2) -> o1.getTimestamp().getTime().compareTo(o2.getTimestamp().getTime()));
58
59 for (final FTPFile file : files) {
60 // The directory contains a few additional files at the beginning
61 // which aren't in the series we want. The series we want consists
62 // of files named sn.dddd. This adjusts the file list to get rid
63 // of the uninteresting ones.
64 if (file.getName().startsWith("sn")) {
65 sorted.add(file);
66 }
67 }
68 return sorted;
69 }
70
71 /**
72 * @throws Exception
73 */
74 @Override
75 protected void setUp() throws Exception {
76 super.setUp();
77 ftpClientConfig = new FTPClientConfig(FTPClientConfig.SYST_UNIX);
78 ftpClientConfig.setServerTimeZoneId("GMT");
79 ftpClient.configure(ftpClientConfig);
80 try {
81 ftpClient.connect("tgftp.nws.noaa.gov");
82 ftpClient.login("anonymous", "testing@apache.org");
83 ftpClient.changeWorkingDirectory("SL.us008001/DF.an/DC.sflnd/DS.metar");
84 ftpClient.enterLocalPassiveMode();
85 } catch (final IOException e) {
86 e.printStackTrace();
87 }
88 }
89
90 /**
91 * @throws Exception
92 */
93 @Override
94 protected void tearDown() throws Exception {
95 ftpClient.disconnect();
96 super.tearDown();
97 }
98
99 public void testTimeZoneFunctionality() throws Exception {
100 final java.util.Date nowDate = new java.util.Date();
101 final Instant nowInstant = nowDate.toInstant();
102 final FTPFile[] files = ftpClient.listFiles();
103 final TreeSet<FTPFile> sortedSet = getSortedSet(files);
104 // SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy HH:mm z" );
105 FTPFile lastFile = null;
106 FTPFile firstFile = null;
107 for (final FTPFile thisFile : sortedSet) {
108 if (firstFile == null) {
109 firstFile = thisFile;
110 }
111 // System.out.println(sdf.format(thisFile.getTimestamp().getTime())
112 // + " " +thisFile.getName());
113 if (lastFile != null) {
114 // verify that the list is sorted earliest to latest.
115 assertTrue(lastFile.getTimestamp().before(thisFile.getTimestamp()));
116 assertTrue(lastFile.getTimestampInstant().isBefore(thisFile.getTimestampInstant()));
117 }
118 lastFile = thisFile;
119 }
120
121 if (firstFile == null || lastFile == null) {
122 fail("No files found");
123 } else {
124 // test that notwithstanding any time zone differences, the newest file
125 // is older than now.
126 assertTrue(lastFile.getTimestamp().getTime().before(nowDate));
127 assertTrue(lastFile.getTimestampInstant().isBefore(nowInstant));
128 final Calendar firstCal = firstFile.getTimestamp();
129 final Instant firstInstant = firstFile.getTimestampInstant().plus(Duration.ofDays(2));
130
131 // test that the oldest is less than two days older than the newest
132 // and, in particular, that no files have been considered "future"
133 // by the parser and therefore been relegated to the same date a
134 // year ago.
135 firstCal.add(Calendar.DAY_OF_MONTH, 2);
136 assertTrue(lastFile.getTimestamp().getTime() + " before " + firstCal.getTime(), lastFile.getTimestamp().before(firstCal));
137 assertTrue(lastFile.getTimestampInstant() + " before " + firstInstant, lastFile.getTimestampInstant().isBefore(firstInstant));
138 }
139 }
140 }