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.corba;
018
019 import java.net.InetAddress;
020 import java.net.InetSocketAddress;
021 import java.net.UnknownHostException;
022
023 import javax.ejb.spi.HandleDelegate;
024
025 import org.apache.commons.logging.Log;
026 import org.apache.commons.logging.LogFactory;
027 import org.apache.geronimo.gbean.AbstractName;
028 import org.apache.geronimo.gbean.GBeanLifecycle;
029 import org.apache.geronimo.gbean.InvalidConfigurationException;
030 import org.apache.geronimo.corba.security.ServerPolicy;
031 import org.apache.geronimo.corba.security.ServerPolicyFactory;
032 import org.apache.geronimo.corba.security.config.ConfigAdapter;
033 import org.apache.geronimo.corba.security.config.ssl.SSLConfig;
034 import org.apache.geronimo.corba.security.config.tss.TSSConfig;
035 import org.apache.geronimo.corba.security.config.tss.TSSSSLTransportConfig;
036 import org.apache.geronimo.corba.security.config.tss.TSSTransportMechConfig;
037 import org.apache.geronimo.corba.util.Util;
038 import org.apache.geronimo.openejb.OpenEjbSystem;
039 import org.omg.CORBA.Any;
040 import org.omg.CORBA.ORB;
041 import org.omg.CORBA.Policy;
042 import org.omg.PortableServer.POA;
043 import org.omg.PortableServer.POAHelper;
044
045
046 /**
047 * A CORBABean is a main CORBA server configuration. The
048 * CORBABean is the hosting ORB to which additional TSSBeans
049 * attach to export EJBs. The CORBABean may be configured
050 * to use either plain socket listeners or SSL listeners, based
051 * on the bean specification. All TSSBean objects attached
052 * to this Bean instance will share the same listener
053 * endpoint and transport-level security.
054 * @version $Revision: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $
055 */
056 public class CORBABean implements GBeanLifecycle, ORBRef, ORBConfiguration {
057 private final Log log = LogFactory.getLog(CORBABean.class);
058
059 private final ClassLoader classLoader;
060 private final ConfigAdapter configAdapter;
061 // the initial listener port
062 private int listenerPort;
063 // the host name we expose in IORs
064 private String host;
065 private TSSConfig tssConfig;
066 private SSLConfig sslConfig;
067 private ORB orb;
068 private POA rootPOA;
069 private NameService nameService;
070 private AbstractName abstractName;
071 private OpenEjbSystem ejbSystem;
072 // ORB-specific policy overrides we need to add to POA policies created by
073 // child TSSBeans.
074 private Policy[] policyOverrides = null;
075
076 public CORBABean() {
077 this.classLoader = null;
078 this.configAdapter = null;
079 this.sslConfig = null;
080 this.listenerPort = -1;
081 this.host = null;
082 this.abstractName = null;
083 this.policyOverrides = null;
084 this.ejbSystem = null;
085 }
086
087 /**
088 * Instantiate a CORBABean instance.
089 *
090 * @param abstractName
091 * The server-created abstract name for this bean instance.
092 * @param configAdapter
093 * The ORB ConfigAdapter used to interface with the
094 * JVM-configured ORB instance.
095 * @param host The hostname we publish ourselves under.
096 * @param listenerPort
097 * The initial listener port to use.
098 * @param classLoader
099 * The ClassLoader used for ORB context class loading.
100 * @param nameService
101 * The initial name service the created ORB will use
102 * for object resolution.
103 * @param ssl The SSL configuration, including the KeystoreManager.
104 *
105 */
106 public CORBABean(AbstractName abstractName, ConfigAdapter configAdapter, String host, int listenerPort, ClassLoader classLoader, NameService nameService, OpenEjbSystem ejbSystem, SSLConfig ssl) {
107 this.abstractName = abstractName;
108 this.classLoader = classLoader;
109 this.configAdapter = configAdapter;
110 sslConfig = ssl;
111 this.nameService = nameService;
112 this.host = host;
113 this.listenerPort = listenerPort;
114 this.policyOverrides = null;
115 this.ejbSystem = ejbSystem;
116 }
117
118 /**
119 * Retrieve the NameService this CORBA server depends upon.
120 *
121 * @return The configured NameService instance.
122 */
123 public NameService getNameService() {
124 return nameService;
125 }
126
127 /**
128 * Setter attribute for the NameService.
129 *
130 * @param s The new target name service.
131 */
132 public void setNameService(NameService s) {
133 nameService = s;
134 }
135
136 /**
137 * Get the optional TSSConfig object specified for this
138 * CORBABean server.
139 *
140 * @return The TSSConfig object (if any).
141 */
142 public TSSConfig getTssConfig() {
143 // if nothing has been explicitly set, ensure we return
144 // a default one.
145 if (tssConfig == null) {
146 tssConfig = new TSSConfig();
147 }
148 return tssConfig;
149 }
150
151 /**
152 * Set a TSSConfig value for this CORBA instance.
153 *
154 * @param config The required TSSConfig information.
155 */
156 public void setTssConfig(TSSConfig config) {
157 this.tssConfig = config;
158 }
159
160 /**
161 * Return the SSLConfig used for this ORB instance.
162 * if one has not been configured, this returns
163 * a default configuration.
164 *
165 * @return The SSLConfig object use to manage transport-level
166 * security.
167 */
168 public SSLConfig getSslConfig() {
169 if (sslConfig == null) {
170 sslConfig = new SSLConfig();
171 }
172 return sslConfig;
173 }
174
175 /**
176 * Attribute setter for the SSL configuration.
177 *
178 * @param c The new SSLConfig object used for secure communications.
179 */
180 public void setSslConfing(SSLConfig c) {
181 sslConfig = c;
182 }
183
184
185 /**
186 * Return the ORB instance created for this CORBABean.
187 *
188 * @return The ORB instance backing this bean.
189 */
190 public ORB getORB() {
191 return orb;
192 }
193
194 public HandleDelegate getHandleDelegate() {
195 return new CORBAHandleDelegate();
196 }
197
198 /**
199 * Get the root POA() instance associated with the ORB.
200 *
201 * @return The rootPOA instance obtained from the ORB.
202 */
203 public POA getRootPOA() {
204 return rootPOA;
205 }
206
207 /**
208 * Retrieve the listener address (host/port combo) used
209 * by the ORB.
210 *
211 * @return An InetSocketAddress item identifying the end point
212 * for the ORB.
213 */
214 public InetSocketAddress getListenAddress() {
215 return new InetSocketAddress(host, listenerPort);
216 }
217
218 /**
219 * Start the ORB associated with this bean instance.
220 *
221 * @exception Exception
222 */
223 public void doStart() throws Exception {
224
225 ClassLoader savedLoader = Thread.currentThread().getContextClassLoader();
226 try {
227 Thread.currentThread().setContextClassLoader(classLoader);
228
229 // make sure we've decided how the listener should be configured.
230 resolveListenerAddress();
231 // register this so we can retrieve this in the interceptors
232 Util.registerORB(getURI(), this);
233
234 log.debug("CORBABean " + getURI() + " creating listener on port " + listenerPort);
235 // the config adapter creates the actual ORB instance for us.
236 orb = configAdapter.createServerORB(this);
237
238 // we set this ORB value into the Util. The Util ORB is used for a lot of utility things, so
239 // we'll cache the first instance created.
240 Util.setORB(orb);
241
242 // TSSBeans are going to need our rootPOA instance, so resolve this now.
243 org.omg.CORBA.Object obj = orb.resolve_initial_references("RootPOA");
244 rootPOA = POAHelper.narrow(obj);
245 // if we have an OpenEjbSystem reference, inform the ejb subsystem
246 // there's now an ORB available for the JNDI context.
247 if (ejbSystem != null) {
248 ejbSystem.setORBContext(orb, getHandleDelegate());
249 }
250 } catch (NoSuchMethodError e) {
251 log.error("Incorrect level of org.omg.CORBA classes found.\nLikely cause is an incorrect java.endorsed.dirs configuration");
252 throw new InvalidConfigurationException("CORBA usage requires Yoko CORBA spec classes in java.endorsed.dirs classpath", e);
253 } finally {
254 Thread.currentThread().setContextClassLoader(savedLoader);
255 }
256
257 }
258
259 public void doStop() throws Exception {
260 orb.destroy();
261 // remove this from the registry
262 Util.unregisterORB(getURI());
263 log.debug("Stopped CORBABean");
264 }
265
266 public void doFail() {
267 log.warn("Failed CORBABean");
268 }
269
270 /**
271 * Process the specified host/port information on
272 * both the bean and the TSSConfig to arrive at a
273 * target port. This must be called prior to creating
274 * the ORB.
275 */
276 private void resolveListenerAddress() {
277 // now provide defaults for anything still needing resolving
278 if (host == null) {
279 try {
280 host = InetAddress.getLocalHost().getHostName();
281 } catch (UnknownHostException e) {
282 // just punt an use localhost as an absolute fallback.
283 host = "localhost";
284 }
285 }
286
287 // if nothing has been explicitly specified, we use a port value of -1, which
288 // allows the ORB to allocate the address.
289
290 // if we have a config with a TSSSSLTransportConfig defined, the
291 // host and port from the config override bean-configured values.
292 if (tssConfig != null) {
293 TSSTransportMechConfig transportMech = tssConfig.getTransport_mech();
294 if (transportMech != null) {
295 if (transportMech instanceof TSSSSLTransportConfig) {
296 TSSSSLTransportConfig transportConfig = (TSSSSLTransportConfig) transportMech;
297 transportConfig.setHostname(host);
298 transportConfig.setPort((short)listenerPort);
299 }
300 }
301 }
302
303 }
304
305 /**
306 * Return the retrieval URI for this bean.
307 *
308 * @return The URI for the bean AbstractName;
309 */
310 public String getURI() {
311 return abstractName.toString();
312 }
313
314 /**
315 * Get the configured listener port.
316 *
317 * @return The configeration port value.
318 */
319 public int getPort() {
320 return listenerPort;
321 }
322
323 /**
324 * Get the configuration host name.
325 *
326 * @return The configuration host name. The default is "localhost".
327 */
328 public String getHost() {
329 return host;
330 }
331
332 /**
333 * Set a set of policy overrides to be used with
334 * this ORB instance. These are normally set by
335 * the ORBConfigAdapter instance when the ORB
336 * is created.
337 *
338 * @param overrides The new override list.
339 */
340 public void setPolicyOverrides(Policy[] overrides) {
341 policyOverrides = overrides;
342 }
343
344 /**
345 * Add the policy overrides (if any) to the list
346 * of policies used to create a POA instance.
347 *
348 * @param policies The base set of policies.
349 *
350 * @return A new Policy array with the overrides added. Returns
351 * the same array if no overrides are required.
352 */
353 public Policy[] addPolicyOverrides(Policy[] policies) {
354 // just return the same list of no overrides exist
355 if (policyOverrides == null) {
356 return policies;
357 }
358
359 Policy[] newPolicies = new Policy[policies.length + policyOverrides.length];
360
361 System.arraycopy(policies, 0, newPolicies, 0, policies.length);
362 System.arraycopy(policyOverrides, 0, newPolicies, policies.length, policyOverrides.length);
363
364 return newPolicies;
365 }
366 }