• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/conn/scheme/Scheme.java $
3  * $Revision: 652950 $
4  * $Date: 2008-05-02 16:49:48 -0700 (Fri, 02 May 2008) $
5  *
6  * ====================================================================
7  * Licensed to the Apache Software Foundation (ASF) under one
8  * or more contributor license agreements.  See the NOTICE file
9  * distributed with this work for additional information
10  * regarding copyright ownership.  The ASF licenses this file
11  * to you under the Apache License, Version 2.0 (the
12  * "License"); you may not use this file except in compliance
13  * with the License.  You may obtain a copy of the License at
14  *
15  *   http://www.apache.org/licenses/LICENSE-2.0
16  *
17  * Unless required by applicable law or agreed to in writing,
18  * software distributed under the License is distributed on an
19  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
20  * KIND, either express or implied.  See the License for the
21  * specific language governing permissions and limitations
22  * under the License.
23  * ====================================================================
24  *
25  * This software consists of voluntary contributions made by many
26  * individuals on behalf of the Apache Software Foundation.  For more
27  * information on the Apache Software Foundation, please see
28  * <http://www.apache.org/>.
29  *
30  */
31 package org.apache.http.conn.scheme;
32 
33 import java.util.Locale;
34 
35 import org.apache.http.util.LangUtils;
36 
37 /**
38  * Encapsulates specifics of a protocol scheme such as "http" or "https".
39  * Schemes are identified by lowercase names.
40  * Supported schemes are typically collected in a
41  * {@link SchemeRegistry SchemeRegistry}.
42  *
43  * <p>
44  * For example, to configure support for "https://" URLs,
45  * you could write code like the following:
46  * </p>
47  * <pre>
48  * Scheme https = new Scheme("https", new MySecureSocketFactory(), 443);
49  * SchemeRegistry.DEFAULT.register(https);
50  * </pre>
51  *
52  * @author <a href="mailto:rolandw at apache.org">Roland Weber</a>
53  * @author Michael Becke
54  * @author Jeff Dever
55  * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
56  */
57 public final class Scheme {
58 
59     /** The name of this scheme, in lowercase. (e.g. http, https) */
60     private final String name;
61 
62     /** The socket factory for this scheme */
63     private final SocketFactory socketFactory;
64 
65     /** The default port for this scheme */
66     private final int defaultPort;
67 
68     /** Indicates whether this scheme allows for layered connections */
69     private final boolean layered;
70 
71 
72     /** A string representation, for {@link #toString toString}. */
73     private String stringRep;
74 
75 
76     /**
77      * Creates a new scheme.
78      * Whether the created scheme allows for layered connections
79      * depends on the class of <code>factory</code>.
80      *
81      * @param name      the scheme name, for example "http".
82      *                  The name will be converted to lowercase.
83      * @param factory   the factory for creating sockets for communication
84      *                  with this scheme
85      * @param port      the default port for this scheme
86      */
Scheme(final String name, final SocketFactory factory, final int port)87     public Scheme(final String name,
88                   final SocketFactory factory,
89                   final int port) {
90 
91         if (name == null) {
92             throw new IllegalArgumentException
93                 ("Scheme name may not be null");
94         }
95         if (factory == null) {
96             throw new IllegalArgumentException
97                 ("Socket factory may not be null");
98         }
99         if ((port <= 0) || (port > 0xffff)) {
100             throw new IllegalArgumentException
101                 ("Port is invalid: " + port);
102         }
103 
104         this.name = name.toLowerCase(Locale.ENGLISH);
105         this.socketFactory = factory;
106         this.defaultPort = port;
107         this.layered = (factory instanceof LayeredSocketFactory);
108     }
109 
110 
111     /**
112      * Obtains the default port.
113      *
114      * @return  the default port for this scheme
115      */
getDefaultPort()116     public final int getDefaultPort() {
117         return defaultPort;
118     }
119 
120 
121     /**
122      * Obtains the socket factory.
123      * If this scheme is {@link #isLayered layered}, the factory implements
124      * {@link LayeredSocketFactory LayeredSocketFactory}.
125      *
126      * @return  the socket factory for this scheme
127      */
getSocketFactory()128     public final SocketFactory getSocketFactory() {
129         return socketFactory;
130     }
131 
132 
133     /**
134      * Obtains the scheme name.
135      *
136      * @return  the name of this scheme, in lowercase
137      */
getName()138     public final String getName() {
139         return name;
140     }
141 
142 
143     /**
144      * Indicates whether this scheme allows for layered connections.
145      *
146      * @return <code>true</code> if layered connections are possible,
147      *         <code>false</code> otherwise
148      */
isLayered()149     public final boolean isLayered() {
150         return layered;
151     }
152 
153 
154     /**
155      * Resolves the correct port for this scheme.
156      * Returns the given port if it is valid, the default port otherwise.
157      *
158      * @param port      the port to be resolved,
159      *                  a negative number to obtain the default port
160      *
161      * @return the given port or the defaultPort
162      */
resolvePort(int port)163     public final int resolvePort(int port) {
164         return ((port <= 0) || (port > 0xffff)) ? defaultPort : port;
165     }
166 
167 
168     /**
169      * Return a string representation of this object.
170      *
171      * @return  a human-readable string description of this scheme
172      */
173     @Override
toString()174     public final String toString() {
175         if (stringRep == null) {
176             StringBuilder buffer = new StringBuilder();
177             buffer.append(this.name);
178             buffer.append(':');
179             buffer.append(Integer.toString(this.defaultPort));
180             stringRep = buffer.toString();
181         }
182         return stringRep;
183     }
184 
185 
186     /**
187      * Compares this scheme to an object.
188      *
189      * @param obj       the object to compare with
190      *
191      * @return  <code>true</code> iff the argument is equal to this scheme
192      */
193     @Override
equals(Object obj)194     public final boolean equals(Object obj) {
195         if (obj == null) return false;
196         if (this == obj) return true;
197         if (!(obj instanceof Scheme)) return false;
198 
199         Scheme s = (Scheme) obj;
200         return (name.equals(s.name) &&
201                 defaultPort == s.defaultPort &&
202                 layered == s.layered &&
203                 socketFactory.equals(s.socketFactory)
204                 );
205     } // equals
206 
207 
208     /**
209      * Obtains a hash code for this scheme.
210      *
211      * @return  the hash code
212      */
213     @Override
hashCode()214     public int hashCode() {
215         int hash = LangUtils.HASH_SEED;
216         hash = LangUtils.hashCode(hash, this.defaultPort);
217         hash = LangUtils.hashCode(hash, this.name);
218         hash = LangUtils.hashCode(hash, this.layered);
219         hash = LangUtils.hashCode(hash, this.socketFactory);
220         return hash;
221     }
222 
223 } // class Scheme
224