1/* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements.  See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License.  You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package java.net;
17
18/**
19 * This class represents proxy server settings. A created instance of {@code
20 * Proxy} stores a type and an address and is immutable. There are three types
21 * of proxies:
22 * <ul>
23 * <li>DIRECT</li>
24 * <li>HTTP</li>
25 * <li>SOCKS</li></ul
26 */
27public class Proxy {
28
29    /**
30     * Represents the proxy type setting {@code Proxy.Type.DIRECT}. It tells
31     * protocol handlers that there is no proxy to be used. The address is set
32     * to {@code null}.
33     */
34    public static final Proxy NO_PROXY = new Proxy();
35
36    private Proxy.Type type;
37
38    private SocketAddress address;
39
40    /**
41     * Creates a new {@code Proxy} instance. {@code SocketAddress} must NOT be
42     * {@code null} when {@code type} is either {@code Proxy.Type.HTTP} or
43     * {@code Proxy.Type.SOCKS}. To create a {@code Proxy} instance representing
44     * the proxy type {@code Proxy.Type.DIRECT}, use {@code Proxy.NO_PROXY}
45     * instead of this constructor.
46     *
47     * @param type
48     *            the proxy type of this instance.
49     * @param sa
50     *            the proxy address of this instance.
51     * @throws IllegalArgumentException
52     *             if the parameter {@code type} is set to {@code
53     *             Proxy.Type.DIRECT} or the value for {@code SocketAddress} is
54     *             {@code null}.
55     */
56    public Proxy(Proxy.Type type, SocketAddress sa) {
57        /*
58         * Don't use DIRECT type to construct a proxy instance directly.
59         * SocketAddress must NOT be null.
60         */
61        if (type == Type.DIRECT || sa == null) {
62            throw new IllegalArgumentException("Illegal Proxy.Type or SocketAddress argument");
63        }
64        this.type = type;
65        address = sa;
66    }
67
68    /*
69     * Constructs a Proxy instance, which is Proxy.DIRECT type with null
70     * SocketAddress. This constructor is used for NO_PROXY.
71     */
72    private Proxy() {
73        type = Type.DIRECT;
74        address = null;
75    }
76
77    /**
78     * Gets the type of this {@code Proxy} instance.
79     *
80     * @return the stored proxy type.
81     */
82    public Proxy.Type type() {
83        return type;
84    }
85
86    /**
87     * Gets the address of this {@code Proxy} instance.
88     *
89     * @return the stored proxy address or {@code null} if the proxy type is
90     *         {@code DIRECT}.
91     */
92    public SocketAddress address() {
93        return address;
94    }
95
96    /**
97     * Gets a textual representation of this {@code Proxy} instance. The string
98     * includes the two parts {@code type.toString()} and {@code
99     * address.toString()} if {@code address} is not {@code null}.
100     *
101     * @return the representing string of this proxy.
102     */
103    @Override
104    public String toString() {
105        StringBuilder builder = new StringBuilder();
106        if (type != null) {
107            builder.append(type.toString());
108        }
109        builder.append("@");
110        if (type != Proxy.Type.DIRECT && address != null) {
111            builder.append(address.toString());
112        }
113        return builder.toString();
114    }
115
116    /**
117     * Compares the specified {@code obj} to this {@code Proxy} instance and
118     * returns whether they are equal or not. The given object must be an
119     * instance of {@code Proxy} with the same address and the same type value
120     * to be equal.
121     *
122     * @param obj
123     *            the object to compare with this instance.
124     * @return {@code true} if the given object represents the same {@code
125     *         Proxy} as this instance, {@code false} otherwise.
126     * @see #hashCode
127     */
128    @Override
129    public final boolean equals(Object obj) {
130        if (this == obj) {
131            return true;
132        }
133        if (!(obj instanceof Proxy)) {
134            return false;
135        }
136        Proxy another = (Proxy) obj;
137        // address is null when and only when it's NO_PROXY.
138        return (type == another.type) && address.equals(another.address);
139    }
140
141    /**
142     * Gets the hashcode for this {@code Proxy} instance.
143     *
144     * @return the hashcode value for this Proxy instance.
145     */
146    @Override
147    public final int hashCode() {
148        int ret = 0;
149        ret += type.hashCode();
150        if (address != null) {
151            ret += address.hashCode();
152        }
153        return ret;
154    }
155
156    /**
157     * {@code Enum} class for the proxy type. Possible options are {@code
158     * DIRECT}, {@code HTTP} and {@code SOCKS}.
159     */
160    public enum Type {
161        /**
162         * Direct connection. Connect without any proxy.
163         */
164        DIRECT,
165
166        /**
167         * HTTP type proxy. It's often used by protocol handlers such as HTTP,
168         * HTTPS and FTP.
169         */
170        HTTP,
171
172        /**
173         * SOCKS type proxy.
174         */
175        SOCKS
176    }
177}
178