OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libjava/] [classpath/] [gnu/] [CORBA/] [OrbFunctional.java] - Blame information for rev 14

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jlechner
/* 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
     */
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
     */
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
     */
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
     */
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
     */
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
     */
232
    sharedPortServer(int _port)
233
    {
234
      super(_port);
235
    }
236
 
237
    /**
238
     * Perform a single serving step.
239
     *
240
     * @throws java.lang.Exception
241
     */
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
   * Defines the ORB ID that is accessible by IOR interceptors.
302
   */
303
  public static final String ORB_ID = "org.omg.CORBA.ORBid";
304
 
305
 
306
  /**
307
   * Defines the SERVER ID that is accessible by IOR interceptors.
308
   */
309
  public static final String SERVER_ID = "org.omg.CORBA.ServerId";
310
 
311
  /**
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.
316
   */
317
  public static String START_READING_MESSAGE =
318
    "gnu.classpath.CORBA.TOUT_START_READING_MESSAGE";
319
 
320
  /**
321
   * If the client has started to send the request message, the socket time out
322
   * changes to the specified value.
323
   */
324
  public static String WHILE_READING =
325
    "gnu.classpath.CORBA.TOUT_WHILE_READING";
326
 
327
  /**
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.
331
   */
332
  public static String AFTER_RECEIVING =
333
    "gnu.classpath.CORBA.TOUT_AFTER_RECEIVING";
334
 
335
  /**
336
   * The server waits for this duration after the potentially transient error
337
   * during its servicing cycle.
338
   */
339
  public static String SERVER_ERROR_PAUSE =
340
    "gnu.classpath.CORBA.SERVER_ERROR_PAUSE";
341
 
342
  /**
343
   * The address of the local host.
344
   */
345
  public final String LOCAL_HOST;
346
 
347
  /**
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.
352
   */
353
  public int TOUT_START_READING_MESSAGE = 20 * 1000;
354
 
355
  // (Here and below, we use * to make the meaning of the constant clearler).
356
 
357
  /**
358
   * If the client has started to send the request message, the socket time out
359
   * changes to the specified value.
360
   */
361
  public int TOUT_WHILE_READING = 2 * 60 * 1000;
362
 
363
  /**
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.
367
   */
368
  public int TOUT_AFTER_RECEIVING = 40 * 60 * 1000;
369
 
370
  /**
371
   * The server waits for this duration after the potentially transient error
372
   * during its servicing cycle.
373
   */
374
  public int TWAIT_SERVER_ERROR_PAUSE = 5000;
375
 
376
  /**
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.
382
   */
383
  public static int TANDEM_REQUESTS = 7000;
384
 
385
  /**
386
   * The Id of this ORB.
387
   */
388
  public String orb_id = "orb_"+hashCode();
389
 
390
  /**
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.
393
   */
394
  public static String server_id = "server_"+OrbFunctional.class.hashCode();
395
 
396
  /**
397
   * The map of the already conncted objects.
398
   */
399
  protected final Connected_objects connected_objects =
400
    new Connected_objects();
401
 
402
  /**
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.
405
   */
406
  protected Version max_version;
407
 
408
  /**
409
   * Setting this value to false causes the ORB to shutdown after the latest
410
   * serving operation is complete.
411
   */
412
  protected boolean running;
413
 
414
  /**
415
   * The map of the initial references.
416
   */
417
  protected Map initial_references = new TreeMap();
418
 
419
  /**
420
   * The currently active portServers.
421
   */
422
  protected ArrayList portServers = new ArrayList();
423
 
424
  /**
425
   * The host, on that the name service is expected to be running.
426
   */
427
  private String ns_host;
428
 
429
  /**
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.
436
   */
437
  private static int Port = DEFAULT_INITIAL_PORT;
438
 
439
  /**
440
   * The port, on that the name service is expected to be running.
441
   */
442
  private int ns_port = 900;
443
 
444
  /**
445
   * The name parser.
446
   */
447
  NameParser nameParser = new NameParser();
448
 
449
  /**
450
   * The instance, stored in this field, handles the asynchronous dynamic
451
   * invocations.
452
   */
453
  protected Asynchron asynchron = new Asynchron();
454
 
455
  /**
456
   * The list of the freed ports. The ORB reuses ports, when possible.
457
   */
458
  protected LinkedList freed_ports = new LinkedList();
459
 
460
  /**
461
   * Maps a single-threaded POAs to they sharedPortServants.
462
   */
463
  protected Hashtable identities = new Hashtable();
464
 
465
  /**
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.
469
   */
470
  private int MAX_RUNNING_THREADS = 256;
471
 
472
  /**
473
   * The producer of the client and server sockets for this ORB.
474
   */
475
  public SocketFactory socketFactory = DefaultSocketFactory.Singleton;
476
 
477
  /**
478
   * Create the instance of the Functional ORB.
479
   */
480
  public OrbFunctional()
481
  {
482
    try
483
      {
484
        LOCAL_HOST = ns_host = InetAddress.getLocalHost().getHostAddress();
485
        initial_references.put("CodecFactory", new gnuCodecFactory(this));
486
      }
487
    catch (UnknownHostException ex)
488
      {
489
        BAD_OPERATION bad =
490
          new BAD_OPERATION("Unable to open the server socket.");
491
        bad.initCause(ex);
492
        throw bad;
493
      }
494
  }
495
 
496
  /**
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.
501
   */
502
  public void setMaxVersion(Version max_supported)
503
  {
504
    max_version = max_supported;
505
  }
506
 
507
  /**
508
   * Get the maximal supported GIOP version or null if the version is not
509
   * checked.
510
   */
511
  public Version getMaxVersion()
512
  {
513
    return max_version;
514
  }
515
 
516
  /**
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.
519
   *
520
   * @return the currently available free port.
521
   *
522
   * @throws NO_RESOURCES if the server socked cannot be opened on the local
523
   * host.
524
   */
525
  public int getFreePort()
526
    throws BAD_OPERATION
527
  {
528
    ServerSocket s;
529
    int a_port;
530
 
531
    try
532
      {
533
        // If there are some previously freed ports, use them first.
534
        if (!freed_ports.isEmpty())
535
          {
536
            Integer free = (Integer) freed_ports.getLast();
537
            freed_ports.removeLast();
538
            s = socketFactory.createServerSocket(free.intValue());
539
            s.close();
540
            return free.intValue();
541
          }
542
      }
543
    catch (Exception ex)
544
      {
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.
548
      }
549
 
550
    for (a_port = Port; a_port < Port + 20; a_port++)
551
      {
552
        try
553
          {
554
            s = socketFactory.createServerSocket(a_port);
555
            s.close();
556
            Port = a_port + 1;
557
            return a_port;
558
          }
559
        catch (IOException ex)
560
          {
561
            // Repeat the loop if this exception has been thrown.
562
          }
563
      }
564
 
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++)
570
      {
571
        try
572
          {
573
            a_port = RANDOM_PORT_FROM + rand.nextInt(range);
574
            s = socketFactory.createServerSocket(a_port);
575
            s.close();
576
            return a_port;
577
          }
578
        catch (IOException ex)
579
          {
580
            // Repeat the loop if this exception has been thrown.
581
            ioex = ex;
582
          }
583
      }
584
 
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;
590
  }
591
 
592
  /**
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.
598
   *
599
   * @param a_Port a port, on that the server is listening for requests.
600
   */
601
  public static void setPort(int a_Port)
602
  {
603
    Port = a_Port;
604
  }
605
 
606
  /**
607
   * Connect the given CORBA object to this ORB. After the object is connected,
608
   * it starts receiving remote invocations via this ORB.
609
   *
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.
614
   *
615
   * @param object the object, must implement the {@link InvokeHandler})
616
   * interface.
617
   *
618
   * @throws BAD_PARAM if the object does not implement the
619
   * {@link InvokeHandler}).
620
   */
621
  public void connect(org.omg.CORBA.Object object)
622
  {
623
    int a_port = getFreePort();
624
 
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);
630
  }
631
 
632
  /**
633
   * Connect the given CORBA object to this ORB, explicitly specifying the
634
   * object key.
635
   *
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.
640
   *
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.
645
   *
646
   * @throws BAD_PARAM if the object does not implement the
647
   * {@link InvokeHandler}).
648
   */
649
  public void connect(org.omg.CORBA.Object object, byte[] key)
650
  {
651
    int a_port = getFreePort();
652
 
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);
659
  }
660
 
661
  /**
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.
665
   *
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.
673
   *
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.
679
   *
680
   * @throws BAD_PARAM if the object does not implement the
681
   * {@link InvokeHandler}).
682
   */
683
  public void connect_1_thread(org.omg.CORBA.Object object, byte[] key,
684
    java.lang.Object identity
685
  )
686
  {
687
    sharedPortServer shared = (sharedPortServer) identities.get(identity);
688
    if (shared == null)
689
      {
690
        int a_port = getFreePort();
691
        shared = new sharedPortServer(a_port);
692
        identities.put(identity, shared);
693
        if (running)
694
          {
695
            portServers.add(shared);
696
            shared.start();
697
          }
698
      }
699
 
700
    Connected_objects.cObject ref =
701
      connected_objects.add(key, object, shared.s_port, identity);
702
    IOR ior = createIOR(ref);
703
    prepareObject(object, ior);
704
  }
705
 
706
  /**
707
   * Start the service on the given port of this IOR.
708
   *
709
   * @param ior the ior (only Internet.port is used).
710
   */
711
  public void startService(IOR ior)
712
  {
713
    portServer p = new portServer(ior.Internet.port);
714
    portServers.add(p);
715
    p.start();
716
  }
717
 
718
  /**
719
   * Destroy this server, releasing the occupied resources.
720
   */
721
  public void destroy()
722
  {
723
    portServer p;
724
    for (int i = 0; i < portServers.size(); i++)
725
      {
726
        p = (portServer) portServers.get(i);
727
        p.close_now();
728
      }
729
    super.destroy();
730
  }
731
 
732
  /**
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.
738
   *
739
   * @param object the object to disconnect.
740
   */
741
  public void disconnect(org.omg.CORBA.Object object)
742
  {
743
    Connected_objects.cObject rmKey = null;
744
 
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)
748
      {
749
        Delegate delegate = ((ObjectImpl) object)._get_delegate();
750
        if (delegate instanceof SimpleDelegate)
751
          {
752
            byte[] key = ((SimpleDelegate) delegate).getIor().key;
753
            rmKey = connected_objects.get(key);
754
          }
755
      }
756
 
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)
762
      {
763
        // Find and stop the corresponding portServer.
764
        portServer p;
765
        StopService:
766
        for (int i = 0; i < portServers.size(); i++)
767
          {
768
            p = (portServer) portServers.get(i);
769
            if (p.s_port == rmKey.port && !(p instanceof sharedPortServer))
770
              {
771
                p.close_now();
772
                freed_ports.addFirst(new Integer(rmKey.port));
773
                break StopService;
774
              }
775
            connected_objects.remove(rmKey.key);
776
          }
777
      }
778
  }
779
 
780
  /**
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.
785
   *
786
   * @param identity the identity that has been destroyed.
787
   */
788
  public void identityDestroyed(java.lang.Object identity)
789
  {
790
    if (identity == null)
791
      return;
792
 
793
    sharedPortServer ise = (sharedPortServer) identities.get(identity);
794
    if (ise != null)
795
      {
796
        synchronized (connected_objects)
797
          {
798
            ise.close_now();
799
            identities.remove(identity);
800
 
801
            Connected_objects.cObject obj;
802
            Map.Entry m;
803
            Iterator iter = connected_objects.entrySet().iterator();
804
            while (iter.hasNext())
805
              {
806
                m = (Map.Entry) iter.next();
807
                obj = (Connected_objects.cObject) m.getValue();
808
                if (obj.identity == identity)
809
                  iter.remove();
810
              }
811
          }
812
      }
813
  }
814
 
815
  /**
816
   * Find the local object, connected to this ORB.
817
   *
818
   * @param ior the ior of the potentially local object.
819
   *
820
   * @return the local object, represented by the given IOR, or null if this is
821
   * not a local connected object.
822
   */
823
  public org.omg.CORBA.Object find_local_object(IOR ior)
824
  {
825
    // Must be the same host.
826
    if (!ior.Internet.host.equals(LOCAL_HOST))
827
      return null;
828
 
829
    return find_connected_object(ior.key, ior.Internet.port);
830
  }
831
 
832
  /**
833
   * List the initially available CORBA objects (services).
834
   *
835
   * @return a list of services.
836
   *
837
   * @see resolve_initial_references(String)
838
   */
839
  public String[] list_initial_services()
840
  {
841
    String[] refs = new String[ initial_references.size() ];
842
    int p = 0;
843
 
844
    Iterator iter = initial_references.keySet().iterator();
845
    while (iter.hasNext())
846
      {
847
        refs [ p++ ] = (String) iter.next();
848
      }
849
    return refs;
850
  }
851
 
852
  /**
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.
857
   *
858
   * @param the CORBA object
859
   * @return the object IOR representation.
860
   *
861
   * @throws BAD_PARAM if the object has not been previously connected to this
862
   * ORB.
863
   *
864
   * @throws BAD_OPERATION in the unlikely case if the local host address cannot
865
   * be resolved.
866
   *
867
   * @see string_to_object(String)
868
   */
869
  public String object_to_string(org.omg.CORBA.Object forObject)
870
  {
871
    // Handle the case when the object is known, but not local.
872
    if (forObject instanceof ObjectImpl)
873
      {
874
        Delegate delegate = ((ObjectImpl) forObject)._get_delegate();
875
        if (delegate instanceof SimpleDelegate)
876
          return ((SimpleDelegate) delegate).getIor().toStringifiedReference();
877
      }
878
 
879
    // Handle the case when the object is local.
880
    Connected_objects.cObject rec = connected_objects.getKey(forObject);
881
 
882
    if (rec == null)
883
      throw new BAD_PARAM("The object " + forObject +
884
        " has not been previously connected to this ORB"
885
      );
886
 
887
    IOR ior = createIOR(rec);
888
 
889
    return ior.toStringifiedReference();
890
  }
891
 
892
  /**
893
   * Get the local IOR for the given object, null if the object is not local.
894
   */
895
  public IOR getLocalIor(org.omg.CORBA.Object forObject)
896
  {
897
    Connected_objects.cObject rec = connected_objects.getKey(forObject);
898
    if (rec == null)
899
      return null;
900
    else
901
      return createIOR(rec);
902
  }
903
 
904
  /**
905
   * Find and return the easily accessible CORBA object, addressed by name.
906
   *
907
   * @param name the object name.
908
   * @return the object
909
   *
910
   * @throws org.omg.CORBA.ORBPackage.InvalidName if the given name is not
911
   * associated with the known object.
912
   */
913
  public org.omg.CORBA.Object resolve_initial_references(String name)
914
    throws InvalidName
915
  {
916
    org.omg.CORBA.Object object = null;
917
    try
918
      {
919
        object = (org.omg.CORBA.Object) initial_references.get(name);
920
        if (object == null && name.equals(NAME_SERVICE))
921
          {
922
            object = getDefaultNameService();
923
            if (object != null)
924
              initial_references.put(NAME_SERVICE, object);
925
          }
926
      }
927
    catch (Exception ex)
928
      {
929
        InvalidName err = new InvalidName(name);
930
        err.initCause(ex);
931
        throw err;
932
      }
933
    if (object != null)
934
      return object;
935
    else
936
      throw new InvalidName("Not found: '" + name + "'");
937
  }
938
 
939
  /**
940
   * Start the ORBs main working cycle (receive invocation - invoke on the local
941
   * object - send response - wait for another invocation).
942
   *
943
   * The method only returns after calling {@link #shutdown(boolean)}.
944
   */
945
  public void run()
946
  {
947
    running = true;
948
 
949
    // Instantiate the port server for each socket.
950
    Iterator iter = connected_objects.entrySet().iterator();
951
    Map.Entry m;
952
    Connected_objects.cObject obj;
953
 
954
    while (iter.hasNext())
955
      {
956
        m = (Map.Entry) iter.next();
957
        obj = (Connected_objects.cObject) m.getValue();
958
 
959
        portServer subserver;
960
 
961
        if (obj.identity == null)
962
          {
963
            subserver = new portServer(obj.port);
964
            portServers.add(subserver);
965
          }
966
        else
967
          subserver = (portServer) identities.get(obj.identity);
968
 
969
        if (!subserver.isAlive())
970
          {
971
            // Reuse the current thread for the last portServer.
972
            if (!iter.hasNext())
973
              {
974
                // Discard the iterator, eliminating lock checks.
975
                iter = null;
976
                subserver.run();
977
                return;
978
              }
979
            else
980
              subserver.start();
981
          }
982
      }
983
  }
984
 
985
  /**
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.
990
   */
991
  public void ensureRunning()
992
  {
993
    final OrbFunctional THIS = this;
994
 
995
    if (!running)
996
      {
997
        Thread t = new Thread()
998
        {
999
          public void run()
1000
          {
1001
            THIS.run();
1002
          }
1003
        };
1004
        t.setDaemon(true);
1005
        t.start();
1006
      }
1007
  }
1008
 
1009
  /**
1010
   * Shutdown the ORB server.
1011
   *
1012
   * @param wait_for_completion if true, the current thread is suspended until
1013
   * the shutdown process is complete.
1014
   */
1015
  public void shutdown(boolean wait_for_completion)
1016
  {
1017
    super.shutdown(wait_for_completion);
1018
    running = false;
1019
 
1020
    if (!wait_for_completion)
1021
      {
1022
        for (int i = 0; i < portServers.size(); i++)
1023
          {
1024
            portServer p = (portServer) portServers.get(i);
1025
            p.close_now();
1026
          }
1027
      }
1028
  }
1029
 
1030
  /**
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.
1035
   *
1036
   * @param ior the object IOR representation string.
1037
   *
1038
   * @return the found CORBA object.
1039
   * @see object_to_string(org.omg.CORBA.Object)
1040
   */
1041
  public org.omg.CORBA.Object string_to_object(String an_ior)
1042
  {
1043
    return nameParser.corbaloc(an_ior, this);
1044
  }
1045
 
1046
  /**
1047
   * Convert ior reference to CORBA object.
1048
   */
1049
  public org.omg.CORBA.Object ior_to_object(IOR ior)
1050
  {
1051
    org.omg.CORBA.Object object = find_local_object(ior);
1052
    if (object == null)
1053
      {
1054
        ObjectImpl impl = StubLocator.search(this, ior);
1055
        try
1056
          {
1057
            if (impl._get_delegate() == null)
1058
              impl._set_delegate(new IorDelegate(this, ior));
1059
          }
1060
        catch (BAD_OPERATION ex)
1061
          {
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));
1065
          }
1066
 
1067
        object = impl;
1068
        // TODO remove commented out code below.
1069
        // connected_objects.add(ior.key, impl, ior.Internet.port, null);
1070
      }
1071
    return object;
1072
  }
1073
 
1074
  /**
1075
   * Get the default naming service for the case when there no NameService
1076
   * entries.
1077
   */
1078
  protected org.omg.CORBA.Object getDefaultNameService()
1079
  {
1080
    if (initial_references.containsKey(NAME_SERVICE))
1081
      return (org.omg.CORBA.Object) initial_references.get(NAME_SERVICE);
1082
 
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();
1088
 
1089
    IorObject iorc = new IorObject(this, ior);
1090
    NamingContextExt namer = NamingContextExtHelper.narrow(iorc);
1091
    initial_references.put(NAME_SERVICE, namer);
1092
    return namer;
1093
  }
1094
 
1095
  /**
1096
   * Find and return the object, that must be previously connected to this ORB.
1097
   * Return null if no such object is available.
1098
   *
1099
   * @param key the object key.
1100
   * @param port the port where the object is connected.
1101
   *
1102
   * @return the connected object, null if none.
1103
   */
1104
  protected org.omg.CORBA.Object find_connected_object(byte[] key, int port)
1105
  {
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;
1113
  }
1114
 
1115
  /**
1116
   * Set the ORB parameters. This method is normally called from
1117
   * {@link #init(Applet, Properties)}.
1118
   *
1119
   * @param app the current applet.
1120
   *
1121
   * @param props application specific properties, passed as the second
1122
   * parameter in {@link #init(Applet, Properties)}. Can be <code>null</code>.
1123
   */
1124
  protected void set_parameters(Applet app, Properties props)
1125
  {
1126
    useProperties(props);
1127
 
1128
    String[][] para = app.getParameterInfo();
1129
    if (para != null)
1130
      {
1131
        for (int i = 0; i < para.length; i++)
1132
          {
1133
            if (para[i][0].equals(LISTEN_ON))
1134
              Port = Integer.parseInt(para[i][1]);
1135
            if (para[i][0].equals(REFERENCE))
1136
              {
1137
                StringTokenizer st = new StringTokenizer(para[i][1], "=");
1138
                initial_references.put(st.nextToken(),
1139
                  string_to_object(st.nextToken()));
1140
              }
1141
 
1142
            if (para[i][0].equals(ORB_ID))
1143
              orb_id = para[i][1];
1144
 
1145
            if (para[i][0].equals(SERVER_ID))
1146
              server_id = para[i][1];
1147
 
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]);
1156
            try
1157
              {
1158
                if (para[i][0].equals(NS_PORT))
1159
                  ns_port = Integer.parseInt(para[i][1]);
1160
              }
1161
            catch (NumberFormatException ex)
1162
              {
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;
1168
              }
1169
          }
1170
      }
1171
  }
1172
 
1173
  /**
1174
   * Set the ORB parameters. This method is normally called from
1175
   * {@link #init(String[], Properties)}.
1176
   *
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.
1180
   *
1181
   * @param props application specific properties that were passed as a second
1182
   * parameter in {@link init(String[], Properties)}). Can be <code>null</code>.
1183
   */
1184
  protected void set_parameters(String[] para, Properties props)
1185
  {
1186
    if (para.length > 1)
1187
      {
1188
        for (int i = 0; i < para.length - 1; i++)
1189
          {
1190
            if (para[i].endsWith("ListenOn"))
1191
              Port = Integer.parseInt(para[i + 1]);
1192
            if (para[i].endsWith("ORBInitRef"))
1193
              {
1194
                StringTokenizer st = new StringTokenizer(para[i + 1], "=");
1195
                initial_references.put(st.nextToken(),
1196
                  string_to_object(st.nextToken()));
1197
              }
1198
 
1199
            if (para[i].endsWith("ORBInitialHost"))
1200
              ns_host = para[i + 1];
1201
 
1202
            if (para[i].endsWith("ServerId"))
1203
              server_id = para[i++];
1204
            else if (para[i].endsWith("ORBid"))
1205
              orb_id = para[i++];
1206
 
1207
            try
1208
              {
1209
                if (para[i].endsWith("ORBInitialPort"))
1210
                  ns_port = Integer.parseInt(para[i + 1]);
1211
              }
1212
            catch (NumberFormatException ex)
1213
              {
1214
                throw new BAD_PARAM("Invalid " + para[i]
1215
                  + "parameter, unable to parse '"
1216
                  + props.getProperty(para[i + 1]) + "'");
1217
              }
1218
          }
1219
      }
1220
 
1221
    useProperties(props);
1222
  }
1223
 
1224
  /**
1225
   * Create IOR for the given object references.
1226
   */
1227
  protected IOR createIOR(Connected_objects.cObject ref)
1228
    throws BAD_OPERATION
1229
  {
1230
    IOR ior = new IOR();
1231
    ior.key = ref.key;
1232
    ior.Internet.port = ref.port;
1233
 
1234
    if (ref.object instanceof ObjectImpl)
1235
      {
1236
        ObjectImpl imp = (ObjectImpl) ref.object;
1237
        if (imp._ids().length > 0)
1238
          ior.Id = imp._ids() [ 0 ];
1239
      }
1240
    if (ior.Id == null)
1241
      ior.Id = ref.object.getClass().getName();
1242
    try
1243
      {
1244
        ior.Internet.host = InetAddress.getLocalHost().getHostAddress();
1245
        ior.Internet.port = ref.port;
1246
      }
1247
    catch (UnknownHostException ex)
1248
      {
1249
        throw new BAD_OPERATION("Cannot resolve the local host address");
1250
      }
1251
    return ior;
1252
  }
1253
 
1254
  /**
1255
   * Prepare object for connecting it to this ORB.
1256
   *
1257
   * @param object the object being connected.
1258
   *
1259
   * @throws BAD_PARAM if the object does not implement the
1260
   * {@link InvokeHandler}).
1261
   */
1262
  protected void prepareObject(org.omg.CORBA.Object object, IOR ior)
1263
    throws BAD_PARAM
1264
  {
1265
    /*
1266
     * if (!(object instanceof InvokeHandler)) throw new
1267
     * BAD_PARAM(object.getClass().getName() + " does not implement
1268
     * InvokeHandler. " );
1269
     */
1270
 
1271
    // If no delegate is set, set the default delegate.
1272
    if (object instanceof ObjectImpl)
1273
      {
1274
        ObjectImpl impl = (ObjectImpl) object;
1275
        try
1276
          {
1277
            if (impl._get_delegate() == null)
1278
              impl._set_delegate(new SimpleDelegate(this, ior));
1279
          }
1280
        catch (BAD_OPERATION ex)
1281
          {
1282
            // Some colaborants may throw this exception.
1283
            impl._set_delegate(new SimpleDelegate(this, ior));
1284
          }
1285
      }
1286
  }
1287
 
1288
  /**
1289
   * Write the response message.
1290
   *
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.
1298
   *
1299
   * @throws IOException
1300
   */
1301
  private void respond_to_client(OutputStream net_out,
1302
    MessageHeader msh_request, RequestHeader rh_request,
1303
    ResponseHandlerImpl handler, SystemException sysEx
1304
  ) throws IOException
1305
  {
1306
    // Set the reply header properties.
1307
    ReplyHeader reply = handler.reply_header;
1308
 
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;
1316
 
1317
    BufferedCdrOutput out =
1318
      new BufferedCdrOutput(50 + handler.getBuffer().buffer.size());
1319
    out.setOrb(this);
1320
 
1321
    out.setOffset(msh_request.getHeaderSize());
1322
 
1323
    reply.write(out);
1324
 
1325
    if (msh_request.version.since_inclusive(1, 2))
1326
      {
1327
        out.align(8);
1328
 
1329
        // Write the reply data from the handler. The handler data already
1330
        // include the necessary heading zeroes for alignment.
1331
      }
1332
    handler.getBuffer().buffer.writeTo(out);
1333
 
1334
    MessageHeader msh_reply = new MessageHeader();
1335
 
1336
    msh_reply.version = msh_request.version;
1337
    msh_reply.message_type = MessageHeader.REPLY;
1338
    msh_reply.message_size = out.buffer.size();
1339
 
1340
    // Write the reply.
1341
    msh_reply.write(net_out);
1342
    out.buffer.writeTo(net_out);
1343
    net_out.flush();
1344
  }
1345
 
1346
  /**
1347
   * Forward request to another target, as indicated by the passed exception.
1348
   */
1349
  private void forward_request(OutputStream net_out,
1350
    MessageHeader msh_request, RequestHeader rh_request, gnuForwardRequest info
1351
  ) throws IOException
1352
  {
1353
    MessageHeader msh_forward = new MessageHeader();
1354
    msh_forward.version = msh_request.version;
1355
 
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;
1360
 
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());
1365
 
1366
    rh_forward.write(out);
1367
 
1368
    if (msh_forward.version.since_inclusive(1, 2))
1369
      out.align(8);
1370
    out.write_Object(info.forward_reference);
1371
 
1372
    msh_forward.message_size = out.buffer.size();
1373
 
1374
    // Write the forwarding instruction.
1375
    msh_forward.write(net_out);
1376
    out.buffer.writeTo(net_out);
1377
    net_out.flush();
1378
  }
1379
 
1380
  /**
1381
   * Contains a single servicing task.
1382
   *
1383
   * Normally, each task matches a single remote invocation. However under
1384
   * frequent tandem submissions the same task may span over several
1385
   * invocations.
1386
   *
1387
   * @param serverSocket the ORB server socket.
1388
   *
1389
   * @throws MARSHAL
1390
   * @throws IOException
1391
   */
1392
  void serve(final portServer p, ServerSocket serverSocket)
1393
    throws MARSHAL, IOException
1394
  {
1395
    final Socket service;
1396
    service = serverSocket.accept();
1397
 
1398
    // Tell the server there are no more resources.
1399
    if (p.running_threads >= MAX_RUNNING_THREADS)
1400
      {
1401
        serveStep(service, true);
1402
        return;
1403
      }
1404
 
1405
    new Thread()
1406
      {
1407
        public void run()
1408
        {
1409
          try
1410
            {
1411
              synchronized (p)
1412
                {
1413
                  p.running_threads++;
1414
                }
1415
              serveStep(service, false);
1416
            }
1417
          finally
1418
            {
1419
              synchronized (p)
1420
                {
1421
                  p.running_threads--;
1422
                }
1423
            }
1424
        }
1425
      }.start();
1426
  }
1427
 
1428
  /**
1429
   * A single servicing step, when the client socket is alrady open.
1430
   *
1431
   * Normally, each task matches a single remote invocation. However under
1432
   * frequent tandem submissions the same task may span over several
1433
   * invocations.
1434
   *
1435
   * @param service the opened client socket.
1436
   * @param no_resources if true, the "NO RESOURCES" exception is thrown to the
1437
   * client.
1438
   */
1439
  void serveStep(Socket service, boolean no_resources)
1440
  {
1441
    try
1442
      {
1443
        Serving: while (true)
1444
          {
1445
            InputStream in = service.getInputStream();
1446
            service.setSoTimeout(TOUT_START_READING_MESSAGE);
1447
 
1448
            MessageHeader msh_request = new MessageHeader();
1449
 
1450
            try
1451
              {
1452
                msh_request.read(in);
1453
              }
1454
            catch (MARSHAL ex)
1455
              {
1456
                // This exception may be thrown due closing the connection.
1457
                return;
1458
              }
1459
 
1460
            if (max_version != null)
1461
              {
1462
                if (!msh_request.version.until_inclusive(max_version.major,
1463
                  max_version.minor))
1464
                  {
1465
                    OutputStream out = service.getOutputStream();
1466
                    new ErrorMessage(max_version).write(out);
1467
                    return;
1468
                  }
1469
              }
1470
 
1471
            byte[] r = msh_request.readMessage(in, service, TOUT_WHILE_READING,
1472
              TOUT_AFTER_RECEIVING);
1473
 
1474
            if (msh_request.message_type == MessageHeader.REQUEST)
1475
              {
1476
                RequestHeader rh_request;
1477
 
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());
1483
 
1484
                rh_request = msh_request.create_request_header();
1485
 
1486
                // Read header and auto set the charset.
1487
                rh_request.read(cin);
1488
 
1489
                // in 1.2 and higher, align the current position at
1490
                // 8 octet boundary.
1491
                if (msh_request.version.since_inclusive(1, 2))
1492
                  {
1493
                    cin.align(8);
1494
 
1495
                    // find the target object.
1496
                  }
1497
 
1498
                InvokeHandler target = (InvokeHandler) find_connected_object(
1499
                  rh_request.object_key, -1);
1500
 
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();
1505
 
1506
                // TODO log errors about not existing objects and methods.
1507
                ResponseHandlerImpl handler = new ResponseHandlerImpl(
1508
                  this, msh_request, rh_reply, rh_request);
1509
 
1510
                SystemException sysEx = null;
1511
 
1512
                try
1513
                  {
1514
                    if (no_resources)
1515
                      {
1516
                        NO_RESOURCES no = new NO_RESOURCES("Too many parallel calls");
1517
                        no.minor = Minor.Threads;
1518
                        throw no;
1519
                      }
1520
                    if (target == null)
1521
                      throw new OBJECT_NOT_EXIST();
1522
                    target._invoke(rh_request.operation, cin, handler);
1523
                  }
1524
                catch (gnuForwardRequest forwarded)
1525
                  {
1526
                    OutputStream sou = service.getOutputStream();
1527
                    forward_request(sou, msh_request, rh_request, forwarded);
1528
                    if (service != null && !service.isClosed())
1529
                      {
1530
                        // Wait for the subsequent invocations on the
1531
                        // same socket for the TANDEM_REQUEST duration.
1532
                        service.setSoTimeout(TANDEM_REQUESTS);
1533
                        continue Serving;
1534
                      }
1535
                  }
1536
                catch (UnknownException uex)
1537
                  {
1538
                    sysEx = new UNKNOWN("Unknown", 2,
1539
                      CompletionStatus.COMPLETED_MAYBE);
1540
                    sysEx.initCause(uex.originalEx);
1541
 
1542
                    org.omg.CORBA.portable.OutputStream ech = handler.createExceptionReply();
1543
 
1544
                    rh_reply.service_context = UnknownExceptionCtxHandler.addExceptionContext(
1545
                      rh_reply.service_context, uex.originalEx, ech);
1546
 
1547
                    ObjectCreator.writeSystemException(ech, sysEx);
1548
                  }
1549
                catch (SystemException ex)
1550
                  {
1551
                    sysEx = ex;
1552
 
1553
                    org.omg.CORBA.portable.OutputStream ech = handler.createExceptionReply();
1554
 
1555
                    rh_reply.service_context = UnknownExceptionCtxHandler.addExceptionContext(
1556
                      rh_reply.service_context, ex, ech);
1557
 
1558
                    ObjectCreator.writeSystemException(ech, ex);
1559
                  }
1560
                catch (Exception except)
1561
                  {
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();
1566
 
1567
                    sysEx = new UNKNOWN("Unknown", 2,
1568
                      CompletionStatus.COMPLETED_MAYBE);
1569
                    sysEx.initCause(except);
1570
 
1571
                    org.omg.CORBA.portable.OutputStream ech = handler.createExceptionReply();
1572
 
1573
                    rh_reply.service_context = UnknownExceptionCtxHandler.addExceptionContext(
1574
                      rh_reply.service_context, except, ech);
1575
 
1576
                    ObjectCreator.writeSystemException(ech, sysEx);
1577
                  }
1578
 
1579
                // Write the response.
1580
                if (rh_request.isResponseExpected())
1581
                  {
1582
                    OutputStream sou = service.getOutputStream();
1583
                    respond_to_client(sou, msh_request, rh_request, handler,
1584
                      sysEx);
1585
                  }
1586
              }
1587
            else if (msh_request.message_type == MessageHeader.CLOSE_CONNECTION
1588
              || msh_request.message_type == MessageHeader.MESSAGE_ERROR)
1589
              {
1590
                CloseMessage.close(service.getOutputStream());
1591
                service.close();
1592
                return;
1593
              }
1594
 
1595
            if (service != null && !service.isClosed())
1596
 
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;
1602
          }
1603
      }
1604
    catch (SocketException ex)
1605
      {
1606
        // OK.
1607
        return;
1608
      }
1609
    catch (IOException ioex)
1610
      {
1611
        // Network error, probably transient.
1612
        // TODO log it.
1613
        return;
1614
      }
1615
    finally
1616
      {
1617
        try
1618
          {
1619
            if (service!=null && !service.isClosed())
1620
              service.close();
1621
          }
1622
        catch (IOException ioex)
1623
          {
1624
            // OK.
1625
          }
1626
      }
1627
  }
1628
 
1629
  /**
1630
   * Set the ORB parameters from the properties that were accumulated
1631
   * from several locations.
1632
   */
1633
  protected void useProperties(Properties props)
1634
  {
1635
    if (props != null)
1636
      {
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);
1641
        try
1642
          {
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));
1657
          }
1658
        catch (NumberFormatException ex)
1659
          {
1660
            throw new BAD_PARAM("Invalid " + NS_PORT +
1661
              "property, unable to parse '" + props.getProperty(NS_PORT) +
1662
              "'"
1663
            );
1664
          }
1665
 
1666
        if (props.containsKey(SocketFactory.PROPERTY))
1667
          {
1668
            String factory = null;
1669
            try
1670
              {
1671
                factory = props.getProperty(SocketFactory.PROPERTY);
1672
                if (factory!=null)
1673
                  socketFactory = (SocketFactory)
1674
                    ObjectCreator.forName(factory).newInstance();
1675
              }
1676
            catch (Exception ex)
1677
              {
1678
                BAD_PARAM p = new BAD_PARAM("Bad socket factory "+factory);
1679
                p.initCause(ex);
1680
                throw p;
1681
              }
1682
          }
1683
 
1684
        if (props.containsKey(ORB_ID))
1685
          orb_id = props.getProperty(ORB_ID);
1686
 
1687
        if (props.containsKey(SERVER_ID))
1688
          server_id = props.getProperty(SERVER_ID);
1689
 
1690
        Enumeration en = props.elements();
1691
        while (en.hasMoreElements())
1692
          {
1693
            String item = (String) en.nextElement();
1694
            if (item.equals(REFERENCE))
1695
              initial_references.put(item,
1696
                string_to_object(props.getProperty(item))
1697
              );
1698
          }
1699
      }
1700
  }
1701
 
1702
  /**
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.
1708
   *
1709
   * The returned response is removed from the list of the currently submitted
1710
   * responses and is never returned again.
1711
   *
1712
   * @return the previously sent request that now contains the received
1713
   * response.
1714
   *
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.
1719
   */
1720
  public Request get_next_response() throws org.omg.CORBA.WrongTransaction
1721
  {
1722
    return asynchron.get_next_response();
1723
  }
1724
 
1725
  /**
1726
   * Find if any of the requests that have been previously sent with
1727
   * {@link #send_multiple_requests_deferred}, have a response yet.
1728
   *
1729
   * @return true if there is at least one response to the previously sent
1730
   * request, false otherwise.
1731
   */
1732
  public boolean poll_next_response()
1733
  {
1734
    return asynchron.poll_next_response();
1735
  }
1736
 
1737
  /**
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.
1744
   *
1745
   * @param requests the prepared array of requests.
1746
   *
1747
   * @see #poll_next_response()
1748
   * @see #get_next_response()
1749
   * @see Request#send_deferred()
1750
   */
1751
  public void send_multiple_requests_deferred(Request[] requests)
1752
  {
1753
    asynchron.send_multiple_requests_deferred(requests);
1754
  }
1755
 
1756
  /**
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.
1760
   *
1761
   * @param requests the prepared array of requests.
1762
   *
1763
   * @see Request#send_oneway()
1764
   */
1765
  public void send_multiple_requests_oneway(Request[] requests)
1766
  {
1767
    asynchron.send_multiple_requests_oneway(requests);
1768
  }
1769
 
1770
  /**
1771
   * Set the flag, forcing all server threads to terminate.
1772
   */
1773
  protected void finalize() throws java.lang.Throwable
1774
  {
1775
    running = false;
1776
    super.finalize();
1777
  }
1778
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.