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: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $
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 }