Remove old autovect-branch by moving to "dead" directory.
[official-gcc.git] / old-autovect-branch / libjava / classpath / gnu / CORBA / OrbFunctional.java
blob7b9c34ada123027b09acc379a6d94baddd0755aa
1 /* OrbFunctional.java --
2 Copyright (C) 2005 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package gnu.CORBA;
41 import gnu.CORBA.CDR.UnknownExceptionCtxHandler;
42 import gnu.CORBA.CDR.BufferredCdrInput;
43 import gnu.CORBA.CDR.BufferedCdrOutput;
44 import gnu.CORBA.GIOP.CloseMessage;
45 import gnu.CORBA.GIOP.ErrorMessage;
46 import gnu.CORBA.GIOP.MessageHeader;
47 import gnu.CORBA.GIOP.ReplyHeader;
48 import gnu.CORBA.GIOP.RequestHeader;
49 import gnu.CORBA.NamingService.NameParser;
50 import gnu.CORBA.NamingService.NamingServiceTransient;
51 import gnu.CORBA.Poa.gnuForwardRequest;
52 import gnu.CORBA.interfaces.SocketFactory;
54 import org.omg.CORBA.BAD_OPERATION;
55 import org.omg.CORBA.BAD_PARAM;
56 import org.omg.CORBA.CompletionStatus;
57 import org.omg.CORBA.MARSHAL;
58 import org.omg.CORBA.NO_RESOURCES;
59 import org.omg.CORBA.OBJECT_NOT_EXIST;
60 import org.omg.CORBA.Request;
61 import org.omg.CORBA.SystemException;
62 import org.omg.CORBA.UNKNOWN;
63 import org.omg.CORBA.WrongTransaction;
64 import org.omg.CORBA.ORBPackage.InvalidName;
65 import org.omg.CORBA.portable.Delegate;
66 import org.omg.CORBA.portable.InvokeHandler;
67 import org.omg.CORBA.portable.ObjectImpl;
68 import org.omg.CORBA.portable.UnknownException;
69 import org.omg.CosNaming.NamingContextExt;
70 import org.omg.CosNaming.NamingContextExtHelper;
72 import java.applet.Applet;
73 import java.io.IOException;
74 import java.io.InputStream;
75 import java.io.OutputStream;
76 import java.net.InetAddress;
77 import java.net.ServerSocket;
78 import java.net.Socket;
79 import java.net.SocketException;
80 import java.net.UnknownHostException;
81 import java.util.ArrayList;
82 import java.util.Enumeration;
83 import java.util.Hashtable;
84 import java.util.Iterator;
85 import java.util.LinkedList;
86 import java.util.Map;
87 import java.util.Properties;
88 import java.util.Random;
89 import java.util.StringTokenizer;
90 import java.util.TreeMap;
92 /**
93 * The ORB implementation, capable to handle remote invocations on the
94 * registered object. This class implements all features, required till the jdk
95 * 1.3 inclusive, but does not support the POA that appears since 1.4. The POA
96 * is supported by {@link gnu.CORBA.Poa.ORB_1_4}.
98 * @author Audrius Meskauskas (AudriusA@Bioinformatics.org)
100 public class OrbFunctional extends OrbRestricted
103 * A server, responsible for listening on requests on some local port. The ORB
104 * may listen on multiple ports and process the requests in separate threads.
105 * Normally the server takes one port per object being served.
107 protected class portServer
108 extends Thread
111 * The number of the currently running parallel threads.
113 int running_threads;
116 * The port on that this portServer is listening for requests.
118 int s_port;
121 * The server socket of this portServer.
123 ServerSocket service;
126 * True if the serving node must shutdown due call of the close_now().
128 boolean terminated;
131 * Create a new portServer, serving on specific port.
133 portServer(int _port)
135 s_port = _port;
136 setDaemon(true);
139 service = socketFactory.createServerSocket(s_port);
141 catch (IOException ex)
143 BAD_OPERATION bad = new BAD_OPERATION(
144 "Unable to open the server socket at " + s_port);
145 bad.minor = Minor.Socket;
146 bad.initCause(ex);
147 throw bad;
152 * Enter the serving loop (get request/process it). All portServer normally
153 * terminate thy threads when the OrbFunctional.running is set to false.
155 public void run()
157 while (running)
161 tick();
163 catch (SocketException ex)
165 // May be thrown when the service is closed by
166 // the close_now().
167 if (terminated)
168 return;
170 catch (Exception iex)
172 // Wait. Do not terminate the
173 // service due potentially transient error.
176 Thread.sleep(TWAIT_SERVER_ERROR_PAUSE);
178 catch (InterruptedException ex)
186 * Perform a single serving step.
188 * @throws java.lang.Exception
190 void tick()
191 throws Exception
193 serve(this, service);
197 * Forcibly close the server socket and mark this port as free.
199 public void close_now()
203 terminated = true;
204 service.close();
206 catch (Exception ex)
208 // This may happen if the service has not been opened or
209 // cannot be closed. Return without action.
214 * If the thread is no longer in use, close the socket (if opened).
216 protected void finalize()
218 close_now();
223 * A server, responsible for listening on requests on some local port and
224 * serving multiple requests (probably to the different objects) on the same
225 * thread.
227 protected class sharedPortServer extends portServer
230 * Create a new portServer, serving on specific port.
232 sharedPortServer(int _port)
234 super(_port);
238 * Perform a single serving step.
240 * @throws java.lang.Exception
242 void tick() throws Exception
244 Socket request = service.accept();
245 serveStep(request, false);
250 * The default value where the first instance of this ORB will start looking
251 * for a free port.
253 public static int DEFAULT_INITIAL_PORT = 1126;
256 * When trying to open the socket on a random port, start of the interval to
257 * try.
259 public static int RANDOM_PORT_FROM = 1024;
262 * When trying to open the socket on a random port, end of the interval to
263 * try.
265 public static int RANDOM_PORT_TO = 4024;
268 * The number of attempts to try when opening random port.
270 public static int RANDOM_PORT_ATTEMPTS = 64;
273 * The property of port, on that this ORB is listening for requests from
274 * clients. This class supports one port per ORB only.
276 public static final String LISTEN_ON = "gnu.classpath.CORBA.ListenOn";
279 * The property, defining the IOR of the intial reference to resolve.
281 public static final String REFERENCE = "org.omg.CORBA.ORBInitRef";
284 * The property, defining the port on that the default name service is
285 * running.
287 public static final String NS_PORT = "org.omg.CORBA.ORBInitialPort";
290 * The property, defining the host on that the default name service is
291 * running.
293 public static final String NS_HOST = "org.omg.CORBA.ORBInitialHost";
296 * The string, defining the naming service initial reference.
298 public static final String NAME_SERVICE = "NameService";
301 * Defines the ORB ID that is accessible by IOR interceptors.
303 public static final String ORB_ID = "org.omg.CORBA.ORBid";
307 * Defines the SERVER ID that is accessible by IOR interceptors.
309 public static final String SERVER_ID = "org.omg.CORBA.ServerId";
312 * The if the client has once opened a socket, it should start sending the
313 * message header in a given time. Otherwise the server will close the socket.
314 * This prevents server hang when the client opens the socket, but does not
315 * send any message, usually due crash on the client side.
317 public static String START_READING_MESSAGE =
318 "gnu.classpath.CORBA.TOUT_START_READING_MESSAGE";
321 * If the client has started to send the request message, the socket time out
322 * changes to the specified value.
324 public static String WHILE_READING =
325 "gnu.classpath.CORBA.TOUT_WHILE_READING";
328 * If the message body is received, the time out changes to the specifice
329 * value. This must be longer, as includes time, required to process the
330 * received task. We make it 40 minutes.
332 public static String AFTER_RECEIVING =
333 "gnu.classpath.CORBA.TOUT_AFTER_RECEIVING";
336 * The server waits for this duration after the potentially transient error
337 * during its servicing cycle.
339 public static String SERVER_ERROR_PAUSE =
340 "gnu.classpath.CORBA.SERVER_ERROR_PAUSE";
343 * The address of the local host.
345 public final String LOCAL_HOST;
348 * The if the client has once opened a socket, it should start sending the
349 * message header in a given time. Otherwise the server will close the socket.
350 * This prevents server hang when the client opens the socket, but does not
351 * send any message, usually due crash on the client side.
353 public int TOUT_START_READING_MESSAGE = 20 * 1000;
355 // (Here and below, we use * to make the meaning of the constant clearler).
358 * If the client has started to send the request message, the socket time out
359 * changes to the specified value.
361 public int TOUT_WHILE_READING = 2 * 60 * 1000;
364 * If the message body is received, the time out changes to the specifice
365 * value. This must be longer, as includes time, required to process the
366 * received task. We make it 40 minutes.
368 public int TOUT_AFTER_RECEIVING = 40 * 60 * 1000;
371 * The server waits for this duration after the potentially transient error
372 * during its servicing cycle.
374 public int TWAIT_SERVER_ERROR_PAUSE = 5000;
377 * Some clients tend to submit multiple requests over the same socket. The
378 * server waits for the next request on the same socket for the duration,
379 * specified below. In additions, the request of this implementation also
380 * waits for the same duration before closing the socket. The default time is
381 * seven seconds.
383 public static int TANDEM_REQUESTS = 7000;
386 * The Id of this ORB.
388 public String orb_id = "orb_"+hashCode();
391 * The Id of this Server. This field is defined static to ensure it has
392 * the same value over all ORB's in this machine.
394 public static String server_id = "server_"+OrbFunctional.class.hashCode();
397 * The map of the already conncted objects.
399 protected final Connected_objects connected_objects =
400 new Connected_objects();
403 * The maximal CORBA version, supported by this ORB. The default value 0 means
404 * that the ORB will not check the request version while trying to respond.
406 protected Version max_version;
409 * Setting this value to false causes the ORB to shutdown after the latest
410 * serving operation is complete.
412 protected boolean running;
415 * The map of the initial references.
417 protected Map initial_references = new TreeMap();
420 * The currently active portServers.
422 protected ArrayList portServers = new ArrayList();
425 * The host, on that the name service is expected to be running.
427 private String ns_host;
430 * Probably free port, under that the ORB will try listening for remote
431 * requests first. When the new object is connected, this port is used first,
432 * then it is incremented by 1, etc. If the given port is not available, up to
433 * 20 subsequent values are tried and then the parameterless server socket
434 * contructor is called. The constant is shared between multiple instances of
435 * this ORB.
437 private static int Port = DEFAULT_INITIAL_PORT;
440 * The port, on that the name service is expected to be running.
442 private int ns_port = 900;
445 * The name parser.
447 NameParser nameParser = new NameParser();
450 * The instance, stored in this field, handles the asynchronous dynamic
451 * invocations.
453 protected Asynchron asynchron = new Asynchron();
456 * The list of the freed ports. The ORB reuses ports, when possible.
458 protected LinkedList freed_ports = new LinkedList();
461 * Maps a single-threaded POAs to they sharedPortServants.
463 protected Hashtable identities = new Hashtable();
466 * The maximal allowed number of the currently running parallel threads per
467 * object. For security reasons, this is made private and unchangeable. After
468 * exceeding this limit, the NO_RESOURCES is thrown back to the client.
470 private int MAX_RUNNING_THREADS = 256;
473 * The producer of the client and server sockets for this ORB.
475 public SocketFactory socketFactory = DefaultSocketFactory.Singleton;
478 * Create the instance of the Functional ORB.
480 public OrbFunctional()
484 LOCAL_HOST = ns_host = InetAddress.getLocalHost().getHostAddress();
485 initial_references.put("CodecFactory", new gnuCodecFactory(this));
487 catch (UnknownHostException ex)
489 BAD_OPERATION bad =
490 new BAD_OPERATION("Unable to open the server socket.");
491 bad.initCause(ex);
492 throw bad;
497 * If the max version is assigned, the orb replies with the error message if
498 * the request version is above the supported 1.2 version. This behavior is
499 * recommended by OMG, but not all implementations respond that error message
500 * by re-sending the request, encoded in the older version.
502 public void setMaxVersion(Version max_supported)
504 max_version = max_supported;
508 * Get the maximal supported GIOP version or null if the version is not
509 * checked.
511 public Version getMaxVersion()
513 return max_version;
517 * Get the currently free port, starting from the initially set port and going
518 * up max 20 steps, then trying to bind into any free address.
520 * @return the currently available free port.
522 * @throws NO_RESOURCES if the server socked cannot be opened on the local
523 * host.
525 public int getFreePort()
526 throws BAD_OPERATION
528 ServerSocket s;
529 int a_port;
533 // If there are some previously freed ports, use them first.
534 if (!freed_ports.isEmpty())
536 Integer free = (Integer) freed_ports.getLast();
537 freed_ports.removeLast();
538 s = socketFactory.createServerSocket(free.intValue());
539 s.close();
540 return free.intValue();
543 catch (Exception ex)
545 // This may be thrown if the request for the new port has arrived
546 // before the current service is completly shutdown.
547 // OK then, use a new port.
550 for (a_port = Port; a_port < Port + 20; a_port++)
554 s = socketFactory.createServerSocket(a_port);
555 s.close();
556 Port = a_port + 1;
557 return a_port;
559 catch (IOException ex)
561 // Repeat the loop if this exception has been thrown.
565 Random rand = new Random();
566 // Try any random port in the interval RANDOM_PORT_FROM.RANDOM_PORT_TO.
567 int range = RANDOM_PORT_TO - RANDOM_PORT_FROM;
568 IOException ioex = null;
569 for (int i = 0; i < RANDOM_PORT_ATTEMPTS; i++)
573 a_port = RANDOM_PORT_FROM + rand.nextInt(range);
574 s = socketFactory.createServerSocket(a_port);
575 s.close();
576 return a_port;
578 catch (IOException ex)
580 // Repeat the loop if this exception has been thrown.
581 ioex = ex;
585 NO_RESOURCES bad = new NO_RESOURCES("Unable to open the server socket.");
586 bad.minor = Minor.Ports;
587 if (ioex != null)
588 bad.initCause(ioex);
589 throw bad;
593 * Set the port, on that the server is listening for the client requests. If
594 * only one object is connected to the orb, the server will be try listening
595 * on this port first. It the port is busy, or if more objects are connected,
596 * the subsequent object will receive a larger port values, skipping
597 * unavailable ports, if required. The change applies globally.
599 * @param a_Port a port, on that the server is listening for requests.
601 public static void setPort(int a_Port)
603 Port = a_Port;
607 * Connect the given CORBA object to this ORB. After the object is connected,
608 * it starts receiving remote invocations via this ORB.
610 * The ORB tries to connect the object to the port, that has been previously
611 * set by {@link setPort(int)}. On failure, it tries 20 subsequent larger
612 * values and then calls the parameterless server socked constructor to get
613 * any free local port. If this fails, the {@link NO_RESOURCES} is thrown.
615 * @param object the object, must implement the {@link InvokeHandler})
616 * interface.
618 * @throws BAD_PARAM if the object does not implement the
619 * {@link InvokeHandler}).
621 public void connect(org.omg.CORBA.Object object)
623 int a_port = getFreePort();
625 Connected_objects.cObject ref = connected_objects.add(object, a_port);
626 IOR ior = createIOR(ref);
627 prepareObject(object, ior);
628 if (running)
629 startService(ior);
633 * Connect the given CORBA object to this ORB, explicitly specifying the
634 * object key.
636 * The ORB tries to connect the object to the port, that has been previously
637 * set by {@link setPort(int)}. On failure, it tries 20 subsequent larger
638 * values and then calls the parameterless server socked constructor to get
639 * any free local port. If this fails, the {@link NO_RESOURCES} is thrown.
641 * @param object the object, must implement the {@link InvokeHandler})
642 * interface.
643 * @param key the object key, usually used to identify the object from remote
644 * side.
646 * @throws BAD_PARAM if the object does not implement the
647 * {@link InvokeHandler}).
649 public void connect(org.omg.CORBA.Object object, byte[] key)
651 int a_port = getFreePort();
653 Connected_objects.cObject ref =
654 connected_objects.add(key, object, a_port, null);
655 IOR ior = createIOR(ref);
656 prepareObject(object, ior);
657 if (running)
658 startService(ior);
662 * Connect the given CORBA object to this ORB, explicitly specifying the
663 * object key and the identity of the thread (and port), where the object must
664 * be served. The identity is normally the POA.
666 * The new port server will be started only if there is no one already running
667 * for the same identity. Otherwise, the task of the existing port server will
668 * be widened, including duty to serve the given object. All objects,
669 * connected to a single identity by this method, will process they requests
670 * subsequently in the same thread. The method is used when the expected
671 * number of the objects is too large to have a single port and thread per
672 * object. This method is used by POAs, having a single thread policy.
674 * @param object the object, must implement the {@link InvokeHandler})
675 * interface.
676 * @param key the object key, usually used to identify the object from remote
677 * side.
678 * @param port the port, where the object must be connected.
680 * @throws BAD_PARAM if the object does not implement the
681 * {@link InvokeHandler}).
683 public void connect_1_thread(org.omg.CORBA.Object object, byte[] key,
684 java.lang.Object identity
687 sharedPortServer shared = (sharedPortServer) identities.get(identity);
688 if (shared == null)
690 int a_port = getFreePort();
691 shared = new sharedPortServer(a_port);
692 identities.put(identity, shared);
693 if (running)
695 portServers.add(shared);
696 shared.start();
700 Connected_objects.cObject ref =
701 connected_objects.add(key, object, shared.s_port, identity);
702 IOR ior = createIOR(ref);
703 prepareObject(object, ior);
707 * Start the service on the given port of this IOR.
709 * @param ior the ior (only Internet.port is used).
711 public void startService(IOR ior)
713 portServer p = new portServer(ior.Internet.port);
714 portServers.add(p);
715 p.start();
719 * Destroy this server, releasing the occupied resources.
721 public void destroy()
723 portServer p;
724 for (int i = 0; i < portServers.size(); i++)
726 p = (portServer) portServers.get(i);
727 p.close_now();
729 super.destroy();
733 * Disconnect the given CORBA object from this ORB. The object will be no
734 * longer receiving the remote invocations. In response to the remote
735 * invocation on this object, the ORB will send the exception
736 * {@link OBJECT_NOT_EXIST}. The object, however, is not destroyed and can
737 * receive the local invocations.
739 * @param object the object to disconnect.
741 public void disconnect(org.omg.CORBA.Object object)
743 Connected_objects.cObject rmKey = null;
745 // Handle the case when it is possible to get the object key.
746 // Handle the case when the object is known, but not local.
747 if (object instanceof ObjectImpl)
749 Delegate delegate = ((ObjectImpl) object)._get_delegate();
750 if (delegate instanceof SimpleDelegate)
752 byte[] key = ((SimpleDelegate) delegate).getIor().key;
753 rmKey = connected_objects.get(key);
757 // Try to find and disconned the object that is not an instance of the
758 // object implementation.
759 if (rmKey == null)
760 rmKey = connected_objects.getKey(object);
761 if (rmKey != null)
763 // Find and stop the corresponding portServer.
764 portServer p;
765 StopService:
766 for (int i = 0; i < portServers.size(); i++)
768 p = (portServer) portServers.get(i);
769 if (p.s_port == rmKey.port && !(p instanceof sharedPortServer))
771 p.close_now();
772 freed_ports.addFirst(new Integer(rmKey.port));
773 break StopService;
775 connected_objects.remove(rmKey.key);
781 * Notifies ORB that the shared service indentity (usually POA) is destroyed.
782 * The matching shared port server is terminated and the identity table entry
783 * is deleted. If this identity is not known for this ORB, the method returns
784 * without action.
786 * @param identity the identity that has been destroyed.
788 public void identityDestroyed(java.lang.Object identity)
790 if (identity == null)
791 return;
793 sharedPortServer ise = (sharedPortServer) identities.get(identity);
794 if (ise != null)
796 synchronized (connected_objects)
798 ise.close_now();
799 identities.remove(identity);
801 Connected_objects.cObject obj;
802 Map.Entry m;
803 Iterator iter = connected_objects.entrySet().iterator();
804 while (iter.hasNext())
806 m = (Map.Entry) iter.next();
807 obj = (Connected_objects.cObject) m.getValue();
808 if (obj.identity == identity)
809 iter.remove();
816 * Find the local object, connected to this ORB.
818 * @param ior the ior of the potentially local object.
820 * @return the local object, represented by the given IOR, or null if this is
821 * not a local connected object.
823 public org.omg.CORBA.Object find_local_object(IOR ior)
825 // Must be the same host.
826 if (!ior.Internet.host.equals(LOCAL_HOST))
827 return null;
829 return find_connected_object(ior.key, ior.Internet.port);
833 * List the initially available CORBA objects (services).
835 * @return a list of services.
837 * @see resolve_initial_references(String)
839 public String[] list_initial_services()
841 String[] refs = new String[ initial_references.size() ];
842 int p = 0;
844 Iterator iter = initial_references.keySet().iterator();
845 while (iter.hasNext())
847 refs [ p++ ] = (String) iter.next();
849 return refs;
853 * Get the IOR reference string for the given object. The string embeds
854 * information about the object repository Id, its access key and the server
855 * internet address and port. With this information, the object can be found
856 * by another ORB, possibly located on remote computer.
858 * @param the CORBA object
859 * @return the object IOR representation.
861 * @throws BAD_PARAM if the object has not been previously connected to this
862 * ORB.
864 * @throws BAD_OPERATION in the unlikely case if the local host address cannot
865 * be resolved.
867 * @see string_to_object(String)
869 public String object_to_string(org.omg.CORBA.Object forObject)
871 // Handle the case when the object is known, but not local.
872 if (forObject instanceof ObjectImpl)
874 Delegate delegate = ((ObjectImpl) forObject)._get_delegate();
875 if (delegate instanceof SimpleDelegate)
876 return ((SimpleDelegate) delegate).getIor().toStringifiedReference();
879 // Handle the case when the object is local.
880 Connected_objects.cObject rec = connected_objects.getKey(forObject);
882 if (rec == null)
883 throw new BAD_PARAM("The object " + forObject +
884 " has not been previously connected to this ORB"
887 IOR ior = createIOR(rec);
889 return ior.toStringifiedReference();
893 * Get the local IOR for the given object, null if the object is not local.
895 public IOR getLocalIor(org.omg.CORBA.Object forObject)
897 Connected_objects.cObject rec = connected_objects.getKey(forObject);
898 if (rec == null)
899 return null;
900 else
901 return createIOR(rec);
905 * Find and return the easily accessible CORBA object, addressed by name.
907 * @param name the object name.
908 * @return the object
910 * @throws org.omg.CORBA.ORBPackage.InvalidName if the given name is not
911 * associated with the known object.
913 public org.omg.CORBA.Object resolve_initial_references(String name)
914 throws InvalidName
916 org.omg.CORBA.Object object = null;
919 object = (org.omg.CORBA.Object) initial_references.get(name);
920 if (object == null && name.equals(NAME_SERVICE))
922 object = getDefaultNameService();
923 if (object != null)
924 initial_references.put(NAME_SERVICE, object);
927 catch (Exception ex)
929 InvalidName err = new InvalidName(name);
930 err.initCause(ex);
931 throw err;
933 if (object != null)
934 return object;
935 else
936 throw new InvalidName("Not found: '" + name + "'");
940 * Start the ORBs main working cycle (receive invocation - invoke on the local
941 * object - send response - wait for another invocation).
943 * The method only returns after calling {@link #shutdown(boolean)}.
945 public void run()
947 running = true;
949 // Instantiate the port server for each socket.
950 Iterator iter = connected_objects.entrySet().iterator();
951 Map.Entry m;
952 Connected_objects.cObject obj;
954 while (iter.hasNext())
956 m = (Map.Entry) iter.next();
957 obj = (Connected_objects.cObject) m.getValue();
959 portServer subserver;
961 if (obj.identity == null)
963 subserver = new portServer(obj.port);
964 portServers.add(subserver);
966 else
967 subserver = (portServer) identities.get(obj.identity);
969 if (!subserver.isAlive())
971 // Reuse the current thread for the last portServer.
972 if (!iter.hasNext())
974 // Discard the iterator, eliminating lock checks.
975 iter = null;
976 subserver.run();
977 return;
979 else
980 subserver.start();
986 * Start the server in a new thread, if not already running. This method is
987 * used to ensure that the objects being transfered will be served from the
988 * remote side, if required. If the ORB is started using this method, it
989 * starts as a daemon thread.
991 public void ensureRunning()
993 final OrbFunctional THIS = this;
995 if (!running)
997 Thread t = new Thread()
999 public void run()
1001 THIS.run();
1004 t.setDaemon(true);
1005 t.start();
1010 * Shutdown the ORB server.
1012 * @param wait_for_completion if true, the current thread is suspended until
1013 * the shutdown process is complete.
1015 public void shutdown(boolean wait_for_completion)
1017 super.shutdown(wait_for_completion);
1018 running = false;
1020 if (!wait_for_completion)
1022 for (int i = 0; i < portServers.size(); i++)
1024 portServer p = (portServer) portServers.get(i);
1025 p.close_now();
1031 * Find and return the CORBA object, addressed by the given IOR string
1032 * representation. The object can (an usually is) located on a remote
1033 * computer, possibly running a different (not necessary java) CORBA
1034 * implementation.
1036 * @param ior the object IOR representation string.
1038 * @return the found CORBA object.
1039 * @see object_to_string(org.omg.CORBA.Object)
1041 public org.omg.CORBA.Object string_to_object(String an_ior)
1043 return nameParser.corbaloc(an_ior, this);
1047 * Convert ior reference to CORBA object.
1049 public org.omg.CORBA.Object ior_to_object(IOR ior)
1051 org.omg.CORBA.Object object = find_local_object(ior);
1052 if (object == null)
1054 ObjectImpl impl = StubLocator.search(this, ior);
1057 if (impl._get_delegate() == null)
1058 impl._set_delegate(new IorDelegate(this, ior));
1060 catch (BAD_OPERATION ex)
1062 // Some colaborants may throw this exception
1063 // in response to the attempt to get the unset delegate.
1064 impl._set_delegate(new IorDelegate(this, ior));
1067 object = impl;
1068 // TODO remove commented out code below.
1069 // connected_objects.add(ior.key, impl, ior.Internet.port, null);
1071 return object;
1075 * Get the default naming service for the case when there no NameService
1076 * entries.
1078 protected org.omg.CORBA.Object getDefaultNameService()
1080 if (initial_references.containsKey(NAME_SERVICE))
1081 return (org.omg.CORBA.Object) initial_references.get(NAME_SERVICE);
1083 IOR ior = new IOR();
1084 ior.Id = NamingContextExtHelper.id();
1085 ior.Internet.host = ns_host;
1086 ior.Internet.port = ns_port;
1087 ior.key = NamingServiceTransient.getDefaultKey();
1089 IorObject iorc = new IorObject(this, ior);
1090 NamingContextExt namer = NamingContextExtHelper.narrow(iorc);
1091 initial_references.put(NAME_SERVICE, namer);
1092 return namer;
1096 * Find and return the object, that must be previously connected to this ORB.
1097 * Return null if no such object is available.
1099 * @param key the object key.
1100 * @param port the port where the object is connected.
1102 * @return the connected object, null if none.
1104 protected org.omg.CORBA.Object find_connected_object(byte[] key, int port)
1106 Connected_objects.cObject ref = connected_objects.get(key);
1107 if (ref == null)
1108 return null;
1109 if (port >= 0 && ref.port != port)
1110 return null;
1111 else
1112 return ref.object;
1116 * Set the ORB parameters. This method is normally called from
1117 * {@link #init(Applet, Properties)}.
1119 * @param app the current applet.
1121 * @param props application specific properties, passed as the second
1122 * parameter in {@link #init(Applet, Properties)}. Can be <code>null</code>.
1124 protected void set_parameters(Applet app, Properties props)
1126 useProperties(props);
1128 String[][] para = app.getParameterInfo();
1129 if (para != null)
1131 for (int i = 0; i < para.length; i++)
1133 if (para[i][0].equals(LISTEN_ON))
1134 Port = Integer.parseInt(para[i][1]);
1135 if (para[i][0].equals(REFERENCE))
1137 StringTokenizer st = new StringTokenizer(para[i][1], "=");
1138 initial_references.put(st.nextToken(),
1139 string_to_object(st.nextToken()));
1142 if (para[i][0].equals(ORB_ID))
1143 orb_id = para[i][1];
1145 if (para[i][0].equals(SERVER_ID))
1146 server_id = para[i][1];
1148 if (para[i][0].equals(NS_HOST))
1149 ns_host = para[i][1];
1150 if (para[i][0].equals(START_READING_MESSAGE))
1151 TOUT_START_READING_MESSAGE = Integer.parseInt(para[i][1]);
1152 if (para[i][0].equals(WHILE_READING))
1153 TOUT_WHILE_READING = Integer.parseInt(para[i][1]);
1154 if (para[i][0].equals(AFTER_RECEIVING))
1155 TOUT_AFTER_RECEIVING = Integer.parseInt(para[i][1]);
1158 if (para[i][0].equals(NS_PORT))
1159 ns_port = Integer.parseInt(para[i][1]);
1161 catch (NumberFormatException ex)
1163 BAD_PARAM bad = new BAD_PARAM("Invalid " + NS_PORT
1164 + "property, unable to parse '" + props.getProperty(NS_PORT)
1165 + "'");
1166 bad.initCause(ex);
1167 throw bad;
1174 * Set the ORB parameters. This method is normally called from
1175 * {@link #init(String[], Properties)}.
1177 * @param para the parameters, that were passed as the parameters to the
1178 * <code>main(String[] args)</code> method of the current standalone
1179 * application.
1181 * @param props application specific properties that were passed as a second
1182 * parameter in {@link init(String[], Properties)}). Can be <code>null</code>.
1184 protected void set_parameters(String[] para, Properties props)
1186 if (para.length > 1)
1188 for (int i = 0; i < para.length - 1; i++)
1190 if (para[i].endsWith("ListenOn"))
1191 Port = Integer.parseInt(para[i + 1]);
1192 if (para[i].endsWith("ORBInitRef"))
1194 StringTokenizer st = new StringTokenizer(para[i + 1], "=");
1195 initial_references.put(st.nextToken(),
1196 string_to_object(st.nextToken()));
1199 if (para[i].endsWith("ORBInitialHost"))
1200 ns_host = para[i + 1];
1202 if (para[i].endsWith("ServerId"))
1203 server_id = para[i++];
1204 else if (para[i].endsWith("ORBid"))
1205 orb_id = para[i++];
1209 if (para[i].endsWith("ORBInitialPort"))
1210 ns_port = Integer.parseInt(para[i + 1]);
1212 catch (NumberFormatException ex)
1214 throw new BAD_PARAM("Invalid " + para[i]
1215 + "parameter, unable to parse '"
1216 + props.getProperty(para[i + 1]) + "'");
1221 useProperties(props);
1225 * Create IOR for the given object references.
1227 protected IOR createIOR(Connected_objects.cObject ref)
1228 throws BAD_OPERATION
1230 IOR ior = new IOR();
1231 ior.key = ref.key;
1232 ior.Internet.port = ref.port;
1234 if (ref.object instanceof ObjectImpl)
1236 ObjectImpl imp = (ObjectImpl) ref.object;
1237 if (imp._ids().length > 0)
1238 ior.Id = imp._ids() [ 0 ];
1240 if (ior.Id == null)
1241 ior.Id = ref.object.getClass().getName();
1244 ior.Internet.host = InetAddress.getLocalHost().getHostAddress();
1245 ior.Internet.port = ref.port;
1247 catch (UnknownHostException ex)
1249 throw new BAD_OPERATION("Cannot resolve the local host address");
1251 return ior;
1255 * Prepare object for connecting it to this ORB.
1257 * @param object the object being connected.
1259 * @throws BAD_PARAM if the object does not implement the
1260 * {@link InvokeHandler}).
1262 protected void prepareObject(org.omg.CORBA.Object object, IOR ior)
1263 throws BAD_PARAM
1266 * if (!(object instanceof InvokeHandler)) throw new
1267 * BAD_PARAM(object.getClass().getName() + " does not implement
1268 * InvokeHandler. " );
1271 // If no delegate is set, set the default delegate.
1272 if (object instanceof ObjectImpl)
1274 ObjectImpl impl = (ObjectImpl) object;
1277 if (impl._get_delegate() == null)
1278 impl._set_delegate(new SimpleDelegate(this, ior));
1280 catch (BAD_OPERATION ex)
1282 // Some colaborants may throw this exception.
1283 impl._set_delegate(new SimpleDelegate(this, ior));
1289 * Write the response message.
1291 * @param net_out the stream to write response into
1292 * @param msh_request the request message header
1293 * @param rh_request the request header
1294 * @param handler the invocation handler that has been used to invoke the
1295 * operation
1296 * @param sysEx the system exception, thrown during the invocation, null if
1297 * none.
1299 * @throws IOException
1301 private void respond_to_client(OutputStream net_out,
1302 MessageHeader msh_request, RequestHeader rh_request,
1303 ResponseHandlerImpl handler, SystemException sysEx
1304 ) throws IOException
1306 // Set the reply header properties.
1307 ReplyHeader reply = handler.reply_header;
1309 if (sysEx != null)
1310 reply.reply_status = ReplyHeader.SYSTEM_EXCEPTION;
1311 else if (handler.isExceptionReply())
1312 reply.reply_status = ReplyHeader.USER_EXCEPTION;
1313 else
1314 reply.reply_status = ReplyHeader.NO_EXCEPTION;
1315 reply.request_id = rh_request.request_id;
1317 BufferedCdrOutput out =
1318 new BufferedCdrOutput(50 + handler.getBuffer().buffer.size());
1319 out.setOrb(this);
1321 out.setOffset(msh_request.getHeaderSize());
1323 reply.write(out);
1325 if (msh_request.version.since_inclusive(1, 2))
1327 out.align(8);
1329 // Write the reply data from the handler. The handler data already
1330 // include the necessary heading zeroes for alignment.
1332 handler.getBuffer().buffer.writeTo(out);
1334 MessageHeader msh_reply = new MessageHeader();
1336 msh_reply.version = msh_request.version;
1337 msh_reply.message_type = MessageHeader.REPLY;
1338 msh_reply.message_size = out.buffer.size();
1340 // Write the reply.
1341 msh_reply.write(net_out);
1342 out.buffer.writeTo(net_out);
1343 net_out.flush();
1347 * Forward request to another target, as indicated by the passed exception.
1349 private void forward_request(OutputStream net_out,
1350 MessageHeader msh_request, RequestHeader rh_request, gnuForwardRequest info
1351 ) throws IOException
1353 MessageHeader msh_forward = new MessageHeader();
1354 msh_forward.version = msh_request.version;
1356 ReplyHeader rh_forward = msh_forward.create_reply_header();
1357 msh_forward.message_type = MessageHeader.REPLY;
1358 rh_forward.reply_status = info.forwarding_code;
1359 rh_forward.request_id = rh_request.request_id;
1361 // The forwarding code is either LOCATION_FORWARD or LOCATION_FORWARD_PERM.
1362 BufferedCdrOutput out = new BufferedCdrOutput();
1363 out.setOrb(this);
1364 out.setOffset(msh_forward.getHeaderSize());
1366 rh_forward.write(out);
1368 if (msh_forward.version.since_inclusive(1, 2))
1369 out.align(8);
1370 out.write_Object(info.forward_reference);
1372 msh_forward.message_size = out.buffer.size();
1374 // Write the forwarding instruction.
1375 msh_forward.write(net_out);
1376 out.buffer.writeTo(net_out);
1377 net_out.flush();
1381 * Contains a single servicing task.
1383 * Normally, each task matches a single remote invocation. However under
1384 * frequent tandem submissions the same task may span over several
1385 * invocations.
1387 * @param serverSocket the ORB server socket.
1389 * @throws MARSHAL
1390 * @throws IOException
1392 void serve(final portServer p, ServerSocket serverSocket)
1393 throws MARSHAL, IOException
1395 final Socket service;
1396 service = serverSocket.accept();
1398 // Tell the server there are no more resources.
1399 if (p.running_threads >= MAX_RUNNING_THREADS)
1401 serveStep(service, true);
1402 return;
1405 new Thread()
1407 public void run()
1411 synchronized (p)
1413 p.running_threads++;
1415 serveStep(service, false);
1417 finally
1419 synchronized (p)
1421 p.running_threads--;
1425 }.start();
1429 * A single servicing step, when the client socket is alrady open.
1431 * Normally, each task matches a single remote invocation. However under
1432 * frequent tandem submissions the same task may span over several
1433 * invocations.
1435 * @param service the opened client socket.
1436 * @param no_resources if true, the "NO RESOURCES" exception is thrown to the
1437 * client.
1439 void serveStep(Socket service, boolean no_resources)
1443 Serving: while (true)
1445 InputStream in = service.getInputStream();
1446 service.setSoTimeout(TOUT_START_READING_MESSAGE);
1448 MessageHeader msh_request = new MessageHeader();
1452 msh_request.read(in);
1454 catch (MARSHAL ex)
1456 // This exception may be thrown due closing the connection.
1457 return;
1460 if (max_version != null)
1462 if (!msh_request.version.until_inclusive(max_version.major,
1463 max_version.minor))
1465 OutputStream out = service.getOutputStream();
1466 new ErrorMessage(max_version).write(out);
1467 return;
1471 byte[] r = msh_request.readMessage(in, service, TOUT_WHILE_READING,
1472 TOUT_AFTER_RECEIVING);
1474 if (msh_request.message_type == MessageHeader.REQUEST)
1476 RequestHeader rh_request;
1478 BufferredCdrInput cin = new BufferredCdrInput(r);
1479 cin.setOrb(this);
1480 cin.setVersion(msh_request.version);
1481 cin.setOffset(msh_request.getHeaderSize());
1482 cin.setBigEndian(msh_request.isBigEndian());
1484 rh_request = msh_request.create_request_header();
1486 // Read header and auto set the charset.
1487 rh_request.read(cin);
1489 // in 1.2 and higher, align the current position at
1490 // 8 octet boundary.
1491 if (msh_request.version.since_inclusive(1, 2))
1493 cin.align(8);
1495 // find the target object.
1498 InvokeHandler target = (InvokeHandler) find_connected_object(
1499 rh_request.object_key, -1);
1501 // Prepare the reply header. This must be done in advance,
1502 // as the size must be known for handler to set alignments
1503 // correctly.
1504 ReplyHeader rh_reply = msh_request.create_reply_header();
1506 // TODO log errors about not existing objects and methods.
1507 ResponseHandlerImpl handler = new ResponseHandlerImpl(
1508 this, msh_request, rh_reply, rh_request);
1510 SystemException sysEx = null;
1514 if (no_resources)
1516 NO_RESOURCES no = new NO_RESOURCES("Too many parallel calls");
1517 no.minor = Minor.Threads;
1518 throw no;
1520 if (target == null)
1521 throw new OBJECT_NOT_EXIST();
1522 target._invoke(rh_request.operation, cin, handler);
1524 catch (gnuForwardRequest forwarded)
1526 OutputStream sou = service.getOutputStream();
1527 forward_request(sou, msh_request, rh_request, forwarded);
1528 if (service != null && !service.isClosed())
1530 // Wait for the subsequent invocations on the
1531 // same socket for the TANDEM_REQUEST duration.
1532 service.setSoTimeout(TANDEM_REQUESTS);
1533 continue Serving;
1536 catch (UnknownException uex)
1538 sysEx = new UNKNOWN("Unknown", 2,
1539 CompletionStatus.COMPLETED_MAYBE);
1540 sysEx.initCause(uex.originalEx);
1542 org.omg.CORBA.portable.OutputStream ech = handler.createExceptionReply();
1544 rh_reply.service_context = UnknownExceptionCtxHandler.addExceptionContext(
1545 rh_reply.service_context, uex.originalEx, ech);
1547 ObjectCreator.writeSystemException(ech, sysEx);
1549 catch (SystemException ex)
1551 sysEx = ex;
1553 org.omg.CORBA.portable.OutputStream ech = handler.createExceptionReply();
1555 rh_reply.service_context = UnknownExceptionCtxHandler.addExceptionContext(
1556 rh_reply.service_context, ex, ech);
1558 ObjectCreator.writeSystemException(ech, ex);
1560 catch (Exception except)
1562 // This should never happen under normal operation and
1563 // can only indicate errors in user object implementation.
1564 // We inform the user.
1565 except.printStackTrace();
1567 sysEx = new UNKNOWN("Unknown", 2,
1568 CompletionStatus.COMPLETED_MAYBE);
1569 sysEx.initCause(except);
1571 org.omg.CORBA.portable.OutputStream ech = handler.createExceptionReply();
1573 rh_reply.service_context = UnknownExceptionCtxHandler.addExceptionContext(
1574 rh_reply.service_context, except, ech);
1576 ObjectCreator.writeSystemException(ech, sysEx);
1579 // Write the response.
1580 if (rh_request.isResponseExpected())
1582 OutputStream sou = service.getOutputStream();
1583 respond_to_client(sou, msh_request, rh_request, handler,
1584 sysEx);
1587 else if (msh_request.message_type == MessageHeader.CLOSE_CONNECTION
1588 || msh_request.message_type == MessageHeader.MESSAGE_ERROR)
1590 CloseMessage.close(service.getOutputStream());
1591 service.close();
1592 return;
1595 if (service != null && !service.isClosed())
1597 // Wait for the subsequent invocations on the
1598 // same socket for the TANDEM_REQUEST duration.
1599 service.setSoTimeout(TANDEM_REQUESTS);
1600 else
1601 return;
1604 catch (SocketException ex)
1606 // OK.
1607 return;
1609 catch (IOException ioex)
1611 // Network error, probably transient.
1612 // TODO log it.
1613 return;
1615 finally
1617 try
1619 if (service!=null && !service.isClosed())
1620 service.close();
1622 catch (IOException ioex)
1624 // OK.
1630 * Set the ORB parameters from the properties that were accumulated
1631 * from several locations.
1633 protected void useProperties(Properties props)
1635 if (props != null)
1637 if (props.containsKey(LISTEN_ON))
1638 Port = Integer.parseInt(props.getProperty(LISTEN_ON));
1639 if (props.containsKey(NS_HOST))
1640 ns_host = props.getProperty(NS_HOST);
1643 if (props.containsKey(NS_PORT))
1644 ns_port = Integer.parseInt(props.getProperty(NS_PORT));
1645 if (props.containsKey(START_READING_MESSAGE))
1646 TOUT_START_READING_MESSAGE =
1647 Integer.parseInt(props.getProperty(START_READING_MESSAGE));
1648 if (props.containsKey(WHILE_READING))
1649 TOUT_WHILE_READING =
1650 Integer.parseInt(props.getProperty(WHILE_READING));
1651 if (props.containsKey(AFTER_RECEIVING))
1652 TOUT_AFTER_RECEIVING =
1653 Integer.parseInt(props.getProperty(AFTER_RECEIVING));
1654 if (props.containsKey(SERVER_ERROR_PAUSE))
1655 TWAIT_SERVER_ERROR_PAUSE =
1656 Integer.parseInt(props.getProperty(SERVER_ERROR_PAUSE));
1658 catch (NumberFormatException ex)
1660 throw new BAD_PARAM("Invalid " + NS_PORT +
1661 "property, unable to parse '" + props.getProperty(NS_PORT) +
1666 if (props.containsKey(SocketFactory.PROPERTY))
1668 String factory = null;
1671 factory = props.getProperty(SocketFactory.PROPERTY);
1672 if (factory!=null)
1673 socketFactory = (SocketFactory)
1674 ObjectCreator.forName(factory).newInstance();
1676 catch (Exception ex)
1678 BAD_PARAM p = new BAD_PARAM("Bad socket factory "+factory);
1679 p.initCause(ex);
1680 throw p;
1684 if (props.containsKey(ORB_ID))
1685 orb_id = props.getProperty(ORB_ID);
1687 if (props.containsKey(SERVER_ID))
1688 server_id = props.getProperty(SERVER_ID);
1690 Enumeration en = props.elements();
1691 while (en.hasMoreElements())
1693 String item = (String) en.nextElement();
1694 if (item.equals(REFERENCE))
1695 initial_references.put(item,
1696 string_to_object(props.getProperty(item))
1703 * Get the next instance with a response being received. If all currently sent
1704 * responses not yet processed, this method pauses till at least one of them
1705 * is complete. If there are no requests currently sent, the method pauses
1706 * till some request is submitted and the response is received. This strategy
1707 * is identical to the one accepted by Suns 1.4 ORB implementation.
1709 * The returned response is removed from the list of the currently submitted
1710 * responses and is never returned again.
1712 * @return the previously sent request that now contains the received
1713 * response.
1715 * @throws WrongTransaction If the method was called from the transaction
1716 * scope different than the one, used to send the request. The exception can
1717 * be raised only if the request is implicitly associated with some particular
1718 * transaction.
1720 public Request get_next_response() throws org.omg.CORBA.WrongTransaction
1722 return asynchron.get_next_response();
1726 * Find if any of the requests that have been previously sent with
1727 * {@link #send_multiple_requests_deferred}, have a response yet.
1729 * @return true if there is at least one response to the previously sent
1730 * request, false otherwise.
1732 public boolean poll_next_response()
1734 return asynchron.poll_next_response();
1738 * Send multiple prepared requests expecting to get a reply. All requests are
1739 * send in parallel, each in its own separate thread. When the reply arrives,
1740 * it is stored in the agreed fields of the corresponing request data
1741 * structure. If this method is called repeatedly, the new requests are added
1742 * to the set of the currently sent requests, but the old set is not
1743 * discarded.
1745 * @param requests the prepared array of requests.
1747 * @see #poll_next_response()
1748 * @see #get_next_response()
1749 * @see Request#send_deferred()
1751 public void send_multiple_requests_deferred(Request[] requests)
1753 asynchron.send_multiple_requests_deferred(requests);
1757 * Send multiple prepared requests one way, do not caring about the answer.
1758 * The messages, containing requests, will be marked, indicating that the
1759 * sender is not expecting to get a reply.
1761 * @param requests the prepared array of requests.
1763 * @see Request#send_oneway()
1765 public void send_multiple_requests_oneway(Request[] requests)
1767 asynchron.send_multiple_requests_oneway(requests);
1771 * Set the flag, forcing all server threads to terminate.
1773 protected void finalize() throws java.lang.Throwable
1775 running = false;
1776 super.finalize();