1 17 package org.apache.geronimo.client; 18 19 import java.lang.reflect.Constructor ; 20 import java.lang.reflect.InvocationTargetException ; 21 import java.lang.reflect.Method ; 22 import java.security.PrivilegedAction ; 23 24 import javax.security.auth.Subject ; 25 import javax.security.auth.callback.CallbackHandler ; 26 import javax.security.auth.login.LoginContext ; 27 import javax.security.auth.login.LoginException ; 28 29 import org.apache.geronimo.gbean.AbstractName; 30 import org.apache.geronimo.gbean.GBeanInfo; 31 import org.apache.geronimo.gbean.GBeanInfoBuilder; 32 import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory; 33 import org.apache.geronimo.kernel.Kernel; 34 import org.apache.geronimo.security.ContextManager; 35 import org.apache.geronimo.security.Callers; 36 import org.apache.geronimo.security.deploy.DefaultPrincipal; 37 import org.apache.geronimo.security.util.ConfigurationUtil; 38 39 42 public final class AppClientContainer { 43 private static final Class [] MAIN_ARGS = {String [].class}; 44 45 private final String mainClassName; 46 private final AppClientPlugin jndiContext; 47 private final AbstractName appClientModuleName; 48 private final String realmName; 49 private final Class callbackHandlerClass; 50 private final Subject defaultSubject; 51 private final Method mainMethod; 52 private final ClassLoader classLoader; 53 private final Kernel kernel; 54 55 public AppClientContainer(String mainClassName, 56 AbstractName appClientModuleName, 57 String realmName, 58 String callbackHandlerClassName, 59 DefaultPrincipal defaultPrincipal, 60 AppClientPlugin jndiContext, 61 ClassLoader classLoader, 62 Kernel kernel 63 ) throws Exception { 64 this.mainClassName = mainClassName; 65 this.appClientModuleName = appClientModuleName; 66 if ((realmName == null) != (callbackHandlerClassName == null)) { 67 throw new IllegalArgumentException ("You must supply both realmName and callbackHandlerClass or neither"); 68 } 69 this.realmName = realmName; 70 if (callbackHandlerClassName != null) { 71 try { 72 this.callbackHandlerClass = classLoader.loadClass(callbackHandlerClassName); 73 } catch (ClassNotFoundException e) { 74 throw new AppClientInitializationException("Could not load callbackHandlerClass", e); 75 } 76 } else { 77 callbackHandlerClass = null; 78 } 79 if (defaultPrincipal != null) { 80 defaultSubject = ConfigurationUtil.generateDefaultSubject(defaultPrincipal, classLoader); 81 } else { 82 defaultSubject = null; 83 } 84 this.classLoader = classLoader; 85 this.kernel = kernel; 86 this.jndiContext = jndiContext; 87 88 try { 89 Class mainClass = classLoader.loadClass(mainClassName); 90 mainMethod = mainClass.getMethod("main", MAIN_ARGS); 91 } catch (ClassNotFoundException e) { 92 throw new AppClientInitializationException("Unable to load Main-Class " + mainClassName, e); 93 } catch (NoSuchMethodException e) { 94 throw new AppClientInitializationException("Main-Class " + mainClassName + " does not have a main method", e); 95 } 96 } 97 98 public AbstractName getAppClientModuleName() { 99 return appClientModuleName; 100 } 101 102 public String getMainClassName() { 103 return mainClassName; 104 } 105 106 public void main(final String [] args) throws Exception { 107 Thread thread = Thread.currentThread(); 110 111 ClassLoader oldClassLoader = thread.getContextClassLoader(); 112 Callers oldCallers = ContextManager.getCallers(); 113 Subject clientSubject = defaultSubject; 114 LoginContext loginContext = null; 115 try { 116 thread.setContextClassLoader(classLoader); 117 if (callbackHandlerClass != null) { 118 CallbackHandler callbackHandler; 120 try { 121 Constructor cArgs = callbackHandlerClass.getConstructor(new Class [] {String [].class}); 122 callbackHandler = (CallbackHandler ) cArgs.newInstance(new Object [] {args}); 123 } catch (NoSuchMethodException e) { 124 callbackHandler = (CallbackHandler ) callbackHandlerClass.newInstance(); 125 } 126 loginContext = new LoginContext (realmName, callbackHandler); 127 try { 128 loginContext.login(); 129 } catch (LoginException e) { 130 loginContext = null; 131 throw e; 132 } 133 clientSubject = loginContext.getSubject(); 134 } 135 ContextManager.setCallers(clientSubject, clientSubject); 136 jndiContext.startClient(appClientModuleName, kernel, classLoader); 137 if (clientSubject == null) { 138 mainMethod.invoke(null, new Object []{args}); 139 } else { 140 Subject.doAs(clientSubject, new PrivilegedAction () { 141 public Object run() { 142 try { 143 mainMethod.invoke(null, new Object []{args}); 144 } catch (IllegalAccessException e) { 145 throw new RuntimeException (e); 146 } catch (InvocationTargetException e) { 147 throw new RuntimeException (e); 148 } 149 return null; 150 } 151 }); 152 } 153 } catch (InvocationTargetException e) { 154 Throwable cause = e.getCause(); 155 if (cause instanceof Exception ) { 156 throw (Exception ) cause; 157 } else if (cause instanceof Error ) { 158 throw (Error ) cause; 159 } 160 throw new Error (e); 161 } finally { 162 if (loginContext != null) { 163 loginContext.logout(); 164 } 165 jndiContext.stopClient(appClientModuleName); 166 167 thread.setContextClassLoader(oldClassLoader); 168 ContextManager.popCallers(oldCallers); 169 } 170 } 171 172 public static final GBeanInfo GBEAN_INFO; 173 174 static { 175 GBeanInfoBuilder infoFactory = GBeanInfoBuilder.createStatic(AppClientContainer.class, NameFactory.APP_CLIENT); 176 177 infoFactory.addOperation("main", new Class []{String [].class}); 178 179 infoFactory.addAttribute("mainClassName", String .class, true); 180 infoFactory.addAttribute("appClientModuleName", AbstractName.class, true); 181 infoFactory.addAttribute("realmName", String .class, true); 182 infoFactory.addAttribute("callbackHandlerClassName", String .class, true); 183 infoFactory.addAttribute("defaultPrincipal", DefaultPrincipal.class, true); 184 185 infoFactory.addReference("JNDIContext", AppClientPlugin.class, NameFactory.GERONIMO_SERVICE); 186 187 infoFactory.addAttribute("classLoader", ClassLoader .class, false); 188 infoFactory.addAttribute("kernel", Kernel.class, false); 189 190 191 infoFactory.setConstructor(new String []{"mainClassName", 192 "appClientModuleName", 193 "realmName", 194 "callbackHandlerClassName", 195 "defaultPrincipal", 196 "JNDIContext", 197 "classLoader", 198 "kernel" 199 }); 200 201 GBEAN_INFO = infoFactory.getBeanInfo(); 202 } 203 204 public static GBeanInfo getGBeanInfo() { 205 return GBEAN_INFO; 206 } 207 } 208 | Popular Tags |