001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.geronimo.yoko; 018 019 import java.lang.reflect.Method; 020 import java.util.ArrayList; 021 import java.util.Enumeration; 022 import java.util.List; 023 import java.util.Properties; 024 025 import org.apache.commons.logging.Log; 026 import org.apache.commons.logging.LogFactory; 027 import org.apache.geronimo.corba.CORBABean; 028 import org.apache.geronimo.corba.CSSBean; 029 import org.apache.geronimo.corba.NameService; 030 import org.apache.geronimo.corba.ORBConfiguration; 031 import org.apache.geronimo.corba.security.config.ConfigAdapter; 032 import org.apache.geronimo.corba.security.config.ConfigException; 033 import org.apache.geronimo.corba.security.config.tss.TSSConfig; 034 import org.apache.geronimo.corba.security.config.tss.TSSSSLTransportConfig; 035 import org.apache.geronimo.corba.security.config.tss.TSSTransportMechConfig; 036 import org.apache.geronimo.gbean.GBeanLifecycle; 037 import org.apache.yoko.orb.CosNaming.tnaming.TransientNameService; 038 import org.apache.yoko.orb.CosNaming.tnaming.TransientServiceException; 039 import org.apache.yoko.orb.OB.ZERO_PORT_POLICY_ID; 040 import org.omg.CORBA.Any; 041 import org.omg.CORBA.ORB; 042 import org.omg.CORBA.Policy; 043 044 045 /** 046 * A ConfigAdapter instance for the Apache Yoko 047 * CORBA support. 048 * @version $Revision: 497125 $ $Date: 2007-01-17 10:51:30 -0800 (Wed, 17 Jan 2007) $ 049 */ 050 public class ORBConfigAdapter implements GBeanLifecycle, ConfigAdapter { 051 052 private final Log log = LogFactory.getLog(ORBConfigAdapter.class); 053 054 public ORBConfigAdapter() { 055 } 056 057 /** 058 * Start the config adapter GBean. This is basically 059 * an opportunity to set any system properties 060 * required to make the ORB hook ups. In particular, 061 * this makes the ORB hookups for the RMI over IIOP 062 * support. 063 * 064 * @exception Exception 065 */ 066 public void doStart() throws Exception { 067 // define the default ORB for ORB.init(); 068 System.setProperty("org.omg.CORBA.ORBClass", "org.apache.yoko.orb.CORBA.ORB"); 069 System.setProperty("org.omg.CORBA.ORBSingletonClass", "org.apache.yoko.orb.CORBA.ORBSingleton"); 070 071 // redirect the RMI implementation to use the Yoko ORB. 072 System.setProperty("javax.rmi.CORBA.PortableRemoteObjectClass", "org.apache.yoko.rmi.impl.PortableRemoteObjectImpl"); 073 System.setProperty("javax.rmi.CORBA.StubClass", "org.apache.yoko.rmi.impl.StubImpl"); 074 // this hooks the util class and allows us to override certain functions 075 System.setProperty("javax.rmi.CORBA.UtilClass", "org.apache.geronimo.corba.util.UtilDelegateImpl"); 076 // this tells the openejb UtilDelegateImpl which implementation to delegate non-overridden 077 // operations to. 078 System.setProperty("org.apache.geronimo.corba.UtilDelegateClass", "org.apache.yoko.rmi.impl.UtilImpl"); 079 // this allows us to hook RMI stub invocation/serialization events. 080 System.setProperty("org.apache.yoko.rmi.RMIStubInitializerClass", "org.apache.geronimo.yoko.RMIStubHandlerFactory"); 081 082 // ok, now we have a potential classloading problem because of where our util delegates are located. 083 // by forcing these classes to load now using our class loader, we can ensure things are properly initialized 084 Class clazz = this.getClass().getClassLoader().loadClass("javax.rmi.PortableRemoteObject"); 085 Method m = clazz.getMethod("narrow", Object.class, Class.class); 086 m.invoke(null, new Object(), Object.class); 087 088 089 log.debug("Started Yoko ORBConfigAdapter"); 090 } 091 092 public void doStop() throws Exception { 093 // nothing really required here. 094 log.debug("Stopped Yoko ORBConfigAdapter"); 095 } 096 097 public void doFail() { 098 // nothing much to do. 099 log.warn("Failed Yoko ORBConfigAdapter"); 100 } 101 102 /** 103 * Create an ORB for a CORBABean server context. 104 * 105 * @param server The CORBABean that owns this ORB's configuration. 106 * 107 * @return An ORB instance configured for the CORBABean. 108 * @exception ConfigException 109 */ 110 public ORB createServerORB(CORBABean server) throws ConfigException { 111 ORB orb = createORB(server.getURI(), server, translateToArgs(server), translateToProps(server)); 112 113 // check the tss config for a transport mech definition. If we have one, then 114 // the port information will be passed in that config, and the port in the IIOP profile 115 // needs to be zero. 116 TSSConfig config = server.getTssConfig(); 117 TSSTransportMechConfig transportMech = config.getTransport_mech(); 118 if (transportMech != null) { 119 if (transportMech instanceof TSSSSLTransportConfig) { 120 Any any = orb.create_any(); 121 any.insert_boolean(true); 122 123 try { 124 Policy portPolicy = orb.create_policy(ZERO_PORT_POLICY_ID.value, any); 125 Policy[] overrides = new Policy [] { portPolicy }; 126 server.setPolicyOverrides(overrides); 127 } catch (org.omg.CORBA.PolicyError e) { 128 // shouldn't happen, but we'll let things continue with no policy set. 129 } 130 131 } 132 } 133 134 return orb; 135 } 136 137 /** 138 * Create an ORB for a CSSBean client context. 139 * 140 * @param client The configured CSSBean used for access. 141 * 142 * @return An ORB instance configured for this client access. 143 * @exception ConfigException 144 */ 145 public ORB createClientORB(CSSBean client) throws ConfigException { 146 return createORB(client.getURI(), client, translateToArgs(client), translateToProps(client)); 147 } 148 149 /** 150 * Create an ORB for a CSSBean name service client context. 151 * 152 * @param client The configured CSSBean used for access. 153 * 154 * @return An ORB instance configured for this client access. 155 * @exception ConfigException 156 */ 157 public ORB createNameServiceClientORB(CSSBean client) throws ConfigException { 158 return createORB(client.getURI(), client, translateToArgs(client), translateToNameServiceProps(client)); 159 } 160 161 /** 162 * Create a transient name service instance using the 163 * specified host name and port. 164 * 165 * @param host The String host name. 166 * @param port The port number of the listener. 167 * 168 * @return An opaque object that represents the name service. 169 * @exception ConfigException 170 */ 171 public Object createNameService(String host, int port) throws ConfigException { 172 try { 173 // create a name service using the supplied host and publish under the name "NameService" 174 TransientNameService service = new TransientNameService(host, port, "NameService"); 175 service.run(); 176 // the service instance is returned as an opaque object. 177 return service; 178 } catch (TransientServiceException e) { 179 throw new ConfigException("Error starting transient name service", e); 180 } 181 } 182 183 /** 184 * Destroy a name service instance created by a 185 * prior call to createNameService(). 186 * 187 * @param ns The opaque name service object returned from a 188 * prior call to createNameService(). 189 */ 190 public void destroyNameService(Object ns) { 191 // The name service instance handles its own shutdown. 192 ((TransientNameService)ns).destroy(); 193 } 194 195 /** 196 * Create an ORB instance using the configured argument 197 * and property bundles. 198 * 199 * @param name The String name of the configuration GBean used to 200 * create this ORB. 201 * @param config The GBean configuration object required by the 202 * SocketFactory instance. 203 * @param args The String arguments passed to ORB.init(). 204 * @param props The property bundle passed to ORB.init(). 205 * 206 * @return An ORB constructed from the provided args and properties. 207 */ 208 private ORB createORB(String name, ORBConfiguration config, String[] args, Properties props) { 209 return ORB.init(args, props); 210 } 211 212 /** 213 * Translate a CORBABean configuration into an 214 * array of arguments used to configure the ORB 215 * instance. 216 * 217 * @param server The CORBABean we're creating an ORB instance for. 218 * 219 * @return A String{} array containing the initialization 220 * arguments. 221 * @exception ConfigException if configuration cannot be interpreted 222 */ 223 private String[] translateToArgs(CORBABean server) throws ConfigException { 224 ArrayList<String> list = new ArrayList<String>(); 225 //TODO GERONIMO-2687, I don't think it makes sense to associate a default principal with a tss config, but if we need it 226 //here's the disfunctional code. 227 // TSSConfig config = server.getTssConfig(); 228 229 // if the TSSConfig includes principal information, we need to add argument values 230 // for this information. 231 // DefaultPrincipal principal = config.getDefaultPrincipal(); 232 // if (principal != null) { 233 // if (principal instanceof DefaultRealmPrincipal) { 234 // DefaultRealmPrincipal realmPrincipal = (DefaultRealmPrincipal) principal; 235 // list.add("default-realm-principal::" + realmPrincipal.getRealm() + ":" + realmPrincipal.getDomain() + ":" 236 // + realmPrincipal.getPrincipal().getClassName() + ":" + realmPrincipal.getPrincipal().getPrincipalName()); 237 // } else if (principal instanceof DefaultDomainPrincipal) { 238 // DefaultDomainPrincipal domainPrincipal = (DefaultDomainPrincipal) principal; 239 // list.add("default-domain-principal::" + domainPrincipal.getDomain() + ":" 240 // + domainPrincipal.getPrincipal().getClassName() + ":" + domainPrincipal.getPrincipal().getPrincipalName()); 241 // } else { 242 // list.add("default-principal::" + principal.getPrincipal().getClassName() + ":" + principal.getPrincipal().getPrincipalName()); 243 // } 244 // } 245 246 // enable the connection plugin 247 enableSocketFactory(server.getURI(), list); 248 249 NameService nameService = server.getNameService(); 250 // if we have a name service to enable as an initial ref, add it to the init processing. 251 if (nameService != null) { 252 list.add("-ORBInitRef"); 253 list.add("NameService=" + nameService.getURI()); 254 } 255 256 if (log.isDebugEnabled()) { 257 for (String configArg : list) { 258 log.debug(configArg); 259 } 260 } 261 262 return list.toArray(new String[list.size()]); 263 } 264 265 private Properties translateToProps(CORBABean server) throws ConfigException { 266 Properties result = new Properties(); 267 268 result.put("org.omg.CORBA.ORBClass", "org.apache.yoko.orb.CORBA.ORB"); 269 result.put("org.omg.CORBA.ORBSingletonClass", "org.apache.yoko.orb.CORBA.ORBSingleton"); 270 result.put("org.omg.PortableInterceptor.ORBInitializerClass.org.apache.geronimo.corba.transaction.TransactionInitializer", ""); 271 result.put("org.omg.PortableInterceptor.ORBInitializerClass.org.apache.geronimo.corba.security.SecurityInitializer", ""); 272 result.put("org.omg.PortableInterceptor.ORBInitializerClass.org.apache.geronimo.yoko.ORBInitializer", ""); 273 // don't specify the port if we're allowing this to default. 274 if (server.getPort() > 0) { 275 result.put("yoko.orb.oa.endpoint", "iiop --host " + server.getHost() + " --port " + server.getPort()); 276 } 277 else { 278 result.put("yoko.orb.oa.endpoint", "iiop --host " + server.getHost()); 279 } 280 281 // this gives us a connection we can use to retrieve the ORB configuration in the 282 // interceptors. 283 result.put("yoko.orb.id", server.getURI()); 284 285 // check the tss config for a transport mech definition. If we have one, then 286 // the port information will be passed in that config, and the port in the IIOP profile 287 // needs to be zero. 288 TSSConfig config = server.getTssConfig(); 289 TSSTransportMechConfig transportMech = config.getTransport_mech(); 290 if (transportMech != null) { 291 if (transportMech instanceof TSSSSLTransportConfig) { 292 result.put("yoko.orb.policy.zero_port", "true"); 293 } 294 } 295 296 if (log.isDebugEnabled()) { 297 log.debug("translateToProps(TSSConfig)"); 298 for (Enumeration iter = result.keys(); iter.hasMoreElements();) { 299 String key = (String) iter.nextElement(); 300 log.debug(key + " = " + result.getProperty(key)); 301 } 302 } 303 return result; 304 } 305 306 /** 307 * Translate a CSSBean configuration into the 308 * argument bundle needed to instantiate the 309 * ORB instance. 310 * 311 * @param client The CSSBean holding the configuration. 312 * 313 * @return A String array to be passed to ORB.init(). 314 * @exception ConfigException if configuration cannot be interpreted 315 */ 316 private String[] translateToArgs(CSSBean client) throws ConfigException { 317 ArrayList<String> list = new ArrayList<String>(); 318 319 // enable the connection plugin 320 enableSocketFactory(client.getURI(), list); 321 322 if (log.isDebugEnabled()) { 323 for (String configArg : list) { 324 log.debug(configArg); 325 } 326 } 327 328 return list.toArray(new String[list.size()]); 329 } 330 331 /** 332 * Add arguments to the ORB.init() argument list 333 * required to enable the SocketFactory used for 334 * SSL support. 335 * 336 * @param uri The URI name of the configuration GBean (either a 337 * CSSBean or a CORBABean). 338 * @param args configuration arguments to add to 339 */ 340 private void enableSocketFactory(String uri, List<String> args) { 341 args.add("-IIOPconnectionHelper"); 342 args.add("org.apache.geronimo.yoko.SocketFactory"); 343 args.add("-IIOPconnectionHelperArgs"); 344 args.add(uri); 345 } 346 347 348 /** 349 * Translate a CSSBean configuration into the 350 * property bundle necessary to configure the 351 * ORB instance. 352 * 353 * @param client The CSSBean holding the configuration. 354 * 355 * @return A property bundle that can be passed to ORB.init(); 356 * @exception ConfigException if configuration cannot be interpreted 357 */ 358 private Properties translateToProps(CSSBean client) throws ConfigException { 359 Properties result = new Properties(); 360 361 result.put("org.omg.CORBA.ORBClass", "org.apache.yoko.orb.CORBA.ORB"); 362 result.put("org.omg.CORBA.ORBSingletonClass", "org.apache.yoko.orb.CORBA.ORBSingleton"); 363 result.put("org.omg.PortableInterceptor.ORBInitializerClass.org.apache.geronimo.corba.transaction.TransactionInitializer", ""); 364 result.put("org.omg.PortableInterceptor.ORBInitializerClass.org.apache.geronimo.corba.security.SecurityInitializer", ""); 365 result.put("org.omg.PortableInterceptor.ORBInitializerClass.org.apache.geronimo.yoko.ORBInitializer", ""); 366 367 // this gives us a connection we can use to retrieve the ORB configuration in the 368 // interceptors. 369 result.put("yoko.orb.id", client.getURI()); 370 371 if (log.isDebugEnabled()) { 372 log.debug("translateToProps(CSSConfig)"); 373 for (Enumeration iter = result.keys(); iter.hasMoreElements();) { 374 String key = (String) iter.nextElement(); 375 log.debug(key + " = " + result.getProperty(key)); 376 } 377 } 378 return result; 379 } 380 381 382 /** 383 * Translate a CSSBean configuration into the 384 * property bundle necessary to configure the 385 * ORB instance. 386 * 387 * @param client The CSSBean holding the configuration. 388 * 389 * @return A property bundle that can be passed to ORB.init(); 390 * @exception ConfigException if configuration cannot be interpreted 391 */ 392 private Properties translateToNameServiceProps(CSSBean client) throws ConfigException { 393 Properties result = new Properties(); 394 395 result.put("org.omg.CORBA.ORBClass", "org.apache.yoko.orb.CORBA.ORB"); 396 result.put("org.omg.CORBA.ORBSingletonClass", "org.apache.yoko.orb.CORBA.ORBSingleton"); 397 398 if (log.isDebugEnabled()) { 399 log.debug("translateToNameServiceProps(CSSConfig)"); 400 for (Enumeration iter = result.keys(); iter.hasMoreElements();) { 401 String key = (String) iter.nextElement(); 402 log.debug(key + " = " + result.getProperty(key)); 403 } 404 } 405 return result; 406 } 407 }