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 public void run() throws TransientServiceException {
176 // Create an ORB object
177 java.util.Properties props = new Properties();
178 props.putAll(System.getProperties());
179
180 props.put("org.omg.CORBA.ORBServerId", "1000000" ) ;
181 props.put("org.omg.CORBA.ORBClass", "org.apache.yoko.orb.CORBA.ORB");
182 props.put("org.omg.CORBA.ORBSingletonClass", "org.apache.yoko.orb.CORBA.ORBSingleton");
183 props.put("yoko.orb.oa.endpoint", "iiop --bind " + host + " --host " + host + " --port " + port );
184
185 createdOrb = ORB.init((String[])null, props) ;
186
187 // now initialize the service
188 initialize(createdOrb);
189 }
190 };
191 service.run();
192 log.debug("Creating ORB endpoint with host=" + host + ", port=" + port);
193 // the service instance is returned as an opaque object.
194 return service;
195 } catch (TransientServiceException e) {
196 throw new ConfigException("Error starting transient name service on port " + port, e);
197 }
198 }
199
200 /**
201 * Destroy a name service instance created by a
202 * prior call to createNameService().
203 *
204 * @param ns The opaque name service object returned from a
205 * prior call to createNameService().
206 */
207 public void destroyNameService(Object ns) {
208 // The name service instance handles its own shutdown.
209 ((TransientNameService)ns).destroy();
210 }
211
212 /**
213 * Create an ORB instance using the configured argument
214 * and property bundles.
215 *
216 * @param name The String name of the configuration GBean used to
217 * create this ORB.
218 * @param config The GBean configuration object required by the
219 * SocketFactory instance.
220 * @param args The String arguments passed to ORB.init().
221 * @param props The property bundle passed to ORB.init().
222 *
223 * @return An ORB constructed from the provided args and properties.
224 */
225 private ORB createORB(String name, ORBConfiguration config, String[] args, Properties props) {
226 return ORB.init(args, props);
227 }
228
229 /**
230 * Translate a CORBABean configuration into an
231 * array of arguments used to configure the ORB
232 * instance.
233 *
234 * @param server The CORBABean we're creating an ORB instance for.
235 *
236 * @return A String{} array containing the initialization
237 * arguments.
238 * @exception ConfigException if configuration cannot be interpreted
239 */
240 private String[] translateToArgs(CORBABean server) throws ConfigException {
241 ArrayList<String> list = new ArrayList<String>();
242 //TODO GERONIMO-2687, I don't think it makes sense to associate a default principal with a tss config, but if we need it
243 //here's the disfunctional code.
244 // TSSConfig config = server.getTssConfig();
245
246 // if the TSSConfig includes principal information, we need to add argument values
247 // for this information.
248 // DefaultPrincipal principal = config.getDefaultPrincipal();
249 // if (principal != null) {
250 // if (principal instanceof DefaultRealmPrincipal) {
251 // DefaultRealmPrincipal realmPrincipal = (DefaultRealmPrincipal) principal;
252 // list.add("default-realm-principal::" + realmPrincipal.getRealm() + ":" + realmPrincipal.getDomain() + ":"
253 // + realmPrincipal.getPrincipal().getClassName() + ":" + realmPrincipal.getPrincipal().getPrincipalName());
254 // } else if (principal instanceof DefaultDomainPrincipal) {
255 // DefaultDomainPrincipal domainPrincipal = (DefaultDomainPrincipal) principal;
256 // list.add("default-domain-principal::" + domainPrincipal.getDomain() + ":"
257 // + domainPrincipal.getPrincipal().getClassName() + ":" + domainPrincipal.getPrincipal().getPrincipalName());
258 // } else {
259 // list.add("default-principal::" + principal.getPrincipal().getClassName() + ":" + principal.getPrincipal().getPrincipalName());
260 // }
261 // }
262
263 // enable the connection plugin
264 enableSocketFactory(server.getURI(), list);
265
266 NameService nameService = server.getNameService();
267 // if we have a name service to enable as an initial ref, add it to the init processing.
268 if (nameService != null) {
269 list.add("-ORBInitRef");
270 list.add("NameService=" + nameService.getURI());
271 }
272
273 if (log.isDebugEnabled()) {
274 for (String configArg : list) {
275 log.debug(configArg);
276 }
277 }
278
279 return list.toArray(new String[list.size()]);
280 }
281
282 private Properties translateToProps(CORBABean server) throws ConfigException {
283 Properties result = new Properties();
284
285 result.put("org.omg.CORBA.ORBClass", "org.apache.yoko.orb.CORBA.ORB");
286 result.put("org.omg.CORBA.ORBSingletonClass", "org.apache.yoko.orb.CORBA.ORBSingleton");
287 result.put("org.omg.PortableInterceptor.ORBInitializerClass.org.apache.geronimo.corba.transaction.TransactionInitializer", "");
288 result.put("org.omg.PortableInterceptor.ORBInitializerClass.org.apache.geronimo.corba.security.SecurityInitializer", "");
289 result.put("org.omg.PortableInterceptor.ORBInitializerClass.org.apache.geronimo.yoko.ORBInitializer", "");
290 // don't specify the port if we're allowing this to default.
291 if (server.getPort() > 0) {
292 result.put("yoko.orb.oa.endpoint", "iiop --bind " + server.getHost() + " --host " + server.getHost() + " --port " + server.getPort());
293 }
294 else {
295 result.put("yoko.orb.oa.endpoint", "iiop --bind " + server.getHost()+ " --host " + server.getHost());
296 }
297
298 // this gives us a connection we can use to retrieve the ORB configuration in the
299 // interceptors.
300 result.put("yoko.orb.id", server.getURI());
301
302 // check the tss config for a transport mech definition. If we have one, then
303 // the port information will be passed in that config, and the port in the IIOP profile
304 // needs to be zero.
305 TSSConfig config = server.getTssConfig();
306 TSSTransportMechConfig transportMech = config.getTransport_mech();
307 if (transportMech != null) {
308 if (transportMech instanceof TSSSSLTransportConfig) {
309 result.put("yoko.orb.policy.zero_port", "true");
310 }
311 }
312
313 if (log.isDebugEnabled()) {
314 log.debug("translateToProps(TSSConfig)");
315 for (Enumeration iter = result.keys(); iter.hasMoreElements();) {
316 String key = (String) iter.nextElement();
317 log.debug(key + " = " + result.getProperty(key));
318 }
319 }
320 return result;
321 }
322
323 /**
324 * Translate a CSSBean configuration into the
325 * argument bundle needed to instantiate the
326 * ORB instance.
327 *
328 * @param client The CSSBean holding the configuration.
329 *
330 * @return A String array to be passed to ORB.init().
331 * @exception ConfigException if configuration cannot be interpreted
332 */
333 private String[] translateToArgs(CSSBean client) throws ConfigException {
334 ArrayList<String> list = new ArrayList<String>();
335
336 // enable the connection plugin
337 enableSocketFactory(client.getURI(), list);
338
339 if (log.isDebugEnabled()) {
340 for (String configArg : list) {
341 log.debug(configArg);
342 }
343 }
344
345 return list.toArray(new String[list.size()]);
346 }
347
348 /**
349 * Add arguments to the ORB.init() argument list
350 * required to enable the SocketFactory used for
351 * SSL support.
352 *
353 * @param uri The URI name of the configuration GBean (either a
354 * CSSBean or a CORBABean).
355 * @param args configuration arguments to add to
356 */
357 private void enableSocketFactory(String uri, List<String> args) {
358 args.add("-IIOPconnectionHelper");
359 args.add("org.apache.geronimo.yoko.SocketFactory");
360 args.add("-IIOPconnectionHelperArgs");
361 args.add(uri);
362 }
363
364
365 /**
366 * Translate a CSSBean configuration into the
367 * property bundle necessary to configure the
368 * ORB instance.
369 *
370 * @param client The CSSBean holding the configuration.
371 *
372 * @return A property bundle that can be passed to ORB.init();
373 * @exception ConfigException if configuration cannot be interpreted
374 */
375 private Properties translateToProps(CSSBean client) throws ConfigException {
376 Properties result = new Properties();
377
378 result.put("org.omg.CORBA.ORBClass", "org.apache.yoko.orb.CORBA.ORB");
379 result.put("org.omg.CORBA.ORBSingletonClass", "org.apache.yoko.orb.CORBA.ORBSingleton");
380 result.put("org.omg.PortableInterceptor.ORBInitializerClass.org.apache.geronimo.corba.transaction.TransactionInitializer", "");
381 result.put("org.omg.PortableInterceptor.ORBInitializerClass.org.apache.geronimo.corba.security.SecurityInitializer", "");
382 result.put("org.omg.PortableInterceptor.ORBInitializerClass.org.apache.geronimo.yoko.ORBInitializer", "");
383
384 // this gives us a connection we can use to retrieve the ORB configuration in the
385 // interceptors.
386 result.put("yoko.orb.id", client.getURI());
387
388 if (log.isDebugEnabled()) {
389 log.debug("translateToProps(CSSConfig)");
390 for (Enumeration iter = result.keys(); iter.hasMoreElements();) {
391 String key = (String) iter.nextElement();
392 log.debug(key + " = " + result.getProperty(key));
393 }
394 }
395 return result;
396 }
397
398
399 /**
400 * Translate a CSSBean configuration into the
401 * property bundle necessary to configure the
402 * ORB instance.
403 *
404 * @param client The CSSBean holding the configuration.
405 *
406 * @return A property bundle that can be passed to ORB.init();
407 * @exception ConfigException if configuration cannot be interpreted
408 */
409 private Properties translateToNameServiceProps(CSSBean client) throws ConfigException {
410 Properties result = new Properties();
411
412 result.put("org.omg.CORBA.ORBClass", "org.apache.yoko.orb.CORBA.ORB");
413 result.put("org.omg.CORBA.ORBSingletonClass", "org.apache.yoko.orb.CORBA.ORBSingleton");
414
415 if (log.isDebugEnabled()) {
416 log.debug("translateToNameServiceProps(CSSConfig)");
417 for (Enumeration iter = result.keys(); iter.hasMoreElements();) {
418 String key = (String) iter.nextElement();
419 log.debug(key + " = " + result.getProperty(key));
420 }
421 }
422 return result;
423 }
424 }