package org.chenyang.http.impl.client;

import org.chenyang.commons.logging.Log;
import org.chenyang.commons.logging.LogFactory;
import org.chenyang.http.HttpHost;
import org.chenyang.http.annotation.Contract;
import org.chenyang.http.annotation.ThreadingBehavior;
import org.chenyang.http.auth.AuthScheme;
import org.chenyang.http.client.AuthCache;
import org.chenyang.http.conn.SchemePortResolver;
import org.chenyang.http.conn.UnsupportedSchemeException;
import org.chenyang.http.impl.conn.DefaultSchemePortResolver;
import org.chenyang.http.util.Args;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Contract(
   threading = ThreadingBehavior.SAFE
)
public class BasicAuthCache implements AuthCache {
   private final Log log;
   private final Map<HttpHost, byte[]> map;
   private final SchemePortResolver schemePortResolver;

   public BasicAuthCache(SchemePortResolver schemePortResolver) {
      this.log = LogFactory.getLog(this.getClass());
      this.map = new ConcurrentHashMap();
      this.schemePortResolver = (SchemePortResolver)(schemePortResolver != null ? schemePortResolver : DefaultSchemePortResolver.INSTANCE);
   }

   public BasicAuthCache() {
      this((SchemePortResolver)null);
   }

   protected HttpHost getKey(HttpHost host) {
      if (host.getPort() <= 0) {
         int port;
         try {
            port = this.schemePortResolver.resolve(host);
         } catch (UnsupportedSchemeException var4) {
            return host;
         }

         return new HttpHost(host.getHostName(), port, host.getSchemeName());
      } else {
         return host;
      }
   }

   public void put(HttpHost host, AuthScheme authScheme) {
      Args.notNull(host, "HTTP host");
      if (authScheme != null) {
         if (authScheme instanceof Serializable) {
            try {
               ByteArrayOutputStream buf = new ByteArrayOutputStream();
               ObjectOutputStream out = new ObjectOutputStream(buf);
               out.writeObject(authScheme);
               out.close();
               this.map.put(this.getKey(host), buf.toByteArray());
            } catch (IOException ex) {
               if (this.log.isWarnEnabled()) {
                  this.log.warn("Unexpected I/O error while serializing auth scheme", ex);
               }
            }
         } else if (this.log.isDebugEnabled()) {
            this.log.debug("Auth scheme " + authScheme.getClass() + " is not serializable");
         }

      }
   }

   public AuthScheme get(HttpHost host) {
      Args.notNull(host, "HTTP host");
      byte[] bytes = (byte[])this.map.get(this.getKey(host));
      if (bytes != null) {
         try {
            ByteArrayInputStream buf = new ByteArrayInputStream(bytes);
            ObjectInputStream in = new ObjectInputStream(buf);
            AuthScheme authScheme = (AuthScheme)in.readObject();
            in.close();
            return authScheme;
         } catch (IOException ex) {
            if (this.log.isWarnEnabled()) {
               this.log.warn("Unexpected I/O error while de-serializing auth scheme", ex);
            }

            return null;
         } catch (ClassNotFoundException ex) {
            if (this.log.isWarnEnabled()) {
               this.log.warn("Unexpected error while de-serializing auth scheme", ex);
            }

            return null;
         }
      } else {
         return null;
      }
   }

   public void remove(HttpHost host) {
      Args.notNull(host, "HTTP host");
      this.map.remove(this.getKey(host));
   }

   public void clear() {
      this.map.clear();
   }

   public String toString() {
      return this.map.toString();
   }
}
