001: /*
002: * JacORB - a free Java ORB
003: *
004: * Copyright (C) The JacORB project, 1997-2006.
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Library General Public
008: * License as published by the Free Software Foundation; either
009: * version 2 of the License, or (at your option) any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Library General Public License for more details.
015: *
016: * You should have received a copy of the GNU Library General Public
017: * License along with this library; if not, write to the Free
018: * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
019: */
020:
021: package org.jacorb.orb;
022:
023: import java.util.ArrayList;
024: import java.util.Iterator;
025: import java.util.List;
026:
027: import org.apache.avalon.framework.configuration.Configurable;
028: import org.apache.avalon.framework.configuration.Configuration;
029: import org.apache.avalon.framework.configuration.ConfigurationException;
030: import org.apache.avalon.framework.logger.Logger;
031: import org.jacorb.orb.giop.GIOPConnection;
032: import org.jacorb.orb.giop.GIOPConnectionManager;
033: import org.jacorb.orb.giop.MessageReceptorPool;
034: import org.jacorb.orb.giop.NoBiDirServerReplyListener;
035: import org.jacorb.orb.giop.ReplyListener;
036: import org.jacorb.orb.giop.RequestListener;
037: import org.jacorb.orb.giop.ServerRequestListener;
038: import org.jacorb.orb.giop.TransportManager;
039: import org.jacorb.orb.iiop.IIOPAddress;
040: import org.jacorb.orb.iiop.IIOPListener;
041: import org.jacorb.orb.iiop.IIOPProfile;
042: import org.omg.CORBA.INTERNAL;
043: import org.omg.ETF.Connection;
044: import org.omg.ETF.Factories;
045: import org.omg.ETF.Listener;
046:
047: /**
048: * Class BasicAdapter, used by the POA.
049: *
050: * @author Gerald Brose
051: * @version $Id: BasicAdapter.java,v 1.59 2006/07/13 08:57:36 nick.cross Exp $
052: */
053: public class BasicAdapter extends org.omg.ETF._HandleLocalBase
054: implements Configurable {
055: private final List listeners = new ArrayList();
056:
057: private MessageReceptorPool receptor_pool = null;
058: private final ServerRequestListener request_listener;
059: private ReplyListener reply_listener = null;
060:
061: private final TransportManager transport_manager;
062: private final GIOPConnectionManager giop_connection_manager;
063:
064: /** the configuration object */
065: private org.jacorb.config.Configuration configuration = null;
066: private Logger logger = null;
067:
068: private final ORB orb;
069:
070: BasicAdapter(org.jacorb.orb.ORB orb, org.jacorb.poa.POA poa,
071: TransportManager transport_manager,
072: GIOPConnectionManager giop_connection_manager) {
073: super ();
074:
075: this .orb = orb;
076: this .transport_manager = transport_manager;
077: this .giop_connection_manager = giop_connection_manager;
078: request_listener = new ServerRequestListener(orb, poa);
079: }
080:
081: /**
082: * configure the BasicAdapter
083: */
084:
085: public void configure(Configuration myConfiguration)
086: throws ConfigurationException {
087: configuration = (org.jacorb.config.Configuration) myConfiguration;
088: logger = configuration.getNamedLogger("jacorb.orb.basic");
089:
090: receptor_pool = new MessageReceptorPool("server",
091: "ServerMessageReceptor", myConfiguration);
092:
093: request_listener.configure(configuration);
094: reply_listener = new NoBiDirServerReplyListener();
095:
096: // create all Listeners
097: for (Iterator i = getListenerFactories().iterator(); i
098: .hasNext();) {
099: Factories factories = (Factories) i.next();
100: Listener listener = factories.create_listener(null,
101: (short) 0, (short) 0);
102: listener.set_handle(this );
103: listeners.add(listener);
104: }
105:
106: // activate them
107: for (Iterator i = listeners.iterator(); i.hasNext();) {
108: ((Listener) i.next()).listen();
109: }
110: }
111:
112: /**
113: * Returns a List of Factories for all transport plugins that
114: * should listen for incoming connections.
115: */
116: private List getListenerFactories() {
117: List result = new ArrayList();
118: List tags = configuration
119: .getAttributeList("jacorb.transport.server.listeners");
120:
121: if (tags.isEmpty()) {
122: result.addAll(transport_manager.getFactoriesList());
123: } else {
124: for (Iterator i = tags.iterator(); i.hasNext();) {
125: String s = ((String) i.next());
126: int tag = -1;
127: try {
128: tag = Integer.parseInt(s);
129: } catch (NumberFormatException ex) {
130: throw new IllegalArgumentException(
131: "could not parse profile tag for listener: "
132: + s
133: + " (should have been a number)");
134: }
135: Factories factories = transport_manager
136: .getFactories(tag);
137: if (factories == null) {
138: throw new IllegalArgumentException(
139: "could not find Factories for profile tag: "
140: + tag);
141: }
142:
143: result.add(factories);
144: }
145: }
146: return result;
147: }
148:
149: public RequestListener getRequestListener() {
150: return request_listener;
151: }
152:
153: /**
154: * Returns a List of endpoint profiles for all transports that listen
155: * for incoming connections. Each individual profile is a copy and can
156: * safely be modified by the caller (e.g. add an object key, patch the
157: * address, stuff it into an IOR, etc.).
158: */
159: public List getEndpointProfiles() {
160: List result = new ArrayList();
161: for (Iterator i = listeners.iterator(); i.hasNext();) {
162: Listener listener = (Listener) i.next();
163: result.add(listener.endpoint());
164: }
165: return result;
166: }
167:
168: /**
169: * If only a single IIOPListener (and no other Listener) is
170: * active for this BasicAdapter, then this method returns it.
171: * Otherwise it returns null.
172: */
173: private IIOPListener getIIOPListener() {
174: if (listeners.size() == 1) {
175: Listener listener = (Listener) listeners.get(0);
176: if (listener instanceof IIOPListener) {
177: return (IIOPListener) listener;
178: }
179: return null;
180: }
181:
182: return null;
183: }
184:
185: /**
186: * @deprecated This method cannot return a sensible result in the presence
187: * of alternate transports, use {@link #getEndpointProfiles()} instead.
188: */
189: public int getPort() {
190: IIOPListener l = getIIOPListener();
191: if (l != null) {
192: IIOPProfile profile = (IIOPProfile) l.endpoint();
193: return ((IIOPAddress) profile.getAddress()).getPort();
194: }
195:
196: throw new RuntimeException(
197: "Cannot find server port for non-IIOP transport");
198: }
199:
200: /**
201: * @deprecated This method cannot return a sensible result in the presence
202: * of alternate transports, use {@link #getEndpointProfiles()} instead.
203: */
204: public int getSSLPort() {
205: IIOPListener listener = getIIOPListener();
206: if (listener != null) {
207: return ((IIOPProfile) listener.endpoint()).getSSLPort();
208: }
209:
210: throw new RuntimeException(
211: "Non-IIOP transport does not have an SSL port");
212: }
213:
214: /**
215: * @deprecated This method cannot return a sensible result in the presence
216: * of alternate transports, use {@link #getEndpointProfiles()} instead.
217: */
218: public boolean hasSSLListener() {
219: return getSSLPort() != -1;
220: }
221:
222: /**
223: * @deprecated This method cannot return a sensible result in the presence
224: * of alternate transports, use {@link #getEndpointProfiles()} instead.
225: */
226: public String getAddress() {
227: IIOPListener l = getIIOPListener();
228: if (l != null) {
229: IIOPProfile profile = (IIOPProfile) l.endpoint();
230: return ((IIOPAddress) profile.getAddress()).getHostname();
231: }
232:
233: throw new RuntimeException(
234: "Cannot find server address for non-IIOP transport");
235: }
236:
237: /**
238: * to be called from the POA, code duplicated for performance
239: * reasons to avoid synchronization in the private version of this
240: * method.
241: */
242: public void deliverRequest(
243: org.jacorb.orb.dsi.ServerRequest request,
244: org.omg.PortableServer.POA poa) {
245: org.jacorb.poa.POA tmp_poa = (org.jacorb.poa.POA) poa;
246: String scopes[] = request.remainingPOAName();
247:
248: try {
249: for (int i = 0; i < scopes.length - 1; i++) {
250: if (scopes[i].equals("")) {
251: request.setRemainingPOAName(null);
252: break;
253: }
254: try {
255: tmp_poa = tmp_poa._getChildPOA(scopes[i]);
256: } catch (org.jacorb.poa.except.ParentIsHolding p) {
257: /*
258: * if one of the POAs is in holding state, we
259: * simply deliver deliver the request to this
260: * POA. It will forward the request to its child
261: * POAs if necessary when changing back to active
262: * For the POA to be able to forward this request
263: * to its child POAa, we need to supply the
264: * remaining part of the child's POA name
265: */
266: String[] rest_of_name = new String[scopes.length
267: - i];
268: for (int j = 0; j < i; j++) {
269: rest_of_name[j] = scopes[j + i];
270: }
271: request.setRemainingPOAName(rest_of_name);
272: break;
273: }
274: }
275:
276: if (tmp_poa == null) {
277: throw new INTERNAL("Request POA null!");
278: }
279:
280: /* hand over to the POA */
281: tmp_poa._invoke(request);
282:
283: } catch (org.omg.PortableServer.POAPackage.WrongAdapter e) {
284: // unknown oid (not previously generated)
285: request
286: .setSystemException(new org.omg.CORBA.OBJECT_NOT_EXIST(
287: "unknown oid"));
288: request.reply();
289: } catch (org.omg.CORBA.SystemException e) {
290: request.setSystemException(e);
291: request.reply();
292: } catch (RuntimeException e) {
293: request.setSystemException(new org.omg.CORBA.UNKNOWN(e
294: .toString()));
295: request.reply();
296: logger.warn("unexpected exception", e);
297: } catch (Throwable e) {
298: // TODO in general its not advisable
299: // to catch Throwable as this also includes
300: // Errors (e.g. OutOfMemoryError)
301: // TODO throw exception?
302: request.setSystemException(new org.omg.CORBA.UNKNOWN(e
303: .toString()));
304: request.reply();
305: logger.error("unexpected exception", e);
306: }
307: }
308:
309: /**
310: * to be called from the POA
311: */
312:
313: public void return_result(org.jacorb.orb.dsi.ServerRequest request) {
314: request.reply();
315: }
316:
317: public void stopListeners() {
318: for (Iterator i = listeners.iterator(); i.hasNext();) {
319: ((Listener) i.next()).destroy();
320: }
321: receptor_pool.shutdown();
322: }
323:
324: /**
325: * Tell all IIOPListeners to renew their SSL server sockets.
326: *
327: * @see IIOPListener#renewSSLServerSocket
328: */
329: public void renewSSLServerSockets() {
330: for (Iterator i = listeners.iterator(); i.hasNext();) {
331: Object o = i.next();
332: if (o instanceof IIOPListener) {
333: ((IIOPListener) o).renewSSLServerSocket();
334: }
335: }
336: }
337:
338: // Handle methods below this line
339:
340: /**
341: * Announces a new connection instance to the ORB.
342: * The caller shall examine the boolean return value and
343: * destroy the connection, if the call returns false.
344: * A new connection initially belongs to the plug-in,
345: * and it shall signal the connection to the ORB when
346: * the first incoming request data was received,
347: * using this Handle upcall.
348: * <p>
349: * The Handle shall accept the connection (and cache
350: * information about it if needed), as long as it is
351: * allowed to do so by the ORB. In this case it shall
352: * return true. If a new connection is currently not
353: * allowed, it shall ignore the passed instance and
354: * return false.
355: */
356: public boolean add_input(org.omg.ETF.Connection conn) {
357: GIOPConnection giopConnection = giop_connection_manager
358: .createServerGIOPConnection(conn.get_server_profile(),
359: conn, request_listener, reply_listener);
360: receptor_pool.connectionCreated(giopConnection);
361: return true;
362: }
363:
364: /**
365: * In some cases, the client side can initiate the closing of a
366: * connection. The plugin shall signal this event to the server side
367: * ORB via its Handle by calling this function.
368: */
369: public void closed_by_peer(org.omg.ETF.Connection conn) {
370: // We don't do this in JacORB; Connections are never
371: // given back to the Listener after they have been
372: // passed up initially.
373: throw new org.omg.CORBA.NO_IMPLEMENT();
374: }
375:
376: /**
377: * The plugged-in transport (e.g. the Listener instance) shall call
378: * this function when it owns a server-side Connection and data arrives
379: * on the local endpoint. This will start a new request dispatching
380: * cycle in the ORB. Subsequently, it shall ignore any other incoming
381: * data from this Connection until the Listener's completed_data function
382: * is called by the ORB.
383: */
384: public void signal_data_available(Connection conn) {
385: // We don't do this in JacORB; Connections are never
386: // given back to the Listener after they have been
387: // passed up initially.
388: throw new org.omg.CORBA.NO_IMPLEMENT();
389: }
390:
391: public ORB getORB() {
392: return orb;
393: }
394: }
|