Home | History | Annotate | Download | only in scheme
      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 (at) 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      */
     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      */
    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      */
    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      */
    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      */
    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      */
    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
    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
    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
    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