View Javadoc
1   /*
2    * Copyright (C) 2014 Laurent Goujon <lgoujon@twitter.com> and others
3    *
4    * This program and the accompanying materials are made available under the
5    * terms of the Eclipse Distribution License v. 1.0 which is available at
6    * https://www.eclipse.org/org/documents/edl-v10.php.
7    *
8    * SPDX-License-Identifier: BSD-3-Clause
9    */
10  
11  package org.eclipse.jgit.util;
12  
13  import java.lang.reflect.Constructor;
14  import java.lang.reflect.InvocationTargetException;
15  import java.net.URL;
16  
17  import org.ietf.jgss.GSSManager;
18  
19  /**
20   * Factory to detect which GSSManager implementation should be used.
21   *
22   * @since 3.4
23   */
24  public abstract class GSSManagerFactory {
25  	/**
26  	 * Auto-detects the GSSManager factory to use based on system.
27  	 *
28  	 * @return detected GSSManager factory
29  	 */
30  	public static GSSManagerFactory detect() {
31  		return (SunGSSManagerFactory.isSupported()) ? new SunGSSManagerFactory()
32  				: new DefaultGSSManagerFactory();
33  	}
34  
35  	/**
36  	 * Returns a GSS Manager instance for the provided url
37  	 *
38  	 * @param url
39  	 *            the repository url
40  	 * @return a GSSManager instance
41  	 */
42  	public abstract GSSManager newInstance(URL url);
43  
44  	/**
45  	 * DefaultGSSManagerFactory uses @link {@link GSSManager#getInstance()} but
46  	 * you might need to set
47  	 * <code>javax.security.auth.useSubjectCredsOnly</code> system property to
48  	 * <code>false</code> for authentication to work.
49  	 */
50  	private static class DefaultGSSManagerFactory extends GSSManagerFactory {
51  		private static final GSSManager INSTANCE = GSSManager.getInstance();
52  
53  		@Override
54  		public GSSManager newInstance(URL url) {
55  			return INSTANCE;
56  		}
57  	}
58  
59  	private static class SunGSSManagerFactory extends GSSManagerFactory {
60  		private static boolean IS_SUPPORTED;
61  		private static Constructor<?> HTTP_CALLER_INFO_CONSTRUCTOR;
62  		private static Constructor<?> HTTP_CALLER_CONSTRUCTOR;
63  
64  		private static Constructor<?> GSS_MANAGER_IMPL_CONSTRUCTOR;
65  
66  		static {
67  			try {
68  				init();
69  				IS_SUPPORTED = true;
70  			} catch (Exception e) {
71  				IS_SUPPORTED = false;
72  			}
73  		}
74  
75  		private static void init() throws ClassNotFoundException,
76  				NoSuchMethodException {
77  			Class<?> httpCallerInfoClazz = Class
78  					.forName("sun.net.www.protocol.http.HttpCallerInfo"); //$NON-NLS-1$
79  			HTTP_CALLER_INFO_CONSTRUCTOR = httpCallerInfoClazz
80  					.getConstructor(URL.class);
81  
82  			Class<?> httpCallerClazz = Class
83  					.forName("sun.security.jgss.HttpCaller"); //$NON-NLS-1$
84  			HTTP_CALLER_CONSTRUCTOR = httpCallerClazz
85  					.getConstructor(httpCallerInfoClazz);
86  
87  			Class<?> gssCallerClazz = Class
88  					.forName("sun.security.jgss.GSSCaller"); //$NON-NLS-1$
89  			Class<?> gssManagerImplClazz = Class
90  					.forName("sun.security.jgss.GSSManagerImpl"); //$NON-NLS-1$
91  			GSS_MANAGER_IMPL_CONSTRUCTOR = gssManagerImplClazz
92  					.getConstructor(gssCallerClazz);
93  
94  		}
95  
96  		/**
97  		 * Detects if SunGSSManagerProvider is supported by the system
98  		 *
99  		 * @return true if it is supported
100 		 */
101 		public static boolean isSupported() {
102 			return IS_SUPPORTED;
103 		}
104 
105 		@Override
106 		public GSSManager newInstance(URL url) {
107 			try {
108 				Object httpCallerInfo = HTTP_CALLER_INFO_CONSTRUCTOR
109 						.newInstance(url);
110 				Object httpCaller = HTTP_CALLER_CONSTRUCTOR
111 						.newInstance(httpCallerInfo);
112 
113 				return (GSSManager) GSS_MANAGER_IMPL_CONSTRUCTOR
114 						.newInstance(httpCaller);
115 			} catch (InstantiationException | IllegalAccessException
116 					| IllegalArgumentException | InvocationTargetException e) {
117 				throw new Error(e);
118 			}
119 		}
120 	}
121 }