1/*
2 * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24/*
25 * @test
26 * @bug 7167293
27 * @summary FtpURLConnection doesn't close FTP connection when FileNotFoundException is thrown
28 * @library ../www/ftptest/
29 * @build FtpServer FtpCommandHandler FtpAuthHandler FtpFileSystemHandler
30 * @run main FtpURLConnectionLeak
31 */
32import java.io.FileNotFoundException;
33import java.io.IOException;
34import java.io.InputStream;
35import java.io.OutputStream;
36import java.net.URL;
37
38public class FtpURLConnectionLeak {
39
40    public static void main(String[] args) throws Exception {
41        FtpServer server = new FtpServer(0);
42        server.setFileSystemHandler(new CustomFileSystemHandler("/"));
43        server.setAuthHandler(new MyAuthHandler());
44        int port = server.getLocalPort();
45        server.start();
46        URL url = new URL("ftp://localhost:" + port + "/filedoesNotExist.txt");
47        for (int i = 0; i < 3; i++) {
48            try {
49                InputStream stream = url.openStream();
50            } catch (FileNotFoundException expectedFirstTimeAround) {
51                // should always reach this point since the path does not exist
52            } catch (IOException expected) {
53                System.out.println("caught expected " + expected);
54                int times = 1;
55                do {
56                    // give some time to close the connection...
57                    System.out.println("sleeping... " + times);
58                    Thread.sleep(times * 1000);
59                } while (server.activeClientsCount() > 0 && times++ < 5);
60
61                if (server.activeClientsCount() > 0) {
62                    server.killClients();
63                    throw new RuntimeException("URLConnection didn't close the" +
64                            " FTP connection on FileNotFoundException");
65                }
66            } finally {
67                server.terminate();
68            }
69        }
70    }
71
72    static class CustomFileSystemHandler implements FtpFileSystemHandler {
73
74        private String currentDir;
75
76        public CustomFileSystemHandler(String path) {
77            currentDir = path;
78        }
79
80        @Override
81        public boolean cd(String path) {
82            currentDir = path;
83            return true;
84        }
85
86        @Override
87        public boolean cdUp() {
88            throw new UnsupportedOperationException("Not supported yet.");
89        }
90
91        @Override
92        public String pwd() {
93            throw new UnsupportedOperationException("Not supported yet.");
94        }
95
96        @Override
97        public boolean fileExists(String name) {
98            throw new UnsupportedOperationException("Not supported yet.");
99        }
100
101        @Override
102        public InputStream getFile(String name) {
103            return null; //return null so that server will return 550 File not found.
104        }
105
106        @Override
107        public long getFileSize(String name) {
108            throw new UnsupportedOperationException("Not supported yet.");
109        }
110
111        @Override
112        public InputStream listCurrentDir() {
113            return null;
114        }
115
116        @Override
117        public OutputStream putFile(String name) {
118            throw new UnsupportedOperationException("Not supported yet.");
119        }
120
121        @Override
122        public boolean removeFile(String name) {
123            throw new UnsupportedOperationException("Not supported yet.");
124        }
125
126        @Override
127        public boolean mkdir(String name) {
128            throw new UnsupportedOperationException("Not supported yet.");
129        }
130
131        @Override
132        public boolean rename(String from, String to) {
133            throw new UnsupportedOperationException("Not supported yet.");
134        }
135
136    }
137
138    static class MyAuthHandler implements FtpAuthHandler {
139
140        @Override
141        public int authType() {
142            return 0;
143        }
144
145        @Override
146        public boolean authenticate(String user, String password) {
147            return true;
148        }
149
150        @Override
151        public boolean authenticate(String user, String password, String account) {
152            return true;
153        }
154    }
155}
156