Package com.sun.star.lib.uno.protocols.iiop

Source Code of com.sun.star.lib.uno.protocols.iiop.iiop$Message

/*************************************************************************
*
*  $RCSfile: iiop.java,v $
*
*  $Revision: 1.4 $
*
*  last change: $Author: kr $ $Date: 2001/02/02 09:01:03 $
*
*  The Contents of this file are made available subject to the terms of
*  either of the following licenses
*
*         - GNU Lesser General Public License Version 2.1
*         - Sun Industry Standards Source License Version 1.1
*
*  Sun Microsystems Inc., October, 2000
*
*  GNU Lesser General Public License Version 2.1
*  =============================================
*  Copyright 2000 by Sun Microsystems, Inc.
*  901 San Antonio Road, Palo Alto, CA 94303, USA
*
*  This library is free software; you can redistribute it and/or
*  modify it under the terms of the GNU Lesser General Public
*  License version 2.1, as published by the Free Software Foundation.
*
*  This library is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
*  Lesser General Public License for more details.
*
*  You should have received a copy of the GNU Lesser General Public
*  License along with this library; if not, write to the Free Software
*  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
*  MA  02111-1307  USA
*
*
*  Sun Industry Standards Source License Version 1.1
*  =================================================
*  The contents of this file are subject to the Sun Industry Standards
*  Source License Version 1.1 (the "License"); You may not use this file
*  except in compliance with the License. You may obtain a copy of the
*  License at http://www.openoffice.org/license.html.
*
*  Software provided under this License is provided on an "AS IS" basis,
*  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
*  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
*  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
*  See the License for the specific provisions governing your rights and
*  obligations concerning the Software.
*
*  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
*
*  Copyright: 2000 by Sun Microsystems, Inc.
*
*  All Rights Reserved.
*
*  Contributor(s): _______________________________________
*
*
************************************************************************/

package com.sun.star.lib.uno.protocols.iiop;


import java.io.IOException;
import java.io.DataOutput;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.OutputStream;

import java.lang.reflect.Array;

import java.util.Enumeration;
import java.util.Vector;


import com.sun.star.container.NoSuchElementException;

import com.sun.star.corba.CorbaString8;
import com.sun.star.corba.LogicalThreadID;
import com.sun.star.corba.OneThreadID;
import com.sun.star.corba.ObjectKey;

import com.sun.star.corba.giop.IORAddressingInfo;
import com.sun.star.corba.giop.MessageHeader_1_1;
import com.sun.star.corba.giop.MsgType_1_1;
import com.sun.star.corba.giop.RequestHeader_1_2;
import com.sun.star.corba.giop.ReplyHeader_1_2;
import com.sun.star.corba.giop.ReplyStatusType_1_2;
import com.sun.star.corba.giop.TargetAddress;
import com.sun.star.corba.giop.Version;

import com.sun.star.corba.iop.IOR;
import com.sun.star.corba.iop.ServiceContext;
import com.sun.star.corba.iop.TaggedProfile;

import com.sun.star.uno.IBridge;
import com.sun.star.uno.Type;
import com.sun.star.uno.Enum;

import com.sun.star.lib.uno.environments.remote.IMarshal;
import com.sun.star.lib.uno.environments.remote.IMessage;
import com.sun.star.lib.uno.environments.remote.IUnmarshal;
import com.sun.star.lib.uno.environments.remote.IProtocol;
import com.sun.star.lib.uno.environments.remote.Job;
import com.sun.star.lib.uno.environments.remote.Protocol;
import com.sun.star.lib.uno.environments.remote.ThreadID;

import com.sun.star.lib.uno.typedesc.MethodDescription;
import com.sun.star.lib.uno.typedesc.TypeDescription;


/**
* This class implements the complete IIOP protocol
* from corba. The functionality is reachable through
* the <code>IProtocol</code> interface.
* <p>
* @version   $Revision: 1.4 $ $ $Date: 2001/02/02 09:01:03 $
* @author       Kay Ramme
* @see         com.sun.star.lib.uno.environments.remote.IProtocol
* @since       UDK1.0
*/
public class iiop extends Protocol {
  /**
   * When set to true, enables various debugging output.
   */
  static public final boolean DEBUG = false;

  static public final TypeDescription __ObjectKeyTypeDescription = TypeDescription.getTypeDescription(ObjectKey.class);
  static public final TypeDescription __LogicalThreadIDTypeDescription = TypeDescription.getTypeDescription(LogicalThreadID.class);
  static public final TypeDescription __RequestHeader_1_2TypeDescription = TypeDescription.getTypeDescription(RequestHeader_1_2.class);
  static public final TypeDescription __ReplyHeader_1_2TypeDescription = TypeDescription.getTypeDescription(ReplyHeader_1_2.class);

  static private int int_convertEndianness(int value) {
    int b4 = value & 0xFF;
    int b3 = (value >> 8) & 0xFF;
    int b2 = (value >> 16) & 0xFF;
    int b1 = (value >> 24) & 0xFF;

    return (b4 << 24) | (b3 << 16) | (b2 << 8) | b1;
  }

  static private byte magic[] = new byte[] {(byte)'G', (byte)'I', (byte)'O', (byte)'P'};

  static private MessageHeader_1_1 readMessageHeader(InputStream inputStream) throws IOException {
    DataInputStream dataInputStream = new DataInputStream(inputStream);

    MessageHeader_1_1 messageHeader = new MessageHeader_1_1(dataInputStream.readByte(),
                                dataInputStream.readByte(),
                                dataInputStream.readByte(),
                                dataInputStream.readByte(),
                                new Version(dataInputStream.readByte(), // version major
                                      dataInputStream.readByte()), // version minor
                                dataInputStream.readByte(), // flags
                                dataInputStream.readByte(),
                                dataInputStream.readInt());
   
    if(messageHeader.flags != 0)
      messageHeader.message_size = int_convertEndianness(messageHeader.message_size);

    if(DEBUG) System.err.println("##### " + iiop.class.getName() + ".readMessageHeader:" + messageHeader.message_type + " " + messageHeader.message_size);

    if((messageHeader.magic_1 != magic[0])
    || (messageHeader.magic_2 != magic[1])
    || (messageHeader.magic_3 != magic[2])
    || (messageHeader.magic_4 != magic[3]))
      throw new IOException("invalid magic:"
                  + " " + (char)messageHeader.magic_1
                  + " " + (char)messageHeader.magic_2
                  + " " + (char)messageHeader.magic_3
                  + " " + (char)messageHeader.magic_4);
     
    return messageHeader;
  }

  static private void writeMessageHeader(int type, int size, DataOutput dataOutput) throws IOException {
    if(DEBUG) System.err.println("##### " + iiop.class.getName() + ".writeMessageHeader:" + type + " " + size);

    dataOutput.writeByte(magic[0]);
    dataOutput.writeByte(magic[1]);
    dataOutput.writeByte(magic[2]);
    dataOutput.writeByte(magic[3]);

    dataOutput.writeByte(1); // version major
    dataOutput.writeByte(2); // version minor
   
    dataOutput.writeByte(0); // flags
    dataOutput.writeByte(type);
    dataOutput.writeInt(size);
  }

  static private ObjectKey unmarshalObjectKey(boolean littleEndian, byte bytes[]) throws Exception {
    Unmarshal unmarshal = new Unmarshal(bytes, bytes.length, littleEndian, null);
    return (ObjectKey)unmarshal.readObject(__ObjectKeyTypeDescription);
  }

  static private LogicalThreadID unmarshalLogicalThreadID(boolean littleEndian, byte bytes[]) throws Exception {
    Unmarshal unmarshal = new Unmarshal(bytes, bytes.length, littleEndian, null);
    return (LogicalThreadID)unmarshal.readObject(__LogicalThreadIDTypeDescription);
  }



  protected int               _requestId;
  protected IBridge           _iBridge;
  protected boolean           _bIgnoreNextCloseConnection = false;
  protected Vector            _flushList;


  class Message implements IMessage {
    String    _oid;
    Object    _object;
    TypeDescription      _typeDescription;
      MethodDescription    _methodDescription;
    String    _operation;
    ThreadID  _threadId;
    Unmarshal _unmarshal;
    boolean   _synchron;
    boolean   _exception;
    Object    _params[];

    Message(String    oid,
        Object    object,
        TypeDescription      typeDescription,
          MethodDescription    methodDescription,
        String    operation,
        ThreadID  threadId,
        Unmarshal unmarshal,
        boolean   synchron,
        boolean   exception,
        Object    params[])
    {
      _oid       = oid;
      _object    = object;
      _typeDescription      = typeDescription;
        _methodDescription    = methodDescription;
      _operation = operation;
      _threadId  = threadId;
      _unmarshal = unmarshal;
      _synchron  = synchron;
      _exception = exception;
      _params    = params;
    }
   
    public String getOperation() {
      return _operation;
    }

    public ThreadID getThreadID() {
      return _threadId;
    }

    public TypeDescription getInterface() {
      return _typeDescription;
    }

    public boolean isSynchron() {
      return _synchron;
    }

    public boolean mustReply() {
      return _synchron;
    }

    public boolean isException() {
      return _exception;
    }

    public String getOid() {
      return _oid;
    }

    public Object getData(Object params[][]) throws Exception {
      Object result = _object;

      if(_exception) {
//          String exceptionName = _unmarshal.read_asciistring();
        result = _unmarshal.readThrowable();
//          result = _unmarshal.readObject(Class.forName(exceptionName));
      }
      else {
        params[0] = _params;
       
        if(_operation == null) { // is it a reply?
          result = _unmarshal.readObject((TypeDescription)_methodDescription.getReturnSig());
       
          for(int i = 0; i < _params.length; ++ i)
            if(_methodDescription.getOutSignature()[i] != null) // is it an out parameter
              Array.set(_params[i], 0, _unmarshal.readObject(_methodDescription.getOutSignature()[i].getComponentType()));
        }
        else { // it is a request
          for(int i = 0; i < _params.length; ++ i) {
            if(_methodDescription.getInSignature()[i] != null) // is it an in parameter?
              if(_methodDescription.getOutSignature()[i] != null) {// is it also an out -> inout?
                Object inout[] = (Object[])Array.newInstance(_methodDescription.getOutSignature()[i].getComponentType().getZClass(), 1);
                inout[0] = _unmarshal.readObject(_methodDescription.getOutSignature()[i].getComponentType());
                _params[i] = inout;
              }
              else  // it is only an in parameter
                _params[i] = _unmarshal.readObject(_methodDescription.getInSignature()[i]);
            else // it is only an out parameter, so provide the holder
              _params[i] = Array.newInstance(_methodDescription.getOutSignature()[i].getComponentType().getZClass(), 1);
          }
        }
      }
      return result;
    }
  }

  public iiop(IBridge iBridge) {
    _iBridge           = iBridge;

    _flushList = new Vector();
  }

  static private byte[] marshalObjectKey(String oId, String sType) throws Exception {
    Marshal marshal = new Marshal(false, null);
    marshal.writeObject(__ObjectKeyTypeDescription, new ObjectKey(new CorbaString8(oId), new CorbaString8(sType)));
    byte bytes[] = marshal.reset();

    return bytes;
  }

  static private byte[] marshalLogicalThreadID(LogicalThreadID logicalThreadID) throws Exception {
    Marshal marshal = new Marshal(false, null);
    marshal.writeObject(__LogicalThreadIDTypeDescription, logicalThreadID);
    return marshal.reset();
  }


  /**
   * Returns a string representation of this object.
   * <p>
   * @return   the string representation
   * @see      java.lang.Object#toString
   */
  public String toString() {
    return "iiop: statistics - messages created:" + _requestsSend + " requests recieved:" + _requestsRecieved;
  }

  /**
   * Gets the name of the protocol.
   * <p>
   * @result  the name of the protocol (iiop)
   * @see     com.sun.star.lib.uno.environments.remote.IProtocol#getName
   */
  public String getName() {
    return "iiop";
  }

  /**
   * Tells the protocol to ignore the next <code>closeConnection</code>
   * meta request.
   * <p>
   * @see     com.sun.star.lib.uno.environments.remote.IProtocol#ignore_next_closeConnection
   */
  public void ignore_next_closeConnection() {
    _bIgnoreNextCloseConnection = true;
  }

  /**
   * Tells the protocol to send a <code>closeConnection</code>
   * meta request.
   * <p>
   * @param outputStream   the output stream
   * @see                  com.sun.star.lib.uno.environments.remote.IProtocol#send_closeConnection
   */
  public void send_closeConnection(OutputStream outputStream) throws IOException {
    writeMessageHeader(MsgType_1_1.CloseConnection_value, 0, new DataOutputStream(outputStream));
  }


  private IMessage readRequest(Unmarshal unmarshal) throws Exception {
    ++ _requestsRecieved;

    RequestHeader_1_2 requestHeader = (RequestHeader_1_2)unmarshal.readObject(__RequestHeader_1_2TypeDescription);
   
    LogicalThreadID logicalThreadID = unmarshalLogicalThreadID(unmarshal.isLittleEndian(), requestHeader.service_context[0].context_data);
   
    ObjectKey objectKey = unmarshalObjectKey(unmarshal.isLittleEndian(), requestHeader.target.object_key);
   
    boolean synchron = (requestHeader.response_flags != 0); // if != 0, then it should be 3
   
    TypeDescription typeDescription = TypeDescription.getTypeDescription(objectKey.sType.theString);
    ThreadID threadId = new ThreadID(logicalThreadID.IDs[0].threadID);

    MethodDescription methodDescription = typeDescription.getMethodDescription(requestHeader.operation.theString);

    Object params[] = new Object[methodDescription.getInSignature().length];

    if(synchron) // if the request is synchron, it is pending
      putPendingReply(threadId, new Object[]{params, methodDescription.getOutSignature(), methodDescription.getReturnSig(), new Integer(requestHeader.request_id)});
   
    IMessage iMessage = new Message(objectKey.sOid.theString,
                    null,
                    typeDescription,
                    methodDescription,
                    requestHeader.operation.theString,
                    threadId,
                    unmarshal,
                    synchron,
                    false,
                    params);

      if(DEBUG) System.err.println("##### " + getClass().getName() + ".readRequest:" + iMessage);
   
    return iMessage;
  }
 
  private IMessage readReply(Unmarshal unmarshal) throws Exception {
    ReplyHeader_1_2 replyHeader = (ReplyHeader_1_2)unmarshal.readObject(__ReplyHeader_1_2TypeDescription);
    LogicalThreadID logicalThreadID = unmarshalLogicalThreadID(unmarshal.isLittleEndian(), replyHeader.service_context[0].context_data);
   
    ThreadID threadId = new ThreadID(logicalThreadID.IDs[0].threadID);

    Object data[] = (Object[])removePendingRequest(threadId);
    IMessage iMessage = new Message(null,               // oid
                    null,               // object
                    null,               // interface
                    (MethodDescription)data[1],    // MMDesc
                    null,               // operation
                    threadId,
                    unmarshal,
                    false,              // synchron
                    replyHeader.reply_status != ReplyStatusType_1_2.NO_EXCEPTION,
                    (Object[])data[0]); // params

      if(DEBUG) System.err.println("##### " + getClass().getName() + ".readReply:" + iMessage);

    return iMessage;
  }

  /**
   * Reads a job from the given stream.
   * <p>
   * @return  thread read job.
   * @see     com.sun.star.lib.uno.environments.remote.Job
   * @see                  com.sun.star.lib.uno.environments.remote.IProtocol#readJob
   */
  public IMessage readMessage(InputStream inputStream) throws Exception {
    MessageHeader_1_1  messageHeader = readMessageHeader(inputStream);

    byte bytes[] = new byte[messageHeader.message_size];

    int read = 0;
    do {
      int act_read = inputStream.read(bytes, read, bytes.length - read);

      if(act_read < 0)
        throw new com.sun.star.uno.RuntimeException("iiop - got EOF");

      read += act_read;
    }
    while(read < bytes.length);

    boolean littleEndian = messageHeader.flags != 0;

    Unmarshal unmarshal = new Unmarshal(bytes, messageHeader.message_size, littleEndian, _iBridge);

    IMessage iMessage = null;

    switch(messageHeader.message_type) {
    case MsgType_1_1.Request_value:          iMessage = readRequest(unmarshal); break;
    case MsgType_1_1.Reply_value:           iMessage = readReply(unmarshal); break;
    case MsgType_1_1.MessageError_value:    throw new RuntimeException("WARNING: iiop - recieved a message error!!!");
    case MsgType_1_1.CancelRequest_value:
    case MsgType_1_1.LocateRequest_value:
    case MsgType_1_1.LocateReply_value:     throw new RuntimeException("WARNING: iiop - received unsupported message of type:" + messageHeader.message_type);
    case MsgType_1_1.CloseConnection_value:
      if(!_bIgnoreNextCloseConnection) {
        inputStream.close();
      }
      else
        _bIgnoreNextCloseConnection = false;

      break;

    default: throw new RuntimeException("ERROR: iiop - received message of unknown type!!!");
    }

    return iMessage;
  }

  public void writeRequest(String oid, TypeDescription typeDescription, String operation, ThreadID threadId, Object params[], Boolean synchron[], Boolean mustReply[]) throws Exception {
    if(DEBUG) System.err.println("##### " + getClass().getName() + ".writeRequest:" + oid + " " + typeDescription + " " + operation);

    ++ _requestsSend;


    MethodDescription methodDescription = typeDescription.getMethodDescription(operation);

    Marshal marshal = new Marshal(false, _iBridge);

    TargetAddress targetAddress = new TargetAddress(-7,
                            (short)0,
                            marshalObjectKey(oid, typeDescription.getTypeName()),
                            new TaggedProfile(2, new byte[]{(byte)7, (byte)6, (byte)5}),
                            new IORAddressingInfo(3,
                                        new IOR(new CorbaString8(""),
                                            new TaggedProfile[0])
                                          )
                              );

    LogicalThreadID logicalThreadID = new LogicalThreadID(new OneThreadID[]{new OneThreadID(0, threadId.getBytes())});
    ServiceContext serviceContexts[] = new ServiceContext[]{new ServiceContext(4, marshalLogicalThreadID(logicalThreadID))};


    // if the type of request is not provided, use methodDescription if available, otherwise fall back to synchron
    if(synchron[0] == null) {
      if(methodDescription == null)
        synchron[0] = new Boolean(true);
      else
        synchron[0] = new Boolean(!methodDescription.isOneway());
    }


    int messageType = MsgType_1_1.Request_value;
    marshal.writeObject(__RequestHeader_1_2TypeDescription,
              new RequestHeader_1_2(++ _requestId,
                          (byte)(synchron[0].booleanValue() ? 3 : 0),
                          (byte)0, (byte)0, (byte)0,
                          targetAddress,
                          new CorbaString8(operation),
                          serviceContexts)
                );

    // write the in parameters
    for(int i = 0; i < methodDescription.getInSignature().length; ++ i) {
      if(methodDescription.getInSignature()[i] != null) { // is it an in parameter
        if(methodDescription.getOutSignature()[i] != null// is it also an out parameter
          marshal.writeObject(methodDescription.getOutSignature()[i].getComponentType(), ((Object [])params[i])[0]);
        else // in only
          marshal.writeObject(methodDescription.getInSignature()[i], params[i]);
      }
    }

    // add the marshal to the flush list
    _flushList.addElement(new Object[]{MsgType_1_1.Request, marshal});

    if(synchron[0].booleanValue()) // if we are waiting for a reply, the reply is pending
      putPendingRequest(threadId, new Object[]{params, methodDescription});

  }

  public void writeReply(boolean exception, ThreadID threadId, Object result) throws Exception {
    if(DEBUG) System.err.println("##### " + getClass().getName() + ".writeReply:" + exception + " " + threadId + " " + result);

    Object data[] = (Object[])removePendingReply(threadId);

    Object params[]   = (Object[])data[0];
    TypeDescription signature[] = (TypeDescription[])data[1];
    TypeDescription resType    = (TypeDescription)data[2];
    int requestId     = ((Integer)data[3]).intValue();

    Marshal marshal = new Marshal(false, _iBridge);

    LogicalThreadID logicalThreadID = new LogicalThreadID(new OneThreadID[]{new OneThreadID(0, threadId.getBytes())});
    ServiceContext serviceContexts[] = new ServiceContext[]{new ServiceContext(4, marshalLogicalThreadID(logicalThreadID))};

    int messageType = MsgType_1_1.Reply_value;
    marshal.writeObject(__ReplyHeader_1_2TypeDescription,
              new ReplyHeader_1_2(requestId,
                        exception ? ReplyStatusType_1_2.USER_EXCEPTION : ReplyStatusType_1_2.NO_EXCEPTION,
                        serviceContexts)
                );

    if(exception) {
      resType = TypeDescription.getTypeDescription(result.getClass());
//        resType = TypeDescription.getType(com.sun.star.uno.Exception.class);
      signature = new TypeDescription[0];
    }

    marshal.writeObject(resType, result);

    for(int i = 0; i < signature.length; ++ i)
      if(signature[i] != null)
        marshal.writeObject(signature[i].getComponentType(), Array.get(params[i], 0));

    // add the marshal to the flush list
    _flushList.addElement(new Object[]{MsgType_1_1.Reply, marshal});
  }


  public synchronized void flush(DataOutput dataOutput) throws Exception {
    if(DEBUG) System.err.println("##### " + getClass().getName() + ".flush:" + dataOutput);

    Enumeration elements = _flushList.elements();
    while(elements.hasMoreElements()) {
      Object objects[] = (Object[])elements.nextElement();
      Enum enum = (Enum)objects[0];
      Marshal marshal = (Marshal)objects[1];

      int size = marshal.getSize();
      byte bytes[] = marshal.reset();

      writeMessageHeader(enum.getValue(), size, dataOutput);
      if(DEBUG) System.err.println("##### " + getClass().getName() + ".flush - bytes:" + size);

      dataOutput.write(bytes, 0, size);
    }

    _flushList = new Vector();
  }


  public IMarshal createMarshal() {
    return new Marshal(true, _iBridge);
  }

  public IUnmarshal createUnmarshal(byte bytes[]) {
    return new Unmarshal(bytes, bytes.length, true, _iBridge);
  }
}
TOP

Related Classes of com.sun.star.lib.uno.protocols.iiop.iiop$Message

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.