Main Page   Packages   Class Hierarchy   Compound List   File List   Compound Members  

GIOPProtocol.java

Go to the documentation of this file.
00001 /***
00002  * Jonathan: an Open Distributed Processing Environment 
00003  * Copyright (C) 1999-2000 France Telecom R&D
00004  * Copyright (C) 2001 Kelua SA
00005  * 
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2 of the License, or (at your option) any later version.
00010  * 
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  * 
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  * 
00020  * Contact: jonathan@objectweb.org
00021  *
00022  * Author: Bruno Dumant
00023  *
00024  * ------------------------------------------------------
00025  * $ID$
00026  * ------------------------------------------------------
00027  */
00028 
00029 package org.objectweb.david.libs.protocols.giop;
00030 
00031 import org.objectweb.jonathan.apis.kernel.Context;
00032 import org.objectweb.jonathan.apis.kernel.ClassPathFinder;
00033 import org.objectweb.jonathan.apis.kernel.Component;
00034 import org.objectweb.jonathan.apis.binding.Identifier;
00035 import org.objectweb.jonathan.apis.kernel.JonathanException;
00036 import org.objectweb.jonathan.apis.kernel.InternalException;
00037 import org.objectweb.jonathan.apis.binding.NamingContext;
00038 import org.objectweb.jonathan.apis.resources.Scheduler;
00039 import org.objectweb.jonathan.apis.resources.Chunk;
00040 import org.objectweb.jonathan.apis.resources.ChunkFactory;
00041 import org.objectweb.jonathan.apis.presentation.*;
00042 import org.objectweb.jonathan.apis.binding.*;
00043 import org.objectweb.jonathan.apis.protocols.*;
00044 
00045 import org.objectweb.david.apis.services.handler.ServicesHandler;
00046 
00047 import org.objectweb.david.libs.helpers.CORBAHelpers;
00048 
00049 import org.omg.IOP.ServiceContext;
00050 import org.omg.GIOP.MsgType_1_0;
00051 import org.omg.GIOP.ReplyStatusType_1_0;
00052 import org.omg.GIOP.LocateStatusType_1_0;
00053 import org.omg.CORBA.SystemException;
00054 import org.omg.CORBA.UNKNOWN;
00055 import org.omg.CORBA.CompletionStatus;
00056 import org.omg.CORBA.portable.UnknownException;
00057 
00058 import java.io.IOException;
00059 import java.io.InputStream;
00060 import java.util.Properties;
00061 
00065 final public class GIOPProtocol implements Protocol {
00066    
00068    static final public String corba_prefix =  "IDL:CORBA/";
00069 
00070    static final ServiceContext[] no_context = new ServiceContext[0];
00071    
00078    public boolean verbose;
00079 
00083     private boolean tryTcpIp = true;
00084 
00086    static byte[] header = { (byte) 'G', (byte) 'I', (byte) 'O', (byte) 'P', 1, 0 };
00087 
00088    ChunkFactory chunk_factory;
00089    MarshallerFactory marshaller_factory;
00090    Scheduler scheduler;
00092    ClassPathFinder finder;
00093 
00094 
00096    ReplyHolder[] table = new ReplyHolder[17];
00098    ReplyHolder reusable;
00100    int size = 0;
00102    int id = 0;
00103    
00104    
00106    NamingContext adapter;
00107    ClientSession_Low client_session_low = new ClientSession_Low();;
00108    ServerSession_Low server_session_low = new ServerSession_Low();
00109 
00111    ServicesHandler services_handler;
00112    
00148    public GIOPProtocol(Context _c,Scheduler scheduler,
00149                        MarshallerFactory marshaller_factory,
00150                        ChunkFactory chunk_factory,
00151                        NamingContext adapter,
00152                        ServicesHandler services_handler)
00153       throws JonathanException {
00154 
00155       this.scheduler = scheduler;
00156       this.adapter = adapter;
00157       this.services_handler = services_handler;
00158       finder = (ClassPathFinder) _c.getValue("/classpath_finder",'/');
00159       this.marshaller_factory = marshaller_factory;
00160       this.chunk_factory = chunk_factory;
00161       Object prop = _c.getValue("/david/giop/verbose",'/');
00162       if (prop != Context.NO_VALUE) {
00163          verbose = ((Boolean) prop).booleanValue();
00164       } else {
00165          verbose = false;
00166       }
00167 
00168       Object prop2 = _c.getValue("/jonathan/HTTP Tunneling/try with tcpip", '/');
00169       if (prop2 != Context.NO_VALUE) {
00170           tryTcpIp = ((Boolean)prop2).booleanValue();
00171       }
00172    }
00173    
00178    public boolean isAnInvocationProtocol() {
00179       return true;
00180    }
00181 
00189    public ProtocolGraph newProtocolGraph(ProtocolGraph next) {
00190       return new GIOPProtocolGraph(next);
00191    }
00192 
00204    public ProtocolGraph newProtocolGraph(ProtocolGraph next_one, ProtocolGraph next_two) {
00205       return new GIOPProtocolGraph(next_one, next_two);
00206    }
00207    
00215    public GIOPSessionIdentifier newSessionIdentifier(byte[] object_key, 
00216                                                      SessionIdentifier next) {
00217 
00218        return new GIOPCltSessionIdentifier(object_key,next);
00219    }
00220 
00229    public GIOPSessionIdentifier newSessionIdentifier(byte[] object_key, 
00230                                                      SessionIdentifier next_one,
00231                                                      SessionIdentifier next_two) {
00232        return new GIOPCltSessionIdentifier(object_key, next_one, next_two);
00233    }
00234    
00235    void sendError(Session_High sender) {
00236       try {
00237          if (verbose) {
00238             System.err.println("GIOP message error: bad magic bytes." +
00239                                " " + Thread.currentThread());
00240          }
00241          Marshaller marshaller = marshaller_factory.newMarshaller();
00242          sender.prepare(marshaller);
00243          marshaller.writeByteArray(header,0,6);
00244          marshaller.writeBoolean(marshaller.isLittleEndian());
00245          marshaller.writeByte((byte) MsgType_1_0._MessageError);
00246          marshaller.writeInt(0);
00247          sender.send(marshaller);
00248       } catch (Exception ignored) {}
00249       sender.close();
00250    }
00251 
00252    ServiceContext[] decodeServices(UnMarshaller unmarshaller) 
00253       throws JonathanException {
00254       ServiceContext[] contexts = no_context;
00255       int seq_length = unmarshaller.readInt();
00256       //System.err.println("SEQ L " + seq_length);
00257       if (seq_length != 0) {
00258          //debug.Debug.state();
00259          //new Exception().printStackTrace(System.err);
00260          //System.exit(-1);
00261          int len;
00262          contexts = new ServiceContext[seq_length];
00263          int context_id;
00264          byte[] context_data;
00265          for (int i = 0; i < seq_length; i++) {
00266             context_id = unmarshaller.readInt();
00267             len = unmarshaller.readInt();
00268             context_data = new byte[len];
00269             unmarshaller.readByteArray(context_data,0,len);
00270             contexts[i] = new ServiceContext(context_id,context_data);
00271          }
00272       }
00273       return contexts;
00274    }
00275 
00276 
00277    void encodeRequestServices(Marshaller marshaller,int rq_id,
00278                               boolean response_expected, byte[] object_key) 
00279       throws JonathanException {
00280       ServiceContext[] contexts = null;
00281       if (services_handler != null) {
00282          contexts = 
00283             services_handler.getRequestContexts(rq_id,response_expected,object_key,
00284                                                 marshaller.getContext());
00285       }
00286       encodeServices(contexts,marshaller);
00287    }
00288             
00289    void encodeReplyServices(Marshaller marshaller,int rq_id) 
00290       throws JonathanException {
00291 
00292       ServiceContext[] contexts = null;
00293       if (services_handler != null) {
00294          contexts = services_handler.getReplyContexts(rq_id, marshaller.getContext());
00295       }
00296       encodeServices(contexts,marshaller);      
00297    }
00298             
00299 
00300    void encodeServices(ServiceContext[] contexts, Marshaller marshaller) 
00301       throws JonathanException {
00302       if (contexts != null) {
00303          int seq_length = contexts.length;
00304          int len;
00305          byte[] context_data;
00306          marshaller.writeInt(seq_length);
00307          for (int i = 0; i < seq_length; i++) {
00308             marshaller.writeInt(contexts[i].context_id);
00309             context_data = contexts[i].context_data;
00310             len = context_data.length;
00311             marshaller.writeInt(len);
00312             marshaller.writeByteArray(context_data,0,len);
00313          }
00314       } else {
00315          marshaller.writeInt(0);
00316       } 
00317    }
00318          
00319    
00320    synchronized ReplyHolder registerHolder(Session_High lower) {
00321       ReplyHolder holder;
00322       if (reusable == null) {
00323          holder = new ReplyHolder(lower);
00324          id++;
00325          holder.id = id;
00326       } else {
00327          holder = reusable;
00328          holder.lower = lower;
00329          reusable = reusable.next;
00330       }
00331       int len = table.length;
00332       int index = (holder.id & 0x7FFFFFFF) % len;
00333       holder.next = table[index];
00334       table[index] = holder;
00335       size++;
00336       if (size > len / 2) {
00337          rehash(len);
00338       }
00339       return holder;
00340    }
00341    
00346    synchronized void removeHolder(int id) {
00347       int index = (id & 0x7FFFFFFF) % table.length;
00348       ReplyHolder first = table[index];
00349       ReplyHolder holder = first;
00350       ReplyHolder prev = null;
00351       while (holder.id != id) {
00352          prev = holder;
00353          holder = holder.next;
00354       }
00355       if (holder != null) {
00356          size--;
00357          if (prev != null) {
00358             prev.next = holder.next;
00359          } else {
00360             table[index] = holder.next;
00361          }
00362          holder.next = reusable;
00363          holder.lower = null;
00364          reusable = holder;
00365       }
00366    }
00367    
00373    synchronized ReplyHolder getHolder(int id) {
00374       int index = (id & 0x7FFFFFFF) % table.length;
00375       ReplyHolder holder = table[index];
00376       while (! (holder == null || holder.id == id)) {
00377          holder = holder.next;
00378       }
00379       return holder;
00380    }
00381 
00382    void rehash(int len) {
00383       int new_len = 2 * len + 1;
00384       int index;
00385       ReplyHolder holder, next_holder;
00386       ReplyHolder[] new_table = new ReplyHolder[new_len];
00387       for (int i = 0; i < len; i++) {
00388          holder = table[i];
00389          while (holder != null) {
00390             next_holder = holder.next;
00391             // rehashing
00392             index = (holder.id & 0x7FFFFFFF) % new_len;
00393             holder.next = new_table[index];
00394             new_table[index] = holder;
00395             //
00396             holder = next_holder; 
00397          }  
00398       }  
00399       table = new_table;         
00400    }   
00401 
00402    synchronized void forwardException(JonathanException e, Session_High lower) {
00403       int len = table.length;
00404       ReplyHolder holder;
00405       for (int i = 0; i < len; i++) {
00406          holder = table[i];
00407          while (holder != null) {
00408             if (holder.lower == lower) {
00409                holder.sendReply(e);
00410             }
00411             holder = holder.next;
00412          }
00413       }
00414    }
00415    
00416    class GIOPProtocolGraph implements ProtocolGraph {
00417       ProtocolGraph next;
00418       ProtocolGraph next_two;
00419       
00420       public GIOPProtocolGraph(ProtocolGraph next) {
00421          this.next = next;
00422          this.next_two = null;
00423       }
00424 
00425       public GIOPProtocolGraph(ProtocolGraph next_one, ProtocolGraph next_two) {
00426          this.next = next_one;
00427          this.next_two = next_two;
00428       }
00429       
00430       public boolean equals(Object o) {
00431          if (o instanceof GIOPProtocolGraph) {
00432             GIOPProtocolGraph p_graph = (GIOPProtocolGraph) o;
00433             boolean one = false, two = false;
00434             if (next != null) {
00435                one = next.equals(p_graph.next);
00436             } else {
00437                one = p_graph.next == null;
00438             }
00439 
00440             if (next_two != null) {
00441                two = next_two.equals(p_graph.next_two);
00442             } else {
00443                two = p_graph.next_two == null;
00444             }
00445             
00446             return one && two;
00447          }
00448          return false;
00449       }
00450 
00451        // err... how do we do that with two lower protocols??
00452       public int hashCode() {
00453          if (next != null) {
00454             return  next.hashCode();
00455          } else {
00456             return 0;
00457          }
00458       }
00459       
00460       public SessionIdentifier export(Session_Low ignored)
00461          throws JonathanException {
00462          if (next == null) {
00463             throw new ExportException("Badly specified participants");
00464          }
00465          return next_two != null ? new GIOPSrvSessionIdentifier(next.export(server_session_low), next_two.export(server_session_low)) : new GIOPSrvSessionIdentifier(next.export(server_session_low));
00466       }      
00467    }
00468    
00469    class GIOPSrvSessionIdentifier implements GIOPSessionIdentifier {
00470       SessionIdentifier next;
00471       SessionIdentifier next_two;
00472       
00473       public GIOPSrvSessionIdentifier(SessionIdentifier next) {
00474          this.next = next;
00475          this.next_two = null;
00476       }
00477 
00478       public GIOPSrvSessionIdentifier(SessionIdentifier next_one, SessionIdentifier next_two) {
00479          this.next = next_one;
00480          this.next_two = next_two;
00481       }
00482       
00483       public Session_High bind(Session_Low ignored)
00484          throws JonathanException {
00485          throw new BindException("Bad session identifier type");
00486       }
00487       
00488       public void unexport() {
00489          next.unexport();
00490          if (next_two != null) next_two.unexport();
00491       }
00492       
00493       public Protocol getProtocol() {
00494          return GIOPProtocol.this;
00495       }
00496 
00497       public SessionIdentifier next() {
00498          return next;
00499       }
00500 
00501       public SessionIdentifier next_two() {
00502          return next_two;
00503       }
00504 
00505       public boolean equals(Object o) {
00506          if (o instanceof GIOPSrvSessionIdentifier) {
00507             GIOPSrvSessionIdentifier session_id = (GIOPSrvSessionIdentifier) o;
00508 
00509             boolean one = false, two = false;
00510             if (next != null) {
00511                one = next.equals(session_id.next);
00512             } else {
00513                one = session_id.next == null;
00514             }
00515 
00516             if (next_two != null) {
00517                two = next_two.equals(session_id.next_two);
00518             } else {
00519                two = session_id.next_two == null;
00520             }
00521             return one && two;
00522             
00523          }
00524          return false;
00525       }
00526       
00527       public int hashCode() {
00528          if (next != null) {
00529             return  next.hashCode();
00530          } else {
00531             return 0;
00532          }
00533       }      
00534    }
00535 
00536    class GIOPCltSessionIdentifier extends GIOPSrvSessionIdentifier {
00537       byte[] object_key;
00538 
00539       public GIOPCltSessionIdentifier(byte[] object_key,SessionIdentifier next) {
00540 
00541          super(next);
00542          this.object_key = object_key;
00543       }
00544       public GIOPCltSessionIdentifier(byte[] object_key, SessionIdentifier next_one, SessionIdentifier next_two) {
00545 
00546          super(next_one, next_two);
00547          this.object_key = object_key;
00548       }
00549       
00550       public Session_High bind(Session_Low ignored)
00551          throws JonathanException {
00552          if (next == null && next_two == null) {
00553             throw new BindException("Badly specified participants");
00554          }
00555          try {
00556              // SylvainHack: to test first-stage escape set the
00557              // /jonathan/HTTP Tunneling/try with tcpip value to false
00558              if (tryTcpIp) {
00559                  return new ClientSession_High(object_key,next.bind(client_session_low));
00560              } else {
00561                  throw new JonathanException("escape!");
00562              }
00563          } catch (JonathanException e) {
00564              if (next_two != null) {
00565                  // do we have an http protocol to escape to?
00566                  return new ClientSession_High(object_key,next_two.bind(client_session_low));
00567              } else {
00568                  // propagate
00569                  throw e;
00570              }
00571          }
00572       }
00573        
00574       public void unexport() {}
00575 
00576       public boolean equals(Object o) {
00577          if (o instanceof GIOPCltSessionIdentifier) {
00578             GIOPCltSessionIdentifier session_id = (GIOPCltSessionIdentifier) o;
00579             int len = object_key.length;
00580             byte[] other_key = session_id.object_key;
00581             if (other_key.length == len) {
00582                for (int i = 0; i < len; i++) {
00583                   if (other_key[i] != object_key[i]) {
00584                      return false;
00585                   }
00586                }
00587                return super.equals(session_id);
00588             } 
00589          }
00590          return false;
00591       }
00592       
00593       public int hashCode() {
00594          int hash = 0;
00595          int len = object_key.length;
00596          for (int i = 0; i < len; i++) {
00597             hash += (object_key[i] << (i % 32));
00598          }
00599          return  hash + super.hashCode();
00600       }
00601 
00602       public String toString() {
00603          String str = "GIOPCltSessionIdentifier[key[";
00604          if (object_key.length > 0) {
00605             str = str + object_key[0];
00606          }
00607          for (int i = 1; i < object_key.length; i++) {
00608             str = str + "," + object_key[i];
00609          }
00610          if (next_two != null) {
00611              str = str + "],"+ next + ", " + next_two + "]";
00612          } else {
00613              str = str + "]," + next + "]";
00614          }
00615          return str;
00616       }  
00617    }
00618    
00619    final class ClientSession_Low implements Session_Low {
00620       
00621       ClientSession_Low() {}
00622       
00623       public void send(UnMarshaller unmarshaller,Session_High sender)
00624          throws JonathanException {
00625 
00626          // reading the unmarshaller header
00627          int msg_type, msg_size;
00628          boolean little_endian;
00629          try {
00630             if (unmarshaller.readByte() != 'G' ||
00631                 unmarshaller.readByte() != 'I' ||
00632                 unmarshaller.readByte() != 'O' || 
00633                 unmarshaller.readByte() != 'P') {
00634                unmarshaller.close();
00635                sendError(sender);
00636                return;
00637             }
00638             byte major = unmarshaller.readByte();
00639             byte minor = unmarshaller.readByte();                     
00640             little_endian = unmarshaller.readByte() == 0 ? false : true;
00641             msg_type = unmarshaller.readByte();
00642             unmarshaller.setByteOrder(little_endian);
00643             msg_size = unmarshaller.readInt();
00644             unmarshaller.setSize(msg_size);
00645             switch (msg_type) {
00646                case MsgType_1_0._Reply:
00647                   ServiceContext[] contexts = decodeServices(unmarshaller);
00648                   int rq_id = unmarshaller.readInt();
00649                   if (services_handler != null) {
00650                      services_handler.handleReplyContexts(contexts,rq_id,
00651                                                           unmarshaller.getContext());
00652                   }
00653                   ReplyHolder reply = getHolder(rq_id);
00654                   if (reply == null) {
00655                      // we can't find the request: return silently
00656                      unmarshaller.close();
00657                      if (verbose) {
00658                         System.err.println("Request #" + rq_id + " not found.");
00659                      }
00660                   } else {
00661                      Component component = 
00662                         scheduler.getCurrent().getContext().
00663                         getComponent("UnknownException",(char) 0);
00664                      if (component != null) {
00665                         unmarshaller.getContext().addElement("UnknownException",component,(char) 0);
00666                      }
00667                      reply.sendReply(unmarshaller);
00668                   }
00669                   return;
00670                case MsgType_1_0._CloseConnection:
00671                   unmarshaller.close();
00672                   return;
00673                case MsgType_1_0._MessageError:
00674                   unmarshaller.close();
00675                   throw new InternalException("GIOP Message error.");
00676                case MsgType_1_0._LocateReply:
00677                default:
00678                   unmarshaller.close();
00679                   sendError(sender);
00680                   return;
00681             }
00682          } catch (JonathanException e) {
00683             unmarshaller.close();
00684             send(e,sender);
00685          }
00686       }
00687       
00688       public void send(JonathanException e, Session_High sender) {
00689          forwardException(e,sender);
00690       }
00691    }
00692    
00693    final class ServerSession_Low implements Session_Low {
00694 
00695       ServerSession_Low() {}
00696       
00697       public void send(UnMarshaller unmarshaller,Session_High sender)
00698          throws JonathanException {
00699 
00700          // reading the message header
00701          int msg_type, msg_size;
00702          boolean little_endian;
00703          boolean unmarshaller_opened = true;
00704          try {
00705             if (unmarshaller.readByte() != 'G' ||
00706                 unmarshaller.readByte() != 'I' ||
00707                 unmarshaller.readByte() != 'O' || 
00708                 unmarshaller.readByte() != 'P') {
00709                if (verbose) {
00710                   System.err.println("GIOP message error: bad magic bytes.");
00711                }
00712                unmarshaller.close();
00713                sendError(sender);
00714                return;
00715             }
00716             byte major = unmarshaller.readByte();
00717             byte minor = unmarshaller.readByte();                     
00718             little_endian = unmarshaller.readByte() == 0 ? false : true;
00719             msg_type = unmarshaller.readByte();
00720             unmarshaller.setByteOrder(little_endian);
00721             msg_size = unmarshaller.readInt();
00722             unmarshaller.setSize(msg_size);
00723             //System.err.println("MSG SIZE " + msg_size + " " + msg_type);
00724             int rq_id, len;
00725             switch (msg_type) {
00726                case MsgType_1_0._Request:
00727                   //System.err.println("GIOPProtocol receiving request");
00728                   ServiceContext[] contexts = decodeServices(unmarshaller);
00729                   //System.err.println("b");
00730                   rq_id = unmarshaller.readInt();
00731                   boolean response_expected = unmarshaller.readBoolean();
00732                   RequestSession request_session = null;
00733                   try {
00734                      len = unmarshaller.readInt();
00735                      byte[] object_key = new byte[len];
00736                      unmarshaller.readByteArray(object_key,0,len);
00737                      if (services_handler != null) {
00738                         services_handler.handleRequestContexts(contexts,
00739                                                                rq_id,
00740                                                                response_expected,
00741                                                                object_key,
00742                                                                unmarshaller.getContext());
00743                      }
00744                      Identifier id = adapter.decode(object_key,0,len);
00745                      request_session = (RequestSession) id.bind(null,null);
00746                      if (request_session != null) {
00747                         //System.err.println("GIOPProtocol forwarding request");
00748                         // 1st case: standard case
00749                         ServerSession_High reply_session = response_expected ?
00750                            new ServerSession_High(sender, rq_id) : null;
00751                         request_session.send(unmarshaller,reply_session);
00752                         return;
00753                      }
00754                      unmarshaller_opened = false;
00755                      unmarshaller.close();                        
00756                      if (response_expected) {
00757                         Object fwd = id.resolve();
00758                         if (fwd != null) {
00759                            // 2nd case: Location forward
00760                            Marshaller marshaller =
00761                               prepareReplyMessage(rq_id,MsgType_1_0._Reply,
00762                                                   ReplyStatusType_1_0._LOCATION_FORWARD);
00763                            marshaller.writeReference(fwd);
00764                            sendMessage(marshaller,sender);
00765                            sender.close();
00766                            return;
00767                         } else {
00768                            // 3rd case: Object doesn't exist
00769                            // System.err.println("GIOPProtocol object not found " + id);
00770                            sendSystemException(corba_prefix +
00771                                                "OBJECT_NOT_EXIST:1.0",
00772                                                0,
00773                                                CompletionStatus.COMPLETED_NO,
00774                                                rq_id,
00775                                                sender);
00776                         }
00777                      }
00778                   } catch (UnknownException e) {
00779                      if (verbose) {
00780                         System.err.println("Exception caught in GIOP");
00781                         e.originalEx.printStackTrace();
00782                      }
00783                      if (unmarshaller_opened) {
00784                         unmarshaller.close();
00785                      }
00786                      if (response_expected) {
00787                         scheduler.getCurrent().getContext().
00788                            addElement("UnknownException",Throwable.class,
00789                                       e.originalEx,(char) 0);
00790                         sendSystemException(corba_prefix + "UNKNOWN:1.0",
00791                                             e.minor,
00792                                             e.completed,
00793                                             rq_id,
00794                                             sender);
00795                      }
00796                   } catch (SystemException e) {
00797                      if (verbose) {
00798                         System.err.println("Exception caught in GIOP");
00799                         e.printStackTrace();
00800                      }
00801                      if (unmarshaller_opened) {
00802                         unmarshaller.close();
00803                      }
00804                      if (response_expected) {
00805                         sendSystemException(e,rq_id,sender);
00806                      }
00807                   } catch (Exception e) {
00808                      if (verbose) {
00809                         System.err.println("Exception caught in GIOP");
00810                         e.printStackTrace();
00811                      }
00812                      if (unmarshaller_opened) {
00813                         unmarshaller.close();
00814                      }
00815                      if (response_expected) {
00816                         CompletionStatus completed;
00817                         if (request_session != null) {
00818                            completed = CompletionStatus.COMPLETED_MAYBE;
00819                         } else {
00820                            completed = CompletionStatus.COMPLETED_NO;
00821                         }
00822                         SystemException sexp =
00823                            CORBAHelpers.systemException(e,completed);
00824                         if (sexp instanceof UNKNOWN) {
00825                            if (e instanceof JonathanException) {
00826                               e = ((JonathanException) e).represents();
00827                            }
00828                            scheduler.getCurrent().getContext().
00829                               addElement("UnknownException",Throwable.class,
00830                                          e,(char) 0);
00831                            sendSystemException(corba_prefix + "UNKNOWN:1.0",
00832                                                sexp.minor,
00833                                                sexp.completed,
00834                                                rq_id,
00835                                                sender);
00836                         } else {
00837                            sendSystemException(sexp,rq_id,sender);
00838                         }
00839                      }
00840                   }
00841                   return;
00842                case MsgType_1_0._CancelRequest:
00843                   rq_id = unmarshaller.readInt();
00844                   unmarshaller_opened = false;                     
00845                   unmarshaller.close();
00846                   return;
00847                case MsgType_1_0._LocateRequest:
00848                   rq_id = unmarshaller.readInt();
00849                   len = unmarshaller.readInt();
00850                   byte[] object_key = new byte[len];
00851                   unmarshaller.readByteArray(object_key,0,len);
00852                   unmarshaller_opened = false;                     
00853                   unmarshaller.close();               
00854                   //Marshaller marshaller = marshaller_factory.newMarshaller();
00855                   //sender.prepare(marshaller);
00856                   Identifier id = adapter.decode(object_key,0,len);
00857                   Marshaller marshaller = null;
00858                   if (id.isValid()) {
00859                      Object fwd = id.resolve();
00860                      if (fwd != null) {
00861                         marshaller =
00862                            prepareReplyMessage(rq_id,MsgType_1_0._LocateReply,
00863                                                LocateStatusType_1_0._OBJECT_FORWARD);
00864                         marshaller.writeReference(fwd);
00865                      } else {
00866                         marshaller =
00867                            prepareReplyMessage(rq_id,MsgType_1_0._LocateReply,
00868                                                LocateStatusType_1_0._OBJECT_HERE);
00869                      }
00870                   } else {
00871                      marshaller =
00872                         prepareReplyMessage(rq_id,MsgType_1_0._LocateReply,
00873                                             LocateStatusType_1_0._UNKNOWN_OBJECT);
00874                   }
00875                   sendMessage(marshaller,sender);                  
00876                   sender.close();
00877                   return;
00878                case MsgType_1_0._MessageError:
00879                   unmarshaller_opened = false;                     
00880                   unmarshaller.close();
00881                   sender.close();
00882                   throw new InternalException("GIOP Message error.");
00883                default:
00884                   unmarshaller_opened = false;                     
00885                   unmarshaller.close();
00886                   if (verbose) {
00887                      System.err.println("Sending error to sender. Bad message tag: " + msg_type); 
00888                   }
00889                   sendError(sender);
00890                   return;
00891             }
00892          } catch (JonathanException e) {
00893             if (verbose) {
00894                e.printStackTrace();
00895                //debug.Debug.state();
00896                //System.exit(-1);
00897             }
00898             if (unmarshaller_opened) {
00899                unmarshaller.close();
00900             }
00901             sender.close();
00902          }
00903       }
00904 
00905       public void send(JonathanException e, Session_High sender) {
00906          if (verbose) {
00907             System.err.println("Caught exception related to " + sender);
00908             e.printStackTrace();
00909          }
00910          sender.close();
00911       }
00912 
00913       void sendSystemException(SystemException e,
00914                                int rq_id,
00915                                Session_High session) {
00916          String name = e.getClass().getName();
00917          int begin = name.lastIndexOf('.') + 1;
00918          name = name.substring(begin);
00919          sendSystemException(corba_prefix + name + ":1.0",
00920                              e.minor,
00921                              e.completed,
00922                              rq_id,
00923                              session);
00924       }
00925       
00926       void sendSystemException(String id, int minor, CompletionStatus status,
00927                                int rq_id,
00928                                Session_High session) {
00929          try {
00930             Marshaller marshaller =
00931                prepareReplyMessage(rq_id,MsgType_1_0._Reply,
00932                                    ReplyStatusType_1_0._SYSTEM_EXCEPTION);
00933             marshaller.writeString8(id);
00934             marshaller.writeInt(minor);
00935             marshaller.writeInt(status.value());
00936             sendMessage(marshaller,session);
00937          } catch (Exception ignored) {
00938          } finally {
00939             session.close();
00940          }
00941       }
00942    }
00943 
00944 
00945    class ClientSession_High extends GIOPSession_High implements Session_High {
00946       byte[] object_key;
00947       
00948 
00953       ClientSession_High(byte[] object_key,Session_High lower) {
00954          super(lower);
00955          this.object_key = object_key;
00956       }
00957       
00958       public ReplyInterface prepareInvocation(Marshaller marshaller)
00959          throws JonathanException {
00960          marshaller.writeByteArray(header,0,6);
00961          marshaller.writeBoolean(marshaller.isLittleEndian());
00962          marshaller.writeByte((byte) MsgType_1_0._Request);
00963          marshaller.writeInt(0); // size
00964          ReplyHolder reply = registerHolder(lower);
00965          encodeRequestServices(marshaller,reply.id,true,object_key);  
00966          marshaller.writeInt(reply.id);
00967          marshaller.writeBoolean(true);
00968          int len = object_key.length;
00969          marshaller.writeInt(len);
00970          marshaller.writeByteArray(object_key,0,len);
00971          return reply;
00972       }
00973    
00974       public void prepare(Marshaller marshaller)
00975          throws JonathanException {
00976          marshaller.writeByteArray(header,0,6);
00977          marshaller.writeBoolean(marshaller.isLittleEndian());
00978          marshaller.writeByte((byte) MsgType_1_0._Request);
00979          marshaller.writeInt(0); // size
00980          encodeRequestServices(marshaller,0,false,object_key);
00981          marshaller.writeInt(0); // request id
00982          marshaller.writeBoolean(false);            
00983          int len = object_key.length;
00984          marshaller.writeInt(len);
00985          marshaller.writeByteArray(object_key,0,len);
00986       }
00987    }
00988    
00989    Marshaller prepareReplyMessage(int rq_id,int msg_type,int reply_type)
00990       throws JonathanException {
00991       Marshaller marshaller = marshaller_factory.newMarshaller();
00992       marshaller.writeByteArray(header,0,6);
00993       marshaller.writeBoolean(marshaller.isLittleEndian());
00994       marshaller.writeByte((byte) msg_type);
00995       marshaller.writeInt(0); // size            
00996       if (msg_type == MsgType_1_0._Reply) {
00997          encodeReplyServices(marshaller,rq_id);
00998       }
00999       marshaller.writeInt(rq_id);
01000       marshaller.writeInt(reply_type);
01001       return marshaller;
01002    }
01003    
01004    class ServerSession_High extends GIOPSession_High implements ReplySession {
01005       int rq_id;
01006       
01007       public ServerSession_High(Session_High lower,int rq_id) {
01008          super(lower);
01009          this.rq_id = rq_id;
01010       }
01011       
01012       public Marshaller prepareReply()
01013          throws JonathanException {
01014 
01015          return prepareReplyMessage(rq_id,MsgType_1_0._Reply,
01016                                     ReplyStatusType_1_0._NO_EXCEPTION);
01017       }
01018       
01019       public Marshaller prepareExceptionReply()
01020          throws JonathanException {
01021          return prepareReplyMessage(rq_id,MsgType_1_0._Reply,
01022                                     ReplyStatusType_1_0._USER_EXCEPTION);
01023       }
01024    }
01025 
01026    void sendMessage(Marshaller marshaller,Session_High lower) 
01027       throws JonathanException {
01028       Chunk first = marshaller.getState();
01029       Chunk c = first;
01030       int size = 0;
01031       while (c != null) {
01032          size += c.top - c.offset;
01033          c = c.next;
01034       }
01035       int offset = marshaller.getOffset();
01036       marshaller.setOffset(8);
01037       marshaller.writeInt(size - 12);
01038       marshaller.setOffset(offset);
01039       if (lower.direct()) {
01040          lower.send(marshaller);
01041       } else {
01042          Marshaller m = marshaller_factory.newMarshaller();
01043          lower.prepare(m);
01044          m.write(marshaller.getState());
01045          marshaller.reset();
01046          lower.send(m);
01047       }
01048    }
01049 
01050    class GIOPSession_High {
01051       Session_High lower;
01052       
01053       GIOPSession_High(Session_High lower) {
01054          this.lower = lower;
01055       }
01056       
01057       public boolean direct() {
01058          return false;
01059       }
01060       
01061       public void send(Marshaller marshaller) throws JonathanException {
01062           sendMessage(marshaller,lower);
01063       }
01064    
01065       public void close() {
01066          lower.close();
01067       }      
01068    }
01069    
01070    class ReplyHolder implements ReplyInterface {
01071       Object reply;
01073       int id;
01075       ReplyHolder next;
01076       Session_High lower;
01077    
01078       ReplyHolder(Session_High lower) {
01079          super();
01080          this.lower = lower;
01081       }   
01082 
01083       public synchronized UnMarshaller listen() throws JonathanException {
01084          try {
01085             while (reply == null) {
01086                scheduler.wait(this);
01087             }
01088             UnMarshaller message = (UnMarshaller) reply;
01089             int reply_status = message.readInt();
01090             switch (reply_status) {
01091                case ReplyStatusType_1_0._NO_EXCEPTION:
01092                   return message;
01093                case ReplyStatusType_1_0._USER_EXCEPTION:
01094                   throw new ServerException(message);
01095                case ReplyStatusType_1_0._SYSTEM_EXCEPTION:
01096                   try {
01097                      SystemException sys_excep = null;
01098                      String str = message.readString8();
01099                      Object server_ex = 
01100                         message.getContext().getValue("UnknownException",(char) 0);
01101                      if (server_ex != Context.NO_VALUE) {
01102                         sys_excep = new GIOPUnknownException((Throwable) server_ex);
01103                      } else {
01104                         int begin = str.lastIndexOf('/') + 1;
01105                         int end = str.lastIndexOf(':');
01106                         if (begin < 0 || end < begin) {
01107                            throw new JonathanException("Bad repository id " + str);
01108                         }
01109                         str = str.substring(begin,end);
01110                         str = "org.omg.CORBA." + str;
01111                         sys_excep = (SystemException)
01112                            finder.findClass(str).newInstance();
01113                      }
01114                      sys_excep.minor = message.readInt();
01115                      sys_excep.completed =
01116                         CompletionStatus.from_int(message.readInt());
01117                      throw sys_excep;
01118                   } catch (Exception e) {
01119                      throw new JonathanException(e);
01120                   } finally {
01121                      message.close();
01122                   }
01123                case ReplyStatusType_1_0._LOCATION_FORWARD:
01124                   try {
01125                      Object ref = message.readReference();
01126                      throw new ForwardException(ref);
01127                   } finally {
01128                      message.close();
01129                   }
01130                default:
01131                   // never reached
01132                   return null;
01133             }
01134          } catch (InterruptedException e) {
01135             throw new JonathanException(e);
01136          } catch (ClassCastException e) {
01137             throw (JonathanException) reply;
01138             //           } catch (JonathanException e) {
01139             //              e.printStackTrace();
01140             //              throw e;            
01141             //           } catch (RuntimeException e) {
01142             //              e.printStackTrace();
01143             //              throw e;
01144          } finally {
01145             reply = null;
01146             removeHolder(id);
01147          }
01148       }
01149       
01150       public synchronized boolean available() {
01151          return reply != null;
01152       }
01153       
01154       final synchronized void sendReply(Object reply) {
01155          this.reply = reply;
01156          scheduler.notify(this);
01157       }
01158    }
01159 
01160    static class GIOPUnknownException extends UnknownException {
01161       GIOPUnknownException(Throwable ex) {
01162          super(ex);
01163       }
01164       
01165       public String toString() {
01166          if (originalEx != null) {
01167             return "Unknown Server Exception : " + originalEx;
01168          } else {
01169             return super.toString();
01170          }
01171       }
01172    }
01173 }

Generated at Fri May 31 19:23:32 2002 for Jonathan by doxygen1.2.6 written by Dimitri van Heesch, © 1997-2001