View Javadoc
1   /*
2    * Copyright (C) 2014 Laurent Goujon <lgoujon@twitter.com>
3    * and other copyright owners as documented in the project's IP log.
4    *
5    * This program and the accompanying materials are made available
6    * under the terms of the Eclipse Distribution License v1.0 which
7    * accompanies this distribution, is reproduced below, and is
8    * available at http://www.eclipse.org/org/documents/edl-v10.php
9    *
10   * All rights reserved.
11   *
12   * Redistribution and use in source and binary forms, with or
13   * without modification, are permitted provided that the following
14   * conditions are met:
15   *
16   * - Redistributions of source code must retain the above copyright
17   *   notice, this list of conditions and the following disclaimer.
18   *
19   * - Redistributions in binary form must reproduce the above
20   *   copyright notice, this list of conditions and the following
21   *   disclaimer in the documentation and/or other materials provided
22   *   with the distribution.
23   *
24   * - Neither the name of the Eclipse Foundation, Inc. nor the
25   *   names of its contributors may be used to endorse or promote
26   *   products derived from this software without specific prior
27   *   written permission.
28   *
29   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
30   * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
31   * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
32   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
34   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
35   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
36   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
38   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
41   * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42   */
43  
44  package org.eclipse.jgit.util;
45  
46  import java.lang.reflect.Constructor;
47  import java.lang.reflect.InvocationTargetException;
48  import java.net.URL;
49  
50  import org.ietf.jgss.GSSManager;
51  
52  /**
53   * Factory to detect which GSSManager implementation should be used.
54   *
55   * @since 3.4
56   */
57  public abstract class GSSManagerFactory {
58  	/**
59  	 * Auto-detects the GSSManager factory to use based on system.
60  	 *
61  	 * @return detected GSSManager factory
62  	 */
63  	public static GSSManagerFactory detect() {
64  		return (SunGSSManagerFactory.isSupported()) ? new SunGSSManagerFactory()
65  				: new DefaultGSSManagerFactory();
66  	}
67  
68  	/**
69  	 * Returns a GSS Manager instance for the provided url
70  	 *
71  	 * @param url
72  	 *            the repository url
73  	 * @return a GSSManager instance
74  	 */
75  	public abstract GSSManager newInstance(URL url);
76  
77  	/**
78  	 * DefaultGSSManagerFactory uses @link {@link GSSManager#getInstance()} but
79  	 * you might need to set
80  	 * <code>javax.security.auth.useSubjectCredsOnly</code> system property to
81  	 * <code>false</code> for authentication to work.
82  	 */
83  	private static class DefaultGSSManagerFactory extends GSSManagerFactory {
84  		private static final GSSManager INSTANCE = GSSManager.getInstance();
85  
86  		@Override
87  		public GSSManager newInstance(URL url) {
88  			return INSTANCE;
89  		}
90  	}
91  
92  	private static class SunGSSManagerFactory extends GSSManagerFactory {
93  		private static boolean IS_SUPPORTED;
94  		private static Constructor<?> HTTP_CALLER_INFO_CONSTRUCTOR;
95  		private static Constructor<?> HTTP_CALLER_CONSTRUCTOR;
96  
97  		private static Constructor<?> GSS_MANAGER_IMPL_CONSTRUCTOR;
98  
99  		static {
100 			try {
101 				init();
102 				IS_SUPPORTED = true;
103 			} catch (Exception e) {
104 				IS_SUPPORTED = false;
105 			}
106 		}
107 
108 		private static void init() throws ClassNotFoundException,
109 				NoSuchMethodException {
110 			Class<?> httpCallerInfoClazz = Class
111 					.forName("sun.net.www.protocol.http.HttpCallerInfo"); //$NON-NLS-1$
112 			HTTP_CALLER_INFO_CONSTRUCTOR = httpCallerInfoClazz
113 					.getConstructor(URL.class);
114 
115 			Class<?> httpCallerClazz = Class
116 					.forName("sun.security.jgss.HttpCaller"); //$NON-NLS-1$
117 			HTTP_CALLER_CONSTRUCTOR = httpCallerClazz
118 					.getConstructor(httpCallerInfoClazz);
119 
120 			Class<?> gssCallerClazz = Class
121 					.forName("sun.security.jgss.GSSCaller"); //$NON-NLS-1$
122 			Class<?> gssManagerImplClazz = Class
123 					.forName("sun.security.jgss.GSSManagerImpl"); //$NON-NLS-1$
124 			GSS_MANAGER_IMPL_CONSTRUCTOR = gssManagerImplClazz
125 					.getConstructor(gssCallerClazz);
126 
127 		}
128 
129 		/**
130 		 * Detects if SunGSSManagerProvider is supported by the system
131 		 *
132 		 * @return true if it is supported
133 		 */
134 		public static boolean isSupported() {
135 			return IS_SUPPORTED;
136 		}
137 
138 		@Override
139 		public GSSManager newInstance(URL url) {
140 			try {
141 				Object httpCallerInfo = HTTP_CALLER_INFO_CONSTRUCTOR
142 						.newInstance(url);
143 				Object httpCaller = HTTP_CALLER_CONSTRUCTOR
144 						.newInstance(httpCallerInfo);
145 
146 				return (GSSManager) GSS_MANAGER_IMPL_CONSTRUCTOR
147 						.newInstance(httpCaller);
148 			} catch (InstantiationException e) {
149 				throw new Error(e);
150 			} catch (IllegalAccessException e) {
151 				throw new Error(e);
152 			} catch (IllegalArgumentException e) {
153 				throw new Error(e);
154 			} catch (InvocationTargetException e) {
155 				throw new Error(e);
156 			}
157 		}
158 	}
159 }