View Javadoc

    1   /*
    2    * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/java/org/apache/commons/httpclient/protocol/Protocol.java,v 1.10 2004/04/18 23:51:38 jsdever Exp $
    3    * $Revision: 480424 $
    4    * $Date: 2006-11-29 06:56:49 +0100 (Wed, 29 Nov 2006) $
    5    *
    6    * ====================================================================
    7    *
    8    *  Licensed to the Apache Software Foundation (ASF) under one or more
    9    *  contributor license agreements.  See the NOTICE file distributed with
    10   *  this work for additional information regarding copyright ownership.
    11   *  The ASF licenses this file to You under the Apache License, Version 2.0
    12   *  (the "License"); you may not use this file except in compliance with
    13   *  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, software
    18   *  distributed under the License is distributed on an "AS IS" BASIS,
    19   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    20   *  See the License for the specific language governing permissions and
    21   *  limitations under the License.
    22   * ====================================================================
    23   *
    24   * This software consists of voluntary contributions made by many
    25   * individuals on behalf of the Apache Software Foundation.  For more
    26   * information on the Apache Software Foundation, please see
    27   * <http://www.apache.org/>.
    28   *
    29   */
    30  package org.apache.commons.httpclient.protocol;
    31
    32  import java.util.Collections;
    33  import java.util.HashMap;
    34  import java.util.Map;
    35
    36  import org.apache.commons.httpclient.util.LangUtils;
    37
    38  /**
    39   * A class to encapsulate the specifics of a protocol.  This class class also
    40   * provides the ability to customize the set and characteristics of the
    41   * protocols used.
    42   *
    43   * <p>One use case for modifying the default set of protocols would be to set a
    44   * custom SSL socket factory.  This would look something like the following:
    45   * <pre>
    46   * Protocol myHTTPS = new Protocol( "https", new MySSLSocketFactory(), 443 );
    47   *
    48   * Protocol.registerProtocol( "https", myHTTPS );
    49   * </pre>
    50   *
    51   * @author Michael Becke
    52   * @author Jeff Dever
    53   * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
    54   *
    55   * @since 2.0
    56   */
    57  public class Protocol {
    58
    59      /** The available protocols */
    60      private static final Map PROTOCOLS = Collections.synchronizedMap(new HashMap());
    61
    62      /**
    63       * Registers a new protocol with the given identifier.  If a protocol with
    64       * the given ID already exists it will be overridden.  This ID is the same
    65       * one used to retrieve the protocol from getProtocol(String).
    66       *
    67       * @param id the identifier for this protocol
    68       * @param protocol the protocol to register
    69       *
    70       * @see #getProtocol(String)
    71       */
    72      public static void registerProtocol(String id, Protocol protocol) {
    73
    74          if (id == null) {
    75              throw new IllegalArgumentException("id is null");
    76          }
    77          if (protocol == null) {
    78              throw new IllegalArgumentException("protocol is null");
    79          }
    80
    81          PROTOCOLS.put(id, protocol);
    82      }
    83
    84      /**
    85       * Unregisters the protocol with the given ID.
    86       *
    87       * @param id the ID of the protocol to remove
    88       */
    89      public static void unregisterProtocol(String id) {
    90
    91          if (id == null) {
    92              throw new IllegalArgumentException("id is null");
    93          }
    94
    95          PROTOCOLS.remove(id);
    96      }
    97
    98      /**
    99       * Gets the protocol with the given ID.
    100      *
    101      * @param id the protocol ID
    102      *
    103      * @return Protocol a protocol
    104      *
    105      * @throws IllegalStateException if a protocol with the ID cannot be found
    106      */
    107     public static Protocol getProtocol(String id)
    108         throws IllegalStateException {
    109
    110         if (id == null) {
    111             throw new IllegalArgumentException("id is null");
    112         }
    113
    114         Protocol protocol = (Protocol) PROTOCOLS.get(id);
    115
    116         if (protocol == null) {
    117             protocol = lazyRegisterProtocol(id);
    118         }
    119
    120         return protocol;
    121     }
    122
    123     /**
    124      * Lazily registers the protocol with the given id.
    125      *
    126      * @param id the protocol ID
    127      *
    128      * @return the lazily registered protocol
    129      *
    130      * @throws IllegalStateException if the protocol with id is not recognized
    131      */
    132     private static Protocol lazyRegisterProtocol(String id)
    133         throws IllegalStateException {
    134
    135         if ("http".equals(id)) {
    136             final Protocol http
    137                 = new Protocol("http", DefaultProtocolSocketFactory.getSocketFactory(), 80);
    138             Protocol.registerProtocol("http", http);
    139             return http;
    140         }
    141
    142         if ("https".equals(id)) {
    143             final Protocol https
    144                 = new Protocol("https", SSLProtocolSocketFactory.getSocketFactory(), 443);
    145             Protocol.registerProtocol("https", https);
    146             return https;
    147         }
    148
    149         throw new IllegalStateException("unsupported protocol: '" + id + "'");
    150     }
    151
    152
    153     /** the scheme of this protocol (e.g. http, https) */
    154     private String scheme;
    155
    156     /** The socket factory for this protocol */
    157     private ProtocolSocketFactory socketFactory;
    158
    159     /** The default port for this protocol */
    160     private int defaultPort;
    161
    162     /** True if this protocol is secure */
    163     private boolean secure;
    164
    165     /**
    166      * Constructs a new Protocol. Whether the created protocol is secure depends on
    167      * the class of <code>factory</code>.
    168      *
    169      * @param scheme the scheme (e.g. http, https)
    170      * @param factory the factory for creating sockets for communication using
    171      * this protocol
    172      * @param defaultPort the port this protocol defaults to
    173      */
    174     public Protocol(String scheme, ProtocolSocketFactory factory, int defaultPort) {
    175
    176         if (scheme == null) {
    177             throw new IllegalArgumentException("scheme is null");
    178         }
    179         if (factory == null) {
    180             throw new IllegalArgumentException("socketFactory is null");
    181         }
    182         if (defaultPort <= 0) {
    183             throw new IllegalArgumentException("port is invalid: " + defaultPort);
    184         }
    185
    186         this.scheme = scheme;
    187         this.socketFactory = factory;
    188         this.defaultPort = defaultPort;
    189         this.secure = (factory instanceof SecureProtocolSocketFactory);
    190     }
    191
    192     /**
    193      * Constructs a new Protocol. Whether the created protocol is secure depends on
    194      * the class of <code>factory</code>.
    195      *
    196      * @param scheme the scheme (e.g. http, https)
    197      * @param factory the factory for creating sockets for communication using
    198      * this protocol
    199      * @param defaultPort the port this protocol defaults to
    200      * @deprecated Use the constructor that uses ProtocolSocketFactory, this version of
    201      * the constructor is only kept for backwards API compatibility.
    202      */
    203     public Protocol(String scheme,
    204         SecureProtocolSocketFactory factory, int defaultPort) {
    205         this(scheme, (ProtocolSocketFactory) factory, defaultPort);
    206     }
    207
    208     /**
    209      * Returns the defaultPort.
    210      * @return int
    211      */
    212     public int getDefaultPort() {
    213         return defaultPort;
    214     }
    215
    216     /**
    217      * Returns the socketFactory.  If secure the factory is a
    218      * SecureProtocolSocketFactory.
    219      * @return SocketFactory
    220      */
    221     public ProtocolSocketFactory getSocketFactory() {
    222         return socketFactory;
    223     }
    224
    225     /**
    226      * Returns the scheme.
    227      * @return The scheme
    228      */
    229     public String getScheme() {
    230         return scheme;
    231     }
    232
    233     /**
    234      * Returns true if this protocol is secure
    235      * @return true if this protocol is secure
    236      */
    237     public boolean isSecure() {
    238         return secure;
    239     }
    240
    241     /**
    242      * Resolves the correct port for this protocol.  Returns the given port if
    243      * valid or the default port otherwise.
    244      *
    245      * @param port the port to be resolved
    246      *
    247      * @return the given port or the defaultPort
    248      */
    249     public int resolvePort(int port) {
    250         return port <= 0 ? getDefaultPort() : port;
    251     }
    252
    253     /**
    254      * Return a string representation of this object.
    255      * @return a string representation of this object.
    256      */
    257     public String toString() {
    258         return scheme + ":" + defaultPort;
    259     }
    260
    261     /**
    262      * Return true if the specified object equals this object.
    263      * @param obj The object to compare against.
    264      * @return true if the objects are equal.
    265      */
    266     public boolean equals(Object obj) {
    267
    268         if (obj instanceof Protocol) {
    269
    270             Protocol p = (Protocol) obj;
    271
    272             return (
    273                 defaultPort == p.getDefaultPort()
    274                 && scheme.equalsIgnoreCase(p.getScheme())
    275                 && secure == p.isSecure()
    276                 && socketFactory.equals(p.getSocketFactory()));
    277
    278         } else {
    279             return false;
    280         }
    281
    282     }
    283
    284     /**
    285      * Return a hash code for this object
    286      * @return The hash code.
    287      */
    288     public int hashCode() {
    289         int hash = LangUtils.HASH_SEED;
    290         hash = LangUtils.hashCode(hash, this.defaultPort);
    291         hash = LangUtils.hashCode(hash, this.scheme.toLowerCase());
    292         hash = LangUtils.hashCode(hash, this.secure);
    293         hash = LangUtils.hashCode(hash, this.socketFactory);
    294         return hash;
    295     }
    296 }