1 /*
   2  * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Sun designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Sun in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  22  * CA 95054 USA or visit www.sun.com if you need additional information or
  23  * have any questions.
  24  */
  25 package sun.net.www.protocol.http;
  26 
  27 import java.net.URL;
  28 import java.net.PasswordAuthentication;
  29 import java.lang.reflect.Constructor;
  30 import java.lang.reflect.Method;
  31 import sun.util.logging.PlatformLogger;
  32 
  33 /**
  34  * Proxy class for loading NTLMAuthentication, so as to remove static
  35  * dependancy.
  36  */
  37 class NTLMAuthenticationProxy {
  38     private static Method supportsTA;
  39     private static final String clazzStr = "sun.net.www.protocol.http.ntlm.NTLMAuthentication";
  40     private static final String supportsTAStr = "supportsTransparentAuth";
  41 
  42     static final NTLMAuthenticationProxy proxy = tryLoadNTLMAuthentication();
  43     static final boolean supported = proxy != null ? true : false;
  44     static final boolean supportsTransparentAuth = supported ? supportsTransparentAuth(supportsTA) : false;
  45 
  46     private final Constructor<? extends AuthenticationInfo> threeArgCtr;
  47     private final Constructor<? extends AuthenticationInfo> fiveArgCtr;
  48 
  49     private NTLMAuthenticationProxy(Constructor<? extends AuthenticationInfo> threeArgCtr,
  50                                     Constructor<? extends AuthenticationInfo> fiveArgCtr) {
  51         this.threeArgCtr = threeArgCtr;
  52         this.fiveArgCtr = fiveArgCtr;
  53     }
  54 
  55 
  56     AuthenticationInfo create(boolean isProxy,
  57                               URL url,
  58                               PasswordAuthentication pw) {
  59         try {
  60             return threeArgCtr.newInstance(isProxy, url, pw);
  61         } catch (ReflectiveOperationException roe) {
  62             finest(roe);
  63         }
  64 
  65         return null;
  66     }
  67 
  68     AuthenticationInfo create(boolean isProxy,
  69                               String host,
  70                               int port,
  71                               PasswordAuthentication pw) {
  72         try {
  73             return fiveArgCtr.newInstance(isProxy, host, port, pw);
  74         } catch (ReflectiveOperationException roe) {
  75             finest(roe);
  76         }
  77 
  78         return null;
  79     }
  80 
  81     /* Returns true if the NTLM implementation supports transparent
  82      * authentication (try with the current users credentials before
  83      * prompting for username and password, etc).
  84      */
  85     private static boolean supportsTransparentAuth(Method method) {
  86         try {
  87             return (Boolean)method.invoke(null);
  88         } catch (ReflectiveOperationException roe) {
  89             finest(roe);
  90         }
  91 
  92         return false;
  93     }
  94 
  95     /**
  96      * Loads the NTLM authentiation implementation through reflection. If
  97      * the class is present, then it must have the required constructors and
  98      * method. Otherwise, it is considered an error.
  99      */
 100     @SuppressWarnings("unchecked")
 101     private static NTLMAuthenticationProxy tryLoadNTLMAuthentication() {
 102         Class<? extends AuthenticationInfo> cl;
 103         Constructor<? extends AuthenticationInfo> threeArg, fiveArg;
 104         try {
 105             cl = (Class<? extends AuthenticationInfo>)Class.forName(clazzStr, true, null);
 106             if (cl != null) {
 107                 threeArg = cl.getConstructor(boolean.class,
 108                                              URL.class,
 109                                              PasswordAuthentication.class);
 110                 fiveArg = cl.getConstructor(boolean.class,
 111                                             String.class,
 112                                             int.class,
 113                                             PasswordAuthentication.class);
 114                 supportsTA = cl.getDeclaredMethod(supportsTAStr);
 115                 return new NTLMAuthenticationProxy(threeArg,
 116                                                    fiveArg);
 117             }
 118         } catch (ClassNotFoundException cnfe) {
 119             finest(cnfe);
 120         } catch (ReflectiveOperationException roe) {
 121             throw new AssertionError(roe);
 122         }
 123 
 124         return null;
 125     }
 126 
 127     static void finest(Exception e) {
 128         PlatformLogger logger = HttpURLConnection.getHttpLogger();
 129         logger.finest("NTLMAuthenticationProxy: " + e);
 130     }
 131 }