001: package org.jacorb.orb.giop;
002:
003: /*
004: * JacORB - a free Java ORB
005: *
006: * Copyright (C) 1997-2004 Gerald Brose.
007: *
008: * This library is free software; you can redistribute it and/or
009: * modify it under the terms of the GNU Library General Public
010: * License as published by the Free Software Foundation; either
011: * version 2 of the License, or (at your option) any later version.
012: *
013: * This library is distributed in the hope that it will be useful,
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
016: * Library General Public License for more details.
017: *
018: * You should have received a copy of the GNU Library General Public
019: * License along with this library; if not, write to the Free
020: * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
021: */
022:
023: import java.util.ArrayList;
024: import java.util.Collections;
025: import java.util.HashMap;
026: import java.util.Iterator;
027: import java.util.List;
028: import java.util.Map;
029:
030: import org.apache.avalon.framework.configuration.Configurable;
031: import org.apache.avalon.framework.configuration.Configuration;
032: import org.apache.avalon.framework.configuration.ConfigurationException;
033: import org.apache.avalon.framework.logger.Logger;
034: import org.jacorb.orb.DefaultProfileSelector;
035: import org.jacorb.orb.ORB;
036: import org.jacorb.orb.ProfileSelector;
037: import org.jacorb.orb.diop.DIOPFactories;
038: import org.jacorb.orb.factory.SocketFactoryManager;
039: import org.jacorb.orb.giop.TransportListener.Event;
040: import org.jacorb.util.ObjectUtil;
041: import org.omg.CORBA.BAD_PARAM;
042: import org.omg.ETF.Factories;
043:
044: /**
045: * This class manages Transports. On the one hand it creates them, and
046: * on the other it enforces an upper limit on the open transports.
047: *
048: * The class also receives notifications from threads that are about do use a
049: * Transport and notifies any interested listeners. "Use" is defined as
050: * sending (or handling) a request.
051: *
052: * @author Nicolas Noffke
053: * @version $Id: TransportManager.java,v 1.28 2006/08/16 17:46:36 iliyan.jeliazkov Exp $
054: * */
055:
056: public class TransportManager implements Configurable {
057: /** the configuration object */
058: private org.jacorb.config.Configuration configuration = null;
059:
060: /** configuration properties */
061: private Logger logger = null;
062: private List factoryClassNames = null;
063: private ProfileSelector profileSelector = null;
064: private final SocketFactoryManager socketFactoryManager;
065:
066: /**
067: * Maps ETF Profile tags (Integer) to ETF Factories objects.
068: */
069: private Map factoriesMap = null;
070:
071: /**
072: * List of all installed ETF Factories. This list contains an
073: * instance of each Factories class, ordered in the same way as
074: * they were specified in the jacorb.transport.factories property.
075: */
076: private List factoriesList = null;
077:
078: /**
079: * The first listener (in a chain of instances), representing
080: * parties with interest in Transport events.
081: */
082: private TransportListener listener = null;
083:
084: public TransportManager(ORB orb) {
085: socketFactoryManager = new SocketFactoryManager(orb);
086: }
087:
088: public void configure(Configuration myConfiguration)
089: throws ConfigurationException {
090: this .configuration = (org.jacorb.config.Configuration) myConfiguration;
091: logger = configuration.getNamedLogger("jacorb.orb.giop");
092: socketFactoryManager.configure(configuration);
093:
094: // get factory class names
095: factoryClassNames = this .configuration
096: .getAttributeList("jacorb.transport.factories");
097:
098: if (factoryClassNames.isEmpty()) {
099: factoryClassNames.add("org.jacorb.orb.iiop.IIOPFactories");
100: }
101:
102: // get profile selector info
103: profileSelector = (ProfileSelector) configuration
104: .getAttributeAsObject("jacorb.transport.client.selector");
105:
106: if (profileSelector == null) {
107: profileSelector = new DefaultProfileSelector();
108: }
109: }
110:
111: public ProfileSelector getProfileSelector() {
112: return profileSelector;
113: }
114:
115: public SocketFactoryManager getSocketFactoryManager() {
116: return socketFactoryManager;
117: }
118:
119: /**
120: * Returns an ETF Factories object for the given tag, or null
121: * if no Factories class has been defined for this tag.
122: */
123: public synchronized org.omg.ETF.Factories getFactories(int tag) {
124: // This isn't ideal. If DIOPFactories was a full implementation then
125: // this class should be added to the
126: // TransportManager::loadFactories. This shortcut block (which is used
127: // by ParsedIOR) and the static caching in DIOPFactories wouldn't be
128: // needed.
129: if (tag == DIOPFactories.TAG_DIOP_UDP) {
130: return DIOPFactories.getDIOPFactory();
131: }
132:
133: if (factoriesMap == null) {
134: loadFactories();
135: }
136: return (Factories) factoriesMap.get(ObjectUtil.newInteger(tag));
137: }
138:
139: /**
140: * Returns a list of Factories for all configured transport plugins,
141: * in the same order as they were specified in the
142: * jacorb.transport.factories property.
143: */
144: public synchronized List getFactoriesList() {
145: if (factoriesList == null) {
146: loadFactories();
147: }
148: return Collections.unmodifiableList(factoriesList);
149: }
150:
151: /**
152: * Build the factoriesMap and factoriesList.
153: */
154: private void loadFactories() {
155: if (configuration == null) {
156: throw new org.omg.CORBA.BAD_INV_ORDER(
157: "TransportManager not configured!");
158: }
159:
160: if (factoryClassNames == null) {
161: throw new org.omg.CORBA.INTERNAL(
162: "factoryClassNames may not be null");
163: }
164:
165: factoriesMap = new HashMap();
166: factoriesList = new ArrayList();
167:
168: for (Iterator i = factoryClassNames.iterator(); i.hasNext();) {
169: String className = (String) i.next();
170: Factories factories = instantiateFactories(className);
171: factoriesMap.put(new Integer(factories.profile_tag()),
172: factories); // NOPMD
173: factoriesList.add(factories);
174: }
175: }
176:
177: /**
178: * Instantiates the given Factories class.
179: */
180: private org.omg.ETF.Factories instantiateFactories(String className) {
181: try {
182: // ObjectUtil.classForName() uses the context class loader.
183: // This is important here because JacORB might be on the
184: // bootclasspath, and the external transport on the normal
185: // classpath.
186: Class clazz = ObjectUtil.classForName(className);
187: Object instance = clazz.newInstance();
188:
189: if (instance instanceof Configurable) {
190: Configurable configurable = (Configurable) instance;
191: configurable.configure(configuration);
192: }
193:
194: logger.debug("created org.omg.ETF.Factories: " + className);
195:
196: return (Factories) instance;
197: } catch (Exception e) {
198: throw new BAD_PARAM(
199: "could not instantiate Factories class "
200: + className + ", exception: " + e);
201: }
202: }
203:
204: public void notifyTransportListeners(GIOPConnection giopc) {
205:
206: if (listener != null) {
207: listener.transportSelected(new Event(giopc));
208: }
209: }
210:
211: public void addTransportListener(TransportListener tl) {
212:
213: if (logger.isInfoEnabled()) {
214: logger.info("Transport listener to add: " + tl);
215: }
216:
217: if (tl != null) {
218: addTransportListenerImpl(tl);
219: }
220: }
221:
222: private synchronized void addTransportListenerImpl(
223: final TransportListener tl) {
224:
225: if (listener == null) {
226: listener = tl;
227: } else {
228:
229: listener = new TransportListener() {
230:
231: private final TransportListener next_ = listener;
232:
233: public void transportSelected(Event event) {
234:
235: try {
236: tl.transportSelected(event);
237: } finally {
238: next_.transportSelected(event);
239: }
240: }
241: };
242: }
243: }
244:
245: }
|