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
18package tests.support;
19
20import java.net.DatagramSocket;
21import java.net.ServerSocket;
22import java.util.Calendar;
23import java.util.TimeZone;
24
25/**
26 * The port manager is supposed to help finding a free
27 * network port on the machine; however, it uses strange
28 * logic, so leave it to the OS.
29 *
30 * @deprecated Use OS to find free ports.
31 */
32public class Support_PortManager {
33
34    private static int lastAssignedPort = somewhatRandomPort();
35    private static boolean failedOnce = false;
36
37    public static synchronized int getNextPort() {
38        if (!failedOnce) {
39            try {
40                ServerSocket ss = new ServerSocket(0);
41                int port = ss.getLocalPort();
42
43                ss.close();
44                return port;
45            } catch (Exception ex) {
46                failedOnce = true;
47            }
48        }
49        return getNextPort_unsafe();
50    }
51
52    /**
53     * Returns 1 free ports to be used.
54     */
55    public static synchronized int getNextPortForUDP() {
56        return getNextPortsForUDP(1)[0];
57    }
58
59    /**
60     * Returns the specified number of free ports to be used.
61     */
62    public static synchronized int[] getNextPortsForUDP(int num) {
63        if (num <= 0) {
64            throw new IllegalArgumentException("Invalid ports number: " + num);
65        }
66        DatagramSocket[] dss = new DatagramSocket[num];
67        int[] ports = new int[num];
68
69        try {
70            for (int i = 0; i < num; ++i) {
71                dss[i] = new DatagramSocket(0);
72                ports[i] = dss[i].getLocalPort();
73            }
74        } catch (Exception ex) {
75            throw new Error("Unable to get " + num + " ports for UDP: " + ex);
76        } finally {
77            for (int i = 0; i < num; ++i) {
78                if (dss[i] != null) {
79                    dss[i].close();
80                }
81            }
82        }
83        return ports;
84    }
85
86    public static synchronized int getNextPort_unsafe() {
87        if (++lastAssignedPort > 65534) {
88            lastAssignedPort = 6000;
89        }
90        return lastAssignedPort;
91    }
92
93    /*
94      * Returns a different port number every 6 seconds or so. The port number
95      * should be about += 100 at each 6 second interval
96      */
97    private static int somewhatRandomPort() {
98        Calendar c = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
99        int minutes = c.get(Calendar.MINUTE);
100        int seconds = c.get(Calendar.SECOND);
101
102        return 6000 + (1000 * minutes) + ((seconds / 6) * 100);
103    }
104
105}
106