1 /* OrbFunctional.java -- 2 Copyright (C) 2005 Free Software Foundation, Inc. 3 4 This file is part of GNU Classpath. 5 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. 10 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. 15 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. 20 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. 25 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. */ 37 38 39 package gnu.CORBA; 40 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; 53 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; 71 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; 91 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}. 97 * 98 * @author Audrius Meskauskas (AudriusA@Bioinformatics.org) 99 */ 100 public class OrbFunctional extends OrbRestricted 101 { 102 /** 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. 106 */ 107 protected class portServer 108 extends Thread 109 { 110 /** 111 * The number of the currently running parallel threads. 112 */ 113 int running_threads; 114 115 /** 116 * The port on that this portServer is listening for requests. 117 */ 118 int s_port; 119 120 /** 121 * The server socket of this portServer. 122 */ 123 ServerSocket service; 124 125 /** 126 * True if the serving node must shutdown due call of the close_now(). 127 */ 128 boolean terminated; 129 130 /** 131 * Create a new portServer, serving on specific port. 132 */ portServer(int _port)133 portServer(int _port) 134 { 135 s_port = _port; 136 setDaemon(true); 137 try 138 { 139 service = socketFactory.createServerSocket(s_port); 140 } 141 catch (IOException ex) 142 { 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; 148 } 149 } 150 151 /** 152 * Enter the serving loop (get request/process it). All portServer normally 153 * terminate thy threads when the OrbFunctional.running is set to false. 154 */ run()155 public void run() 156 { 157 while (running) 158 { 159 try 160 { 161 tick(); 162 } 163 catch (SocketException ex) 164 { 165 // May be thrown when the service is closed by 166 // the close_now(). 167 if (terminated) 168 return; 169 } 170 catch (Exception iex) 171 { 172 // Wait. Do not terminate the 173 // service due potentially transient error. 174 try 175 { 176 Thread.sleep(TWAIT_SERVER_ERROR_PAUSE); 177 } 178 catch (InterruptedException ex) 179 { 180 } 181 } 182 } 183 } 184 185 /** 186 * Perform a single serving step. 187 * 188 * @throws java.lang.Exception 189 */ tick()190 void tick() 191 throws Exception 192 { 193 serve(this, service); 194 } 195 196 /** 197 * Forcibly close the server socket and mark this port as free. 198 */ close_now()199 public void close_now() 200 { 201 try 202 { 203 terminated = true; 204 service.close(); 205 } 206 catch (Exception ex) 207 { 208 // This may happen if the service has not been opened or 209 // cannot be closed. Return without action. 210 } 211 } 212 213 /** 214 * If the thread is no longer in use, close the socket (if opened). 215 */ finalize()216 protected void finalize() 217 { 218 close_now(); 219 } 220 } 221 222 /** 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. 226 */ 227 protected class sharedPortServer extends portServer 228 { 229 /** 230 * Create a new portServer, serving on specific port. 231 */ sharedPortServer(int _port)232 sharedPortServer(int _port) 233 { 234 super(_port); 235 } 236 237 /** 238 * Perform a single serving step. 239 * 240 * @throws java.lang.Exception 241 */ tick()242 void tick() throws Exception 243 { 244 Socket request = service.accept(); 245 serveStep(request, false); 246 } 247 } 248 249 /** 250 * The default value where the first instance of this ORB will start looking 251 * for a free port. 252 */ 253 public static int DEFAULT_INITIAL_PORT = 1126; 254 255 /** 256 * When trying to open the socket on a random port, start of the interval to 257 * try. 258 */ 259 public static int RANDOM_PORT_FROM = 1024; 260 261 /** 262 * When trying to open the socket on a random port, end of the interval to 263 * try. 264 */ 265 public static int RANDOM_PORT_TO = 4024; 266 267 /** 268 * The number of attempts to try when opening random port. 269 */ 270 public static int RANDOM_PORT_ATTEMPTS = 64; 271 272 /** 273 * The property of port, on that this ORB is listening for requests from 274 * clients. This class supports one port per ORB only. 275 */ 276 public static final String LISTEN_ON = "gnu.classpath.CORBA.ListenOn"; 277 278 /** 279 * The property, defining the IOR of the intial reference to resolve. 280 */ 281 public static final String REFERENCE = "org.omg.CORBA.ORBInitRef"; 282 283 /** 284 * The property, defining the port on that the default name service is 285 * running. 286 */ 287 public static final String NS_PORT = "org.omg.CORBA.ORBInitialPort"; 288 289 /** 290 * The property, defining the host on that the default name service is 291 * running. 292 */ 293 public static final String NS_HOST = "org.omg.CORBA.ORBInitialHost"; 294 295 /** 296 * The string, defining the naming service initial reference. 297 */ 298 public static final String NAME_SERVICE = "NameService"; 299 300 /** 301 * The if the client has once opened a socket, it should start sending the 302 * message header in a given time. Otherwise the server will close the socket. 303 * This prevents server hang when the client opens the socket, but does not 304 * send any message, usually due crash on the client side. 305 */ 306 public static String START_READING_MESSAGE = 307 "gnu.classpath.CORBA.TOUT_START_READING_MESSAGE"; 308 309 /** 310 * If the client has started to send the request message, the socket time out 311 * changes to the specified value. 312 */ 313 public static String WHILE_READING = 314 "gnu.classpath.CORBA.TOUT_WHILE_READING"; 315 316 /** 317 * If the message body is received, the time out changes to the specifice 318 * value. This must be longer, as includes time, required to process the 319 * received task. We make it 40 minutes. 320 */ 321 public static String AFTER_RECEIVING = 322 "gnu.classpath.CORBA.TOUT_AFTER_RECEIVING"; 323 324 /** 325 * The server waits for this duration after the potentially transient error 326 * during its servicing cycle. 327 */ 328 public static String SERVER_ERROR_PAUSE = 329 "gnu.classpath.CORBA.SERVER_ERROR_PAUSE"; 330 331 /** 332 * The address of the local host. 333 */ 334 public final String LOCAL_HOST; 335 336 /** 337 * The if the client has once opened a socket, it should start sending the 338 * message header in a given time. Otherwise the server will close the socket. 339 * This prevents server hang when the client opens the socket, but does not 340 * send any message, usually due crash on the client side. 341 */ 342 public int TOUT_START_READING_MESSAGE = 20 * 1000; 343 344 // (Here and below, we use * to make the meaning of the constant clearler). 345 346 /** 347 * If the client has started to send the request message, the socket time out 348 * changes to the specified value. 349 */ 350 public int TOUT_WHILE_READING = 2 * 60 * 1000; 351 352 /** 353 * If the message body is received, the time out changes to the specifice 354 * value. This must be longer, as includes time, required to process the 355 * received task. We make it 40 minutes. 356 */ 357 public int TOUT_AFTER_RECEIVING = 40 * 60 * 1000; 358 359 /** 360 * The server waits for this duration after the potentially transient error 361 * during its servicing cycle. 362 */ 363 public int TWAIT_SERVER_ERROR_PAUSE = 5000; 364 365 /** 366 * Some clients tend to submit multiple requests over the same socket. The 367 * server waits for the next request on the same socket for the duration, 368 * specified below. In additions, the request of this implementation also 369 * waits for the same duration before closing the socket. The default time is 370 * seven seconds. 371 */ 372 public static int TANDEM_REQUESTS = 7000; 373 374 /** 375 * The map of the already conncted objects. 376 */ 377 protected final Connected_objects connected_objects = 378 new Connected_objects(); 379 380 /** 381 * The maximal CORBA version, supported by this ORB. The default value 0 means 382 * that the ORB will not check the request version while trying to respond. 383 */ 384 protected Version max_version; 385 386 /** 387 * Setting this value to false causes the ORB to shutdown after the latest 388 * serving operation is complete. 389 */ 390 protected boolean running; 391 392 /** 393 * The map of the initial references. 394 */ 395 protected Map initial_references = new TreeMap(); 396 397 /** 398 * The currently active portServers. 399 */ 400 protected ArrayList portServers = new ArrayList(); 401 402 /** 403 * The host, on that the name service is expected to be running. 404 */ 405 private String ns_host; 406 407 /** 408 * Probably free port, under that the ORB will try listening for remote 409 * requests first. When the new object is connected, this port is used first, 410 * then it is incremented by 1, etc. If the given port is not available, up to 411 * 20 subsequent values are tried and then the parameterless server socket 412 * contructor is called. The constant is shared between multiple instances of 413 * this ORB. 414 */ 415 private static int Port = DEFAULT_INITIAL_PORT; 416 417 /** 418 * The port, on that the name service is expected to be running. 419 */ 420 private int ns_port = 900; 421 422 /** 423 * The name parser. 424 */ 425 NameParser nameParser = new NameParser(); 426 427 /** 428 * The instance, stored in this field, handles the asynchronous dynamic 429 * invocations. 430 */ 431 protected Asynchron asynchron = new Asynchron(); 432 433 /** 434 * The list of the freed ports. The ORB reuses ports, when possible. 435 */ 436 protected LinkedList freed_ports = new LinkedList(); 437 438 /** 439 * Maps a single-threaded POAs to they sharedPortServants. 440 */ 441 protected Hashtable identities = new Hashtable(); 442 443 /** 444 * The maximal allowed number of the currently running parallel threads per 445 * object. For security reasons, this is made private and unchangeable. After 446 * exceeding this limit, the NO_RESOURCES is thrown back to the client. 447 */ 448 private int MAX_RUNNING_THREADS = 256; 449 450 /** 451 * The producer of the client and server sockets for this ORB. 452 */ 453 public SocketFactory socketFactory = DefaultSocketFactory.Singleton; 454 455 /** 456 * Create the instance of the Functional ORB. 457 */ OrbFunctional()458 public OrbFunctional() 459 { 460 try 461 { 462 LOCAL_HOST = ns_host = InetAddress.getLocalHost().getHostAddress(); 463 initial_references.put("CodecFactory", new gnuCodecFactory(this)); 464 } 465 catch (UnknownHostException ex) 466 { 467 BAD_OPERATION bad = 468 new BAD_OPERATION("Unable to open the server socket."); 469 bad.initCause(ex); 470 throw bad; 471 } 472 } 473 474 /** 475 * If the max version is assigned, the orb replies with the error message if 476 * the request version is above the supported 1.2 version. This behavior is 477 * recommended by OMG, but not all implementations respond that error message 478 * by re-sending the request, encoded in the older version. 479 */ setMaxVersion(Version max_supported)480 public void setMaxVersion(Version max_supported) 481 { 482 max_version = max_supported; 483 } 484 485 /** 486 * Get the maximal supported GIOP version or null if the version is not 487 * checked. 488 */ getMaxVersion()489 public Version getMaxVersion() 490 { 491 return max_version; 492 } 493 494 /** 495 * Get the currently free port, starting from the initially set port and going 496 * up max 20 steps, then trying to bind into any free address. 497 * 498 * @return the currently available free port. 499 * 500 * @throws NO_RESOURCES if the server socked cannot be opened on the local 501 * host. 502 */ getFreePort()503 public int getFreePort() 504 throws BAD_OPERATION 505 { 506 ServerSocket s; 507 int a_port; 508 509 try 510 { 511 // If there are some previously freed ports, use them first. 512 if (!freed_ports.isEmpty()) 513 { 514 Integer free = (Integer) freed_ports.getLast(); 515 freed_ports.removeLast(); 516 s = socketFactory.createServerSocket(free.intValue()); 517 s.close(); 518 return free.intValue(); 519 } 520 } 521 catch (Exception ex) 522 { 523 // This may be thrown if the request for the new port has arrived 524 // before the current service is completly shutdown. 525 // OK then, use a new port. 526 } 527 528 for (a_port = Port; a_port < Port + 20; a_port++) 529 { 530 try 531 { 532 s = socketFactory.createServerSocket(a_port); 533 s.close(); 534 Port = a_port + 1; 535 return a_port; 536 } 537 catch (IOException ex) 538 { 539 // Repeat the loop if this exception has been thrown. 540 } 541 } 542 543 Random rand = new Random(); 544 // Try any random port in the interval RANDOM_PORT_FROM.RANDOM_PORT_TO. 545 int range = RANDOM_PORT_TO - RANDOM_PORT_FROM; 546 IOException ioex = null; 547 for (int i = 0; i < RANDOM_PORT_ATTEMPTS; i++) 548 { 549 try 550 { 551 a_port = RANDOM_PORT_FROM + rand.nextInt(range); 552 s = socketFactory.createServerSocket(a_port); 553 s.close(); 554 return a_port; 555 } 556 catch (IOException ex) 557 { 558 // Repeat the loop if this exception has been thrown. 559 ioex = ex; 560 } 561 } 562 563 NO_RESOURCES bad = new NO_RESOURCES("Unable to open the server socket."); 564 bad.minor = Minor.Ports; 565 if (ioex != null) 566 bad.initCause(ioex); 567 throw bad; 568 } 569 570 /** 571 * Set the port, on that the server is listening for the client requests. If 572 * only one object is connected to the orb, the server will be try listening 573 * on this port first. It the port is busy, or if more objects are connected, 574 * the subsequent object will receive a larger port values, skipping 575 * unavailable ports, if required. The change applies globally. 576 * 577 * @param a_Port a port, on that the server is listening for requests. 578 */ setPort(int a_Port)579 public static void setPort(int a_Port) 580 { 581 Port = a_Port; 582 } 583 584 /** 585 * Connect the given CORBA object to this ORB. After the object is connected, 586 * it starts receiving remote invocations via this ORB. 587 * 588 * The ORB tries to connect the object to the port, that has been previously 589 * set by {@link setPort(int)}. On failure, it tries 20 subsequent larger 590 * values and then calls the parameterless server socked constructor to get 591 * any free local port. If this fails, the {@link NO_RESOURCES} is thrown. 592 * 593 * @param object the object, must implement the {@link InvokeHandler}) 594 * interface. 595 * 596 * @throws BAD_PARAM if the object does not implement the 597 * {@link InvokeHandler}). 598 */ connect(org.omg.CORBA.Object object)599 public void connect(org.omg.CORBA.Object object) 600 { 601 int a_port = getFreePort(); 602 603 Connected_objects.cObject ref = connected_objects.add(object, a_port); 604 IOR ior = createIOR(ref); 605 prepareObject(object, ior); 606 if (running) 607 startService(ior); 608 } 609 610 /** 611 * Connect the given CORBA object to this ORB, explicitly specifying the 612 * object key. 613 * 614 * The ORB tries to connect the object to the port, that has been previously 615 * set by {@link setPort(int)}. On failure, it tries 20 subsequent larger 616 * values and then calls the parameterless server socked constructor to get 617 * any free local port. If this fails, the {@link NO_RESOURCES} is thrown. 618 * 619 * @param object the object, must implement the {@link InvokeHandler}) 620 * interface. 621 * @param key the object key, usually used to identify the object from remote 622 * side. 623 * 624 * @throws BAD_PARAM if the object does not implement the 625 * {@link InvokeHandler}). 626 */ connect(org.omg.CORBA.Object object, byte[] key)627 public void connect(org.omg.CORBA.Object object, byte[] key) 628 { 629 int a_port = getFreePort(); 630 631 Connected_objects.cObject ref = 632 connected_objects.add(key, object, a_port, null); 633 IOR ior = createIOR(ref); 634 prepareObject(object, ior); 635 if (running) 636 startService(ior); 637 } 638 639 /** 640 * Connect the given CORBA object to this ORB, explicitly specifying the 641 * object key and the identity of the thread (and port), where the object must 642 * be served. The identity is normally the POA. 643 * 644 * The new port server will be started only if there is no one already running 645 * for the same identity. Otherwise, the task of the existing port server will 646 * be widened, including duty to serve the given object. All objects, 647 * connected to a single identity by this method, will process they requests 648 * subsequently in the same thread. The method is used when the expected 649 * number of the objects is too large to have a single port and thread per 650 * object. This method is used by POAs, having a single thread policy. 651 * 652 * @param object the object, must implement the {@link InvokeHandler}) 653 * interface. 654 * @param key the object key, usually used to identify the object from remote 655 * side. 656 * @param port the port, where the object must be connected. 657 * 658 * @throws BAD_PARAM if the object does not implement the 659 * {@link InvokeHandler}). 660 */ connect_1_thread(org.omg.CORBA.Object object, byte[] key, java.lang.Object identity )661 public void connect_1_thread(org.omg.CORBA.Object object, byte[] key, 662 java.lang.Object identity 663 ) 664 { 665 sharedPortServer shared = (sharedPortServer) identities.get(identity); 666 if (shared == null) 667 { 668 int a_port = getFreePort(); 669 shared = new sharedPortServer(a_port); 670 identities.put(identity, shared); 671 if (running) 672 { 673 portServers.add(shared); 674 shared.start(); 675 } 676 } 677 678 Connected_objects.cObject ref = 679 connected_objects.add(key, object, shared.s_port, identity); 680 IOR ior = createIOR(ref); 681 prepareObject(object, ior); 682 } 683 684 /** 685 * Start the service on the given port of this IOR. 686 * 687 * @param ior the ior (only Internet.port is used). 688 */ startService(IOR ior)689 public void startService(IOR ior) 690 { 691 portServer p = new portServer(ior.Internet.port); 692 portServers.add(p); 693 p.start(); 694 } 695 696 /** 697 * Destroy this server, releasing the occupied resources. 698 */ destroy()699 public void destroy() 700 { 701 portServer p; 702 for (int i = 0; i < portServers.size(); i++) 703 { 704 p = (portServer) portServers.get(i); 705 p.close_now(); 706 } 707 super.destroy(); 708 } 709 710 /** 711 * Disconnect the given CORBA object from this ORB. The object will be no 712 * longer receiving the remote invocations. In response to the remote 713 * invocation on this object, the ORB will send the exception 714 * {@link OBJECT_NOT_EXIST}. The object, however, is not destroyed and can 715 * receive the local invocations. 716 * 717 * @param object the object to disconnect. 718 */ disconnect(org.omg.CORBA.Object object)719 public void disconnect(org.omg.CORBA.Object object) 720 { 721 Connected_objects.cObject rmKey = null; 722 723 // Handle the case when it is possible to get the object key. 724 // Handle the case when the object is known, but not local. 725 if (object instanceof ObjectImpl) 726 { 727 Delegate delegate = ((ObjectImpl) object)._get_delegate(); 728 if (delegate instanceof SimpleDelegate) 729 { 730 byte[] key = ((SimpleDelegate) delegate).getIor().key; 731 rmKey = connected_objects.get(key); 732 } 733 } 734 735 // Try to find and disconned the object that is not an instance of the 736 // object implementation. 737 if (rmKey == null) 738 rmKey = connected_objects.getKey(object); 739 if (rmKey != null) 740 { 741 // Find and stop the corresponding portServer. 742 portServer p; 743 StopService: 744 for (int i = 0; i < portServers.size(); i++) 745 { 746 p = (portServer) portServers.get(i); 747 if (p.s_port == rmKey.port && !(p instanceof sharedPortServer)) 748 { 749 p.close_now(); 750 freed_ports.addFirst(new Integer(rmKey.port)); 751 break StopService; 752 } 753 connected_objects.remove(rmKey.key); 754 } 755 } 756 } 757 758 /** 759 * Notifies ORB that the shared service indentity (usually POA) is destroyed. 760 * The matching shared port server is terminated and the identity table entry 761 * is deleted. If this identity is not known for this ORB, the method returns 762 * without action. 763 * 764 * @param identity the identity that has been destroyed. 765 */ identityDestroyed(java.lang.Object identity)766 public void identityDestroyed(java.lang.Object identity) 767 { 768 if (identity == null) 769 return; 770 771 sharedPortServer ise = (sharedPortServer) identities.get(identity); 772 if (ise != null) 773 { 774 synchronized (connected_objects) 775 { 776 ise.close_now(); 777 identities.remove(identity); 778 779 Connected_objects.cObject obj; 780 Map.Entry m; 781 Iterator iter = connected_objects.entrySet().iterator(); 782 while (iter.hasNext()) 783 { 784 m = (Map.Entry) iter.next(); 785 obj = (Connected_objects.cObject) m.getValue(); 786 if (obj.identity == identity) 787 iter.remove(); 788 } 789 } 790 } 791 } 792 793 /** 794 * Find the local object, connected to this ORB. 795 * 796 * @param ior the ior of the potentially local object. 797 * 798 * @return the local object, represented by the given IOR, or null if this is 799 * not a local connected object. 800 */ find_local_object(IOR ior)801 public org.omg.CORBA.Object find_local_object(IOR ior) 802 { 803 // Must be the same host. 804 if (!ior.Internet.host.equals(LOCAL_HOST)) 805 return null; 806 807 return find_connected_object(ior.key, ior.Internet.port); 808 } 809 810 /** 811 * List the initially available CORBA objects (services). 812 * 813 * @return a list of services. 814 * 815 * @see resolve_initial_references(String) 816 */ list_initial_services()817 public String[] list_initial_services() 818 { 819 String[] refs = new String[ initial_references.size() ]; 820 int p = 0; 821 822 Iterator iter = initial_references.keySet().iterator(); 823 while (iter.hasNext()) 824 { 825 refs [ p++ ] = (String) iter.next(); 826 } 827 return refs; 828 } 829 830 /** 831 * Get the IOR reference string for the given object. The string embeds 832 * information about the object repository Id, its access key and the server 833 * internet address and port. With this information, the object can be found 834 * by another ORB, possibly located on remote computer. 835 * 836 * @param the CORBA object 837 * @return the object IOR representation. 838 * 839 * @throws BAD_PARAM if the object has not been previously connected to this 840 * ORB. 841 * 842 * @throws BAD_OPERATION in the unlikely case if the local host address cannot 843 * be resolved. 844 * 845 * @see string_to_object(String) 846 */ object_to_string(org.omg.CORBA.Object forObject)847 public String object_to_string(org.omg.CORBA.Object forObject) 848 { 849 // Handle the case when the object is known, but not local. 850 if (forObject instanceof ObjectImpl) 851 { 852 Delegate delegate = ((ObjectImpl) forObject)._get_delegate(); 853 if (delegate instanceof SimpleDelegate) 854 return ((SimpleDelegate) delegate).getIor().toStringifiedReference(); 855 } 856 857 // Handle the case when the object is local. 858 Connected_objects.cObject rec = connected_objects.getKey(forObject); 859 860 if (rec == null) 861 throw new BAD_PARAM("The object " + forObject + 862 " has not been previously connected to this ORB" 863 ); 864 865 IOR ior = createIOR(rec); 866 867 return ior.toStringifiedReference(); 868 } 869 870 /** 871 * Get the local IOR for the given object, null if the object is not local. 872 */ getLocalIor(org.omg.CORBA.Object forObject)873 public IOR getLocalIor(org.omg.CORBA.Object forObject) 874 { 875 Connected_objects.cObject rec = connected_objects.getKey(forObject); 876 if (rec == null) 877 return null; 878 else 879 return createIOR(rec); 880 } 881 882 /** 883 * Find and return the easily accessible CORBA object, addressed by name. 884 * 885 * @param name the object name. 886 * @return the object 887 * 888 * @throws org.omg.CORBA.ORBPackage.InvalidName if the given name is not 889 * associated with the known object. 890 */ resolve_initial_references(String name)891 public org.omg.CORBA.Object resolve_initial_references(String name) 892 throws InvalidName 893 { 894 org.omg.CORBA.Object object = null; 895 try 896 { 897 object = (org.omg.CORBA.Object) initial_references.get(name); 898 if (object == null && name.equals(NAME_SERVICE)) 899 { 900 object = getDefaultNameService(); 901 if (object != null) 902 initial_references.put(NAME_SERVICE, object); 903 } 904 } 905 catch (Exception ex) 906 { 907 InvalidName err = new InvalidName(name); 908 err.initCause(ex); 909 throw err; 910 } 911 if (object != null) 912 return object; 913 else 914 throw new InvalidName("Not found: '" + name + "'"); 915 } 916 917 /** 918 * Start the ORBs main working cycle (receive invocation - invoke on the local 919 * object - send response - wait for another invocation). 920 * 921 * The method only returns after calling {@link #shutdown(boolean)}. 922 */ run()923 public void run() 924 { 925 running = true; 926 927 // Instantiate the port server for each socket. 928 Iterator iter = connected_objects.entrySet().iterator(); 929 Map.Entry m; 930 Connected_objects.cObject obj; 931 932 while (iter.hasNext()) 933 { 934 m = (Map.Entry) iter.next(); 935 obj = (Connected_objects.cObject) m.getValue(); 936 937 portServer subserver; 938 939 if (obj.identity == null) 940 { 941 subserver = new portServer(obj.port); 942 portServers.add(subserver); 943 } 944 else 945 subserver = (portServer) identities.get(obj.identity); 946 947 if (!subserver.isAlive()) 948 { 949 // Reuse the current thread for the last portServer. 950 if (!iter.hasNext()) 951 { 952 // Discard the iterator, eliminating lock checks. 953 iter = null; 954 subserver.run(); 955 return; 956 } 957 else 958 subserver.start(); 959 } 960 } 961 } 962 963 /** 964 * Start the server in a new thread, if not already running. This method is 965 * used to ensure that the objects being transfered will be served from the 966 * remote side, if required. If the ORB is started using this method, it 967 * starts as a daemon thread. 968 */ ensureRunning()969 public void ensureRunning() 970 { 971 final OrbFunctional THIS = this; 972 973 if (!running) 974 { 975 Thread t = new Thread() 976 { 977 public void run() 978 { 979 THIS.run(); 980 } 981 }; 982 t.setDaemon(true); 983 t.start(); 984 } 985 } 986 987 /** 988 * Shutdown the ORB server. 989 * 990 * @param wait_for_completion if true, the current thread is suspended until 991 * the shutdown process is complete. 992 */ shutdown(boolean wait_for_completion)993 public void shutdown(boolean wait_for_completion) 994 { 995 super.shutdown(wait_for_completion); 996 running = false; 997 998 if (!wait_for_completion) 999 { 1000 for (int i = 0; i < portServers.size(); i++) 1001 { 1002 portServer p = (portServer) portServers.get(i); 1003 p.close_now(); 1004 } 1005 } 1006 } 1007 1008 /** 1009 * Find and return the CORBA object, addressed by the given IOR string 1010 * representation. The object can (an usually is) located on a remote 1011 * computer, possibly running a different (not necessary java) CORBA 1012 * implementation. 1013 * 1014 * @param ior the object IOR representation string. 1015 * 1016 * @return the found CORBA object. 1017 * @see object_to_string(org.omg.CORBA.Object) 1018 */ string_to_object(String an_ior)1019 public org.omg.CORBA.Object string_to_object(String an_ior) 1020 { 1021 return nameParser.corbaloc(an_ior, this); 1022 } 1023 1024 /** 1025 * Convert ior reference to CORBA object. 1026 */ ior_to_object(IOR ior)1027 public org.omg.CORBA.Object ior_to_object(IOR ior) 1028 { 1029 org.omg.CORBA.Object object = find_local_object(ior); 1030 if (object == null) 1031 { 1032 ObjectImpl impl = StubLocator.search(this, ior); 1033 try 1034 { 1035 if (impl._get_delegate() == null) 1036 impl._set_delegate(new IorDelegate(this, ior)); 1037 } 1038 catch (BAD_OPERATION ex) 1039 { 1040 // Some colaborants may throw this exception 1041 // in response to the attempt to get the unset delegate. 1042 impl._set_delegate(new IorDelegate(this, ior)); 1043 } 1044 1045 object = impl; 1046 // TODO remove commented out code below. 1047 // connected_objects.add(ior.key, impl, ior.Internet.port, null); 1048 } 1049 return object; 1050 } 1051 1052 /** 1053 * Get the default naming service for the case when there no NameService 1054 * entries. 1055 */ getDefaultNameService()1056 protected org.omg.CORBA.Object getDefaultNameService() 1057 { 1058 if (initial_references.containsKey(NAME_SERVICE)) 1059 return (org.omg.CORBA.Object) initial_references.get(NAME_SERVICE); 1060 1061 IOR ior = new IOR(); 1062 ior.Id = NamingContextExtHelper.id(); 1063 ior.Internet.host = ns_host; 1064 ior.Internet.port = ns_port; 1065 ior.key = NamingServiceTransient.getDefaultKey(); 1066 1067 IorObject iorc = new IorObject(this, ior); 1068 NamingContextExt namer = NamingContextExtHelper.narrow(iorc); 1069 initial_references.put(NAME_SERVICE, namer); 1070 return namer; 1071 } 1072 1073 /** 1074 * Find and return the object, that must be previously connected to this ORB. 1075 * Return null if no such object is available. 1076 * 1077 * @param key the object key. 1078 * @param port the port where the object is connected. 1079 * 1080 * @return the connected object, null if none. 1081 */ find_connected_object(byte[] key, int port)1082 protected org.omg.CORBA.Object find_connected_object(byte[] key, int port) 1083 { 1084 Connected_objects.cObject ref = connected_objects.get(key); 1085 if (ref == null) 1086 return null; 1087 if (port >= 0 && ref.port != port) 1088 return null; 1089 else 1090 return ref.object; 1091 } 1092 1093 /** 1094 * Set the ORB parameters. This method is normally called from 1095 * {@link #init(Applet, Properties)}. 1096 * 1097 * @param app the current applet. 1098 * 1099 * @param props application specific properties, passed as the second 1100 * parameter in {@link #init(Applet, Properties)}. Can be <code>null</code>. 1101 */ set_parameters(Applet app, Properties props)1102 protected void set_parameters(Applet app, Properties props) 1103 { 1104 useProperties(props); 1105 1106 String[][] para = app.getParameterInfo(); 1107 if (para != null) 1108 { 1109 for (int i = 0; i < para.length; i++) 1110 { 1111 if (para [ i ] [ 0 ].equals(LISTEN_ON)) 1112 Port = Integer.parseInt(para [ i ] [ 1 ]); 1113 if (para [ i ] [ 0 ].equals(REFERENCE)) 1114 { 1115 StringTokenizer st = 1116 new StringTokenizer(para [ i ] [ 1 ], "="); 1117 initial_references.put(st.nextToken(), 1118 string_to_object(st.nextToken()) 1119 ); 1120 } 1121 1122 if (para [ i ] [ 0 ].equals(NS_HOST)) 1123 ns_host = para [ i ] [ 1 ]; 1124 if (para [ i ] [ 0 ].equals(START_READING_MESSAGE)) 1125 TOUT_START_READING_MESSAGE = Integer.parseInt(para [ i ] [ 1 ]); 1126 if (para [ i ] [ 0 ].equals(WHILE_READING)) 1127 TOUT_WHILE_READING = Integer.parseInt(para [ i ] [ 1 ]); 1128 if (para [ i ] [ 0 ].equals(AFTER_RECEIVING)) 1129 TOUT_AFTER_RECEIVING = Integer.parseInt(para [ i ] [ 1 ]); 1130 try 1131 { 1132 if (para [ i ] [ 0 ].equals(NS_PORT)) 1133 ns_port = Integer.parseInt(para [ i ] [ 1 ]); 1134 } 1135 catch (NumberFormatException ex) 1136 { 1137 BAD_PARAM bad = 1138 new BAD_PARAM("Invalid " + NS_PORT + 1139 "property, unable to parse '" + 1140 props.getProperty(NS_PORT) + "'" 1141 ); 1142 bad.initCause(ex); 1143 throw bad; 1144 } 1145 } 1146 } 1147 } 1148 1149 /** 1150 * Set the ORB parameters. This method is normally called from 1151 * {@link #init(String[], Properties)}. 1152 * 1153 * @param para the parameters, that were passed as the parameters to the 1154 * <code>main(String[] args)</code> method of the current standalone 1155 * application. 1156 * 1157 * @param props application specific properties that were passed as a second 1158 * parameter in {@link init(String[], Properties)}). Can be <code>null</code>. 1159 */ set_parameters(String[] para, Properties props)1160 protected void set_parameters(String[] para, Properties props) 1161 { 1162 if (para.length > 1) 1163 { 1164 for (int i = 0; i < para.length - 1; i++) 1165 { 1166 if (para [ i ].endsWith("ListenOn")) 1167 Port = Integer.parseInt(para [ i + 1 ]); 1168 if (para [ i ].endsWith("ORBInitRef")) 1169 { 1170 StringTokenizer st = new StringTokenizer(para [ i + 1 ], "="); 1171 initial_references.put(st.nextToken(), 1172 string_to_object(st.nextToken()) 1173 ); 1174 } 1175 1176 if (para [ i ].endsWith("ORBInitialHost")) 1177 ns_host = para [ i + 1 ]; 1178 try 1179 { 1180 if (para [ i ].endsWith("ORBInitialPort")) 1181 ns_port = Integer.parseInt(para [ i + 1 ]); 1182 } 1183 catch (NumberFormatException ex) 1184 { 1185 throw new BAD_PARAM("Invalid " + para [ i ] + 1186 "parameter, unable to parse '" + 1187 props.getProperty(para [ i + 1 ]) + "'" 1188 ); 1189 } 1190 } 1191 } 1192 1193 useProperties(props); 1194 } 1195 1196 /** 1197 * Create IOR for the given object references. 1198 */ createIOR(Connected_objects.cObject ref)1199 protected IOR createIOR(Connected_objects.cObject ref) 1200 throws BAD_OPERATION 1201 { 1202 IOR ior = new IOR(); 1203 ior.key = ref.key; 1204 ior.Internet.port = ref.port; 1205 1206 if (ref.object instanceof ObjectImpl) 1207 { 1208 ObjectImpl imp = (ObjectImpl) ref.object; 1209 if (imp._ids().length > 0) 1210 ior.Id = imp._ids() [ 0 ]; 1211 } 1212 if (ior.Id == null) 1213 ior.Id = ref.object.getClass().getName(); 1214 try 1215 { 1216 ior.Internet.host = InetAddress.getLocalHost().getHostAddress(); 1217 ior.Internet.port = ref.port; 1218 } 1219 catch (UnknownHostException ex) 1220 { 1221 throw new BAD_OPERATION("Cannot resolve the local host address"); 1222 } 1223 return ior; 1224 } 1225 1226 /** 1227 * Prepare object for connecting it to this ORB. 1228 * 1229 * @param object the object being connected. 1230 * 1231 * @throws BAD_PARAM if the object does not implement the 1232 * {@link InvokeHandler}). 1233 */ prepareObject(org.omg.CORBA.Object object, IOR ior)1234 protected void prepareObject(org.omg.CORBA.Object object, IOR ior) 1235 throws BAD_PARAM 1236 { 1237 /* 1238 * if (!(object instanceof InvokeHandler)) throw new 1239 * BAD_PARAM(object.getClass().getName() + " does not implement 1240 * InvokeHandler. " ); 1241 */ 1242 1243 // If no delegate is set, set the default delegate. 1244 if (object instanceof ObjectImpl) 1245 { 1246 ObjectImpl impl = (ObjectImpl) object; 1247 try 1248 { 1249 if (impl._get_delegate() == null) 1250 impl._set_delegate(new SimpleDelegate(this, ior)); 1251 } 1252 catch (BAD_OPERATION ex) 1253 { 1254 // Some colaborants may throw this exception. 1255 impl._set_delegate(new SimpleDelegate(this, ior)); 1256 } 1257 } 1258 } 1259 1260 /** 1261 * Write the response message. 1262 * 1263 * @param net_out the stream to write response into 1264 * @param msh_request the request message header 1265 * @param rh_request the request header 1266 * @param handler the invocation handler that has been used to invoke the 1267 * operation 1268 * @param sysEx the system exception, thrown during the invocation, null if 1269 * none. 1270 * 1271 * @throws IOException 1272 */ respond_to_client(OutputStream net_out, MessageHeader msh_request, RequestHeader rh_request, ResponseHandlerImpl handler, SystemException sysEx )1273 private void respond_to_client(OutputStream net_out, 1274 MessageHeader msh_request, RequestHeader rh_request, 1275 ResponseHandlerImpl handler, SystemException sysEx 1276 ) throws IOException 1277 { 1278 // Set the reply header properties. 1279 ReplyHeader reply = handler.reply_header; 1280 1281 if (sysEx != null) 1282 reply.reply_status = ReplyHeader.SYSTEM_EXCEPTION; 1283 else if (handler.isExceptionReply()) 1284 reply.reply_status = ReplyHeader.USER_EXCEPTION; 1285 else 1286 reply.reply_status = ReplyHeader.NO_EXCEPTION; 1287 reply.request_id = rh_request.request_id; 1288 1289 BufferedCdrOutput out = 1290 new BufferedCdrOutput(50 + handler.getBuffer().buffer.size()); 1291 out.setOrb(this); 1292 1293 out.setOffset(msh_request.getHeaderSize()); 1294 1295 reply.write(out); 1296 1297 if (msh_request.version.since_inclusive(1, 2)) 1298 { 1299 out.align(8); 1300 1301 // Write the reply data from the handler. The handler data already 1302 // include the necessary heading zeroes for alignment. 1303 } 1304 handler.getBuffer().buffer.writeTo(out); 1305 1306 MessageHeader msh_reply = new MessageHeader(); 1307 1308 msh_reply.version = msh_request.version; 1309 msh_reply.message_type = MessageHeader.REPLY; 1310 msh_reply.message_size = out.buffer.size(); 1311 1312 // Write the reply. 1313 msh_reply.write(net_out); 1314 out.buffer.writeTo(net_out); 1315 net_out.flush(); 1316 } 1317 1318 /** 1319 * Forward request to another target, as indicated by the passed exception. 1320 */ forward_request(OutputStream net_out, MessageHeader msh_request, RequestHeader rh_request, gnuForwardRequest info )1321 private void forward_request(OutputStream net_out, 1322 MessageHeader msh_request, RequestHeader rh_request, gnuForwardRequest info 1323 ) throws IOException 1324 { 1325 MessageHeader msh_forward = new MessageHeader(); 1326 msh_forward.version = msh_request.version; 1327 1328 ReplyHeader rh_forward = msh_forward.create_reply_header(); 1329 msh_forward.message_type = MessageHeader.REPLY; 1330 rh_forward.reply_status = info.forwarding_code; 1331 rh_forward.request_id = rh_request.request_id; 1332 1333 // The forwarding code is either LOCATION_FORWARD or LOCATION_FORWARD_PERM. 1334 BufferedCdrOutput out = new BufferedCdrOutput(); 1335 out.setOrb(this); 1336 out.setOffset(msh_forward.getHeaderSize()); 1337 1338 rh_forward.write(out); 1339 1340 if (msh_forward.version.since_inclusive(1, 2)) 1341 out.align(8); 1342 out.write_Object(info.forward_reference); 1343 1344 msh_forward.message_size = out.buffer.size(); 1345 1346 // Write the forwarding instruction. 1347 msh_forward.write(net_out); 1348 out.buffer.writeTo(net_out); 1349 net_out.flush(); 1350 } 1351 1352 /** 1353 * Contains a single servicing task. 1354 * 1355 * Normally, each task matches a single remote invocation. However under 1356 * frequent tandem submissions the same task may span over several 1357 * invocations. 1358 * 1359 * @param serverSocket the ORB server socket. 1360 * 1361 * @throws MARSHAL 1362 * @throws IOException 1363 */ serve(final portServer p, ServerSocket serverSocket)1364 void serve(final portServer p, ServerSocket serverSocket) 1365 throws MARSHAL, IOException 1366 { 1367 final Socket service; 1368 service = serverSocket.accept(); 1369 1370 // Tell the server there are no more resources. 1371 if (p.running_threads >= MAX_RUNNING_THREADS) 1372 { 1373 serveStep(service, true); 1374 return; 1375 } 1376 1377 new Thread() 1378 { 1379 public void run() 1380 { 1381 try 1382 { 1383 synchronized (p) 1384 { 1385 p.running_threads++; 1386 } 1387 serveStep(service, false); 1388 } 1389 finally 1390 { 1391 synchronized (p) 1392 { 1393 p.running_threads--; 1394 } 1395 } 1396 } 1397 }.start(); 1398 } 1399 1400 /** 1401 * A single servicing step, when the client socket is alrady open. 1402 * 1403 * Normally, each task matches a single remote invocation. However under 1404 * frequent tandem submissions the same task may span over several 1405 * invocations. 1406 * 1407 * @param service the opened client socket. 1408 * @param no_resources if true, the "NO RESOURCES" exception is thrown to the 1409 * client. 1410 */ serveStep(Socket service, boolean no_resources)1411 void serveStep(Socket service, boolean no_resources) 1412 { 1413 try 1414 { 1415 Serving: while (true) 1416 { 1417 InputStream in = service.getInputStream(); 1418 service.setSoTimeout(TOUT_START_READING_MESSAGE); 1419 1420 MessageHeader msh_request = new MessageHeader(); 1421 1422 try 1423 { 1424 msh_request.read(in); 1425 } 1426 catch (MARSHAL ex) 1427 { 1428 // This exception may be thrown due closing the connection. 1429 return; 1430 } 1431 1432 if (max_version != null) 1433 { 1434 if (!msh_request.version.until_inclusive(max_version.major, 1435 max_version.minor)) 1436 { 1437 OutputStream out = service.getOutputStream(); 1438 new ErrorMessage(max_version).write(out); 1439 return; 1440 } 1441 } 1442 1443 byte[] r = msh_request.readMessage(in, service, TOUT_WHILE_READING, 1444 TOUT_AFTER_RECEIVING); 1445 1446 if (msh_request.message_type == MessageHeader.REQUEST) 1447 { 1448 RequestHeader rh_request; 1449 1450 BufferredCdrInput cin = new BufferredCdrInput(r); 1451 cin.setOrb(this); 1452 cin.setVersion(msh_request.version); 1453 cin.setOffset(msh_request.getHeaderSize()); 1454 cin.setBigEndian(msh_request.isBigEndian()); 1455 1456 rh_request = msh_request.create_request_header(); 1457 1458 // Read header and auto set the charset. 1459 rh_request.read(cin); 1460 1461 // in 1.2 and higher, align the current position at 1462 // 8 octet boundary. 1463 if (msh_request.version.since_inclusive(1, 2)) 1464 { 1465 cin.align(8); 1466 1467 // find the target object. 1468 } 1469 1470 InvokeHandler target = (InvokeHandler) find_connected_object( 1471 rh_request.object_key, -1); 1472 1473 // Prepare the reply header. This must be done in advance, 1474 // as the size must be known for handler to set alignments 1475 // correctly. 1476 ReplyHeader rh_reply = msh_request.create_reply_header(); 1477 1478 // TODO log errors about not existing objects and methods. 1479 ResponseHandlerImpl handler = new ResponseHandlerImpl( 1480 this, msh_request, rh_reply, rh_request); 1481 1482 SystemException sysEx = null; 1483 1484 try 1485 { 1486 if (no_resources) 1487 { 1488 NO_RESOURCES no = new NO_RESOURCES("Too many parallel calls"); 1489 no.minor = Minor.Threads; 1490 throw no; 1491 } 1492 if (target == null) 1493 throw new OBJECT_NOT_EXIST(); 1494 target._invoke(rh_request.operation, cin, handler); 1495 } 1496 catch (gnuForwardRequest forwarded) 1497 { 1498 OutputStream sou = service.getOutputStream(); 1499 forward_request(sou, msh_request, rh_request, forwarded); 1500 if (service != null && !service.isClosed()) 1501 { 1502 // Wait for the subsequent invocations on the 1503 // same socket for the TANDEM_REQUEST duration. 1504 service.setSoTimeout(TANDEM_REQUESTS); 1505 continue Serving; 1506 } 1507 } 1508 catch (UnknownException uex) 1509 { 1510 sysEx = new UNKNOWN("Unknown", 2, 1511 CompletionStatus.COMPLETED_MAYBE); 1512 sysEx.initCause(uex.originalEx); 1513 1514 org.omg.CORBA.portable.OutputStream ech = handler.createExceptionReply(); 1515 1516 rh_reply.service_context = UnknownExceptionCtxHandler.addExceptionContext( 1517 rh_reply.service_context, uex.originalEx, ech); 1518 1519 ObjectCreator.writeSystemException(ech, sysEx); 1520 } 1521 catch (SystemException ex) 1522 { 1523 sysEx = ex; 1524 1525 org.omg.CORBA.portable.OutputStream ech = handler.createExceptionReply(); 1526 1527 rh_reply.service_context = UnknownExceptionCtxHandler.addExceptionContext( 1528 rh_reply.service_context, ex, ech); 1529 1530 ObjectCreator.writeSystemException(ech, ex); 1531 } 1532 catch (Exception except) 1533 { 1534 // This should never happen under normal operation and 1535 // can only indicate errors in user object implementation. 1536 // We inform the user. 1537 except.printStackTrace(); 1538 1539 sysEx = new UNKNOWN("Unknown", 2, 1540 CompletionStatus.COMPLETED_MAYBE); 1541 sysEx.initCause(except); 1542 1543 org.omg.CORBA.portable.OutputStream ech = handler.createExceptionReply(); 1544 1545 rh_reply.service_context = UnknownExceptionCtxHandler.addExceptionContext( 1546 rh_reply.service_context, except, ech); 1547 1548 ObjectCreator.writeSystemException(ech, sysEx); 1549 } 1550 1551 // Write the response. 1552 if (rh_request.isResponseExpected()) 1553 { 1554 OutputStream sou = service.getOutputStream(); 1555 respond_to_client(sou, msh_request, rh_request, handler, 1556 sysEx); 1557 } 1558 } 1559 else if (msh_request.message_type == MessageHeader.CLOSE_CONNECTION 1560 || msh_request.message_type == MessageHeader.MESSAGE_ERROR) 1561 { 1562 CloseMessage.close(service.getOutputStream()); 1563 service.close(); 1564 return; 1565 } 1566 1567 if (service != null && !service.isClosed()) 1568 1569 // Wait for the subsequent invocations on the 1570 // same socket for the TANDEM_REQUEST duration. 1571 service.setSoTimeout(TANDEM_REQUESTS); 1572 else 1573 return; 1574 } 1575 } 1576 catch (SocketException ex) 1577 { 1578 // OK. 1579 return; 1580 } 1581 catch (IOException ioex) 1582 { 1583 // Network error, probably transient. 1584 // TODO log it. 1585 return; 1586 } 1587 } 1588 1589 /** 1590 * Set the ORB parameters from the properties that were accumulated 1591 * from several locations. 1592 */ useProperties(Properties props)1593 protected void useProperties(Properties props) 1594 { 1595 if (props != null) 1596 { 1597 if (props.containsKey(LISTEN_ON)) 1598 Port = Integer.parseInt(props.getProperty(LISTEN_ON)); 1599 if (props.containsKey(NS_HOST)) 1600 ns_host = props.getProperty(NS_HOST); 1601 try 1602 { 1603 if (props.containsKey(NS_PORT)) 1604 ns_port = Integer.parseInt(props.getProperty(NS_PORT)); 1605 if (props.containsKey(START_READING_MESSAGE)) 1606 TOUT_START_READING_MESSAGE = 1607 Integer.parseInt(props.getProperty(START_READING_MESSAGE)); 1608 if (props.containsKey(WHILE_READING)) 1609 TOUT_WHILE_READING = 1610 Integer.parseInt(props.getProperty(WHILE_READING)); 1611 if (props.containsKey(AFTER_RECEIVING)) 1612 TOUT_AFTER_RECEIVING = 1613 Integer.parseInt(props.getProperty(AFTER_RECEIVING)); 1614 if (props.containsKey(SERVER_ERROR_PAUSE)) 1615 TWAIT_SERVER_ERROR_PAUSE = 1616 Integer.parseInt(props.getProperty(SERVER_ERROR_PAUSE)); 1617 } 1618 catch (NumberFormatException ex) 1619 { 1620 throw new BAD_PARAM("Invalid " + NS_PORT + 1621 "property, unable to parse '" + props.getProperty(NS_PORT) + 1622 "'" 1623 ); 1624 } 1625 1626 if (props.containsKey(SocketFactory.PROPERTY)) 1627 { 1628 String factory = null; 1629 try 1630 { 1631 factory = props.getProperty(SocketFactory.PROPERTY); 1632 if (factory!=null) 1633 socketFactory = (SocketFactory) 1634 ObjectCreator.forName(factory).newInstance(); 1635 } 1636 catch (Exception ex) 1637 { 1638 BAD_PARAM p = new BAD_PARAM("Bad socket factory "+factory); 1639 p.initCause(ex); 1640 throw p; 1641 } 1642 } 1643 1644 Enumeration en = props.elements(); 1645 while (en.hasMoreElements()) 1646 { 1647 String item = (String) en.nextElement(); 1648 if (item.equals(REFERENCE)) 1649 initial_references.put(item, 1650 string_to_object(props.getProperty(item)) 1651 ); 1652 } 1653 } 1654 } 1655 1656 /** 1657 * Get the next instance with a response being received. If all currently sent 1658 * responses not yet processed, this method pauses till at least one of them 1659 * is complete. If there are no requests currently sent, the method pauses 1660 * till some request is submitted and the response is received. This strategy 1661 * is identical to the one accepted by Suns 1.4 ORB implementation. 1662 * 1663 * The returned response is removed from the list of the currently submitted 1664 * responses and is never returned again. 1665 * 1666 * @return the previously sent request that now contains the received 1667 * response. 1668 * 1669 * @throws WrongTransaction If the method was called from the transaction 1670 * scope different than the one, used to send the request. The exception can 1671 * be raised only if the request is implicitly associated with some particular 1672 * transaction. 1673 */ get_next_response()1674 public Request get_next_response() throws org.omg.CORBA.WrongTransaction 1675 { 1676 return asynchron.get_next_response(); 1677 } 1678 1679 /** 1680 * Find if any of the requests that have been previously sent with 1681 * {@link #send_multiple_requests_deferred}, have a response yet. 1682 * 1683 * @return true if there is at least one response to the previously sent 1684 * request, false otherwise. 1685 */ poll_next_response()1686 public boolean poll_next_response() 1687 { 1688 return asynchron.poll_next_response(); 1689 } 1690 1691 /** 1692 * Send multiple prepared requests expecting to get a reply. All requests are 1693 * send in parallel, each in its own separate thread. When the reply arrives, 1694 * it is stored in the agreed fields of the corresponing request data 1695 * structure. If this method is called repeatedly, the new requests are added 1696 * to the set of the currently sent requests, but the old set is not 1697 * discarded. 1698 * 1699 * @param requests the prepared array of requests. 1700 * 1701 * @see #poll_next_response() 1702 * @see #get_next_response() 1703 * @see Request#send_deferred() 1704 */ send_multiple_requests_deferred(Request[] requests)1705 public void send_multiple_requests_deferred(Request[] requests) 1706 { 1707 asynchron.send_multiple_requests_deferred(requests); 1708 } 1709 1710 /** 1711 * Send multiple prepared requests one way, do not caring about the answer. 1712 * The messages, containing requests, will be marked, indicating that the 1713 * sender is not expecting to get a reply. 1714 * 1715 * @param requests the prepared array of requests. 1716 * 1717 * @see Request#send_oneway() 1718 */ send_multiple_requests_oneway(Request[] requests)1719 public void send_multiple_requests_oneway(Request[] requests) 1720 { 1721 asynchron.send_multiple_requests_oneway(requests); 1722 } 1723 1724 /** 1725 * Set the flag, forcing all server threads to terminate. 1726 */ finalize()1727 protected void finalize() throws java.lang.Throwable 1728 { 1729 running = false; 1730 super.finalize(); 1731 } 1732 }