View Javadoc
1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  package org.apache.http.impl.client;
28  
29  import java.io.ByteArrayInputStream;
30  import java.io.ByteArrayOutputStream;
31  import java.io.IOException;
32  import java.io.ObjectInputStream;
33  import java.io.ObjectOutputStream;
34  import java.io.Serializable;
35  import java.util.Map;
36  import java.util.concurrent.ConcurrentHashMap;
37  
38  import org.apache.commons.logging.Log;
39  import org.apache.commons.logging.LogFactory;
40  import org.apache.http.HttpHost;
41  import org.apache.http.annotation.Contract;
42  import org.apache.http.annotation.ThreadingBehavior;
43  import org.apache.http.auth.AuthScheme;
44  import org.apache.http.client.AuthCache;
45  import org.apache.http.conn.SchemePortResolver;
46  import org.apache.http.conn.UnsupportedSchemeException;
47  import org.apache.http.impl.conn.DefaultSchemePortResolver;
48  import org.apache.http.util.Args;
49  
50  /**
51   * Default implementation of {@link org.apache.http.client.AuthCache}. This implements
52   * expects {@link org.apache.http.auth.AuthScheme} to be {@link java.io.Serializable}
53   * in order to be cacheable.
54   * <p>
55   * Instances of this class are thread safe as of version 4.4.
56   * </p>
57   *
58   * @since 4.1
59   */
60  @Contract(threading = ThreadingBehavior.SAFE)
61  public class BasicAuthCache implements AuthCache {
62  
63      private final Log log = LogFactory.getLog(getClass());
64  
65      private final Map<HttpHost, byte[]> map;
66      private final SchemePortResolver schemePortResolver;
67  
68      /**
69       * Default constructor.
70       *
71       * @since 4.3
72       */
73      public BasicAuthCache(final SchemePortResolver schemePortResolver) {
74          super();
75          this.map = new ConcurrentHashMap<HttpHost, byte[]>();
76          this.schemePortResolver = schemePortResolver != null ? schemePortResolver :
77              DefaultSchemePortResolver.INSTANCE;
78      }
79  
80      public BasicAuthCache() {
81          this(null);
82      }
83  
84      protected HttpHost getKey(final HttpHost host) {
85          if (host.getPort() <= 0) {
86              final int port;
87              try {
88                  port = schemePortResolver.resolve(host);
89              } catch (final UnsupportedSchemeException ignore) {
90                  return host;
91              }
92              return new HttpHost(host.getHostName(), port, host.getSchemeName());
93          } else {
94              return host;
95          }
96      }
97  
98      @Override
99      public void put(final HttpHost host, final AuthScheme authScheme) {
100         Args.notNull(host, "HTTP host");
101         if (authScheme == null) {
102             return;
103         }
104         if (authScheme instanceof Serializable) {
105             try {
106                 final ByteArrayOutputStream buf = new ByteArrayOutputStream();
107                 final ObjectOutputStream out = new ObjectOutputStream(buf);
108                 out.writeObject(authScheme);
109                 out.close();
110                 this.map.put(getKey(host), buf.toByteArray());
111             } catch (final IOException ex) {
112                 if (log.isWarnEnabled()) {
113                     log.warn("Unexpected I/O error while serializing auth scheme", ex);
114                 }
115             }
116         } else {
117             if (log.isDebugEnabled()) {
118                 log.debug("Auth scheme " + authScheme.getClass() + " is not serializable");
119             }
120         }
121     }
122 
123     @Override
124     public AuthScheme get(final HttpHost host) {
125         Args.notNull(host, "HTTP host");
126         final byte[] bytes = this.map.get(getKey(host));
127         if (bytes != null) {
128             try {
129                 final ByteArrayInputStream buf = new ByteArrayInputStream(bytes);
130                 final ObjectInputStream in = new ObjectInputStream(buf);
131                 final AuthScheme authScheme = (AuthScheme) in.readObject();
132                 in.close();
133                 return authScheme;
134             } catch (final IOException ex) {
135                 if (log.isWarnEnabled()) {
136                     log.warn("Unexpected I/O error while de-serializing auth scheme", ex);
137                 }
138                 return null;
139             } catch (final ClassNotFoundException ex) {
140                 if (log.isWarnEnabled()) {
141                     log.warn("Unexpected error while de-serializing auth scheme", ex);
142                 }
143                 return null;
144             }
145         } else {
146             return null;
147         }
148     }
149 
150     @Override
151     public void remove(final HttpHost host) {
152         Args.notNull(host, "HTTP host");
153         this.map.remove(getKey(host));
154     }
155 
156     @Override
157     public void clear() {
158         this.map.clear();
159     }
160 
161     @Override
162     public String toString() {
163         return this.map.toString();
164     }
165 
166 }