package org.jacorb.orb.giop; /* * JacORB - a free Java ORB * * Copyright (C) 1997-2014 Gerald Brose / The JacORB Team. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ import java.io.IOException; import org.jacorb.orb.SystemExceptionHelper; import org.omg.CORBA.MARSHAL; import org.omg.GIOP.LocateStatusType_1_2; import org.omg.GIOP.MsgType_1_1; import org.omg.GIOP.ReplyStatusType_1_0; import org.omg.GIOP.ReplyStatusType_1_2; import org.slf4j.Logger; /** * @author Gerald Brose * */ public class ReplyOutputStream extends ServiceContextTransportingOutputStream { private final boolean is_locate_reply; private final Logger logger; public ReplyOutputStream ( org.omg.CORBA.ORB orb, int request_id, ReplyStatusType_1_2 reply_status, int giop_minor, boolean is_locate_reply, Logger logger) { super(orb); this.logger = logger; this.is_locate_reply = is_locate_reply; setGIOPMinor( giop_minor ); writeGIOPMsgHeader( MsgType_1_1._Reply, giop_minor ); switch( giop_minor ) { case 0 : { // GIOP 1.0 Reply == GIOP 1.1 Reply, fall through } case 1 : { //Technically, GIOP.idl only allows either //ReplyStatusType_1_0 or ReplyStatusType_1_2, but not //both. We go around this by compiling GIOP.idl two //times //GIOP 1.1 // ReplyHeader_1_0 repl_hdr = // new ReplyHeader_1_0( alignment_ctx, // request_id, // ReplyStatusType_1_0.from_int( reply_status.value() )); // ReplyHeader_1_0Helper.write( this, repl_hdr ); // inlining for performance org.omg.IOP.ServiceContextListHelper.write(this , Messages.service_context ); write_ulong( request_id ); org.omg.GIOP.ReplyStatusType_1_0Helper.write( this, ReplyStatusType_1_0.from_int( reply_status.value() )); break; } case 2 : { //GIOP 1.2 // ReplyHeader_1_2 repl_hdr = // new ReplyHeader_1_2( request_id, // reply_status, // alignment_ctx ); // ReplyHeader_1_2Helper.write( this, repl_hdr ); // more inlining write_ulong( request_id ); org.omg.GIOP.ReplyStatusType_1_2Helper.write(this, reply_status); org.omg.IOP.ServiceContextListHelper.write( this, Messages.service_context ); markHeaderEnd(); //use padding if minor 2 break; } default : { throw new MARSHAL( "Unknown GIOP minor: " + giop_minor ); } } } public void write_to( GIOPConnection conn ) throws IOException { if( is_locate_reply ) { final ReplyInputStream in = new ReplyInputStream( orb, getBufferCopy() ); try { final LocateReplyOutputStream out = getLocateReplyOutputStream(in); try { out.write_to( conn ); } finally { out.close(); } } finally { in.close(); } } else { super.write_to( conn ); } } private LocateReplyOutputStream getLocateReplyOutputStream(ReplyInputStream replyInputStream) { final LocateReplyOutputStream result; if( replyInputStream.getGIOPMinor() < 2 ) { //GIOP 1.0 or 1.1 switch( replyInputStream.rep_hdr.reply_status.value() ) { case ReplyStatusType_1_2._NO_EXCEPTION : { int status; //_non_existent? if (replyInputStream.read_boolean()) { //_non_existent == true status = LocateStatusType_1_2._UNKNOWN_OBJECT; } else { //_non_existent == false status = LocateStatusType_1_2._OBJECT_HERE; } result = new LocateReplyOutputStream( orb, replyInputStream.rep_hdr.request_id, status, replyInputStream.getGIOPMinor() ); break; } case ReplyStatusType_1_2._USER_EXCEPTION : { //fall through } case ReplyStatusType_1_2._SYSTEM_EXCEPTION : { //uh oh, can't reply with exception if (logger.isErrorEnabled()) { logger.error("Received an exception when processing a LocateRequest" ); } // GIOP prior to 1.2 doesn't have the status // LOC_SYSTEM_EXCEPTION, so we have to return // OBJECT_UNKNOWN (even if it may not be unknown) result = new LocateReplyOutputStream( orb, replyInputStream.rep_hdr.request_id, LocateStatusType_1_2._UNKNOWN_OBJECT, replyInputStream.getGIOPMinor() ); break; } case ReplyStatusType_1_2._LOCATION_FORWARD : { result = new LocateReplyOutputStream( orb, replyInputStream.rep_hdr.request_id, LocateStatusType_1_2._OBJECT_FORWARD, replyInputStream.getGIOPMinor() ); //FIXME: it would be more efficient to copy //the body part of this buffer to the new //buffer result.write_IOR( org.omg.IOP.IORHelper.read( replyInputStream )); break; } default: throw new IllegalArgumentException("ReplyStatus is invalid"); } } else { //GIOP 1.2 switch( replyInputStream.rep_hdr.reply_status.value() ) { case ReplyStatusType_1_2._NO_EXCEPTION : { int status; //_non_existent? if( replyInputStream.read_boolean() ) { //_non_existent == true status = LocateStatusType_1_2._UNKNOWN_OBJECT; } else { //_non_existent == false status = LocateStatusType_1_2._OBJECT_HERE; } result = new LocateReplyOutputStream( orb, replyInputStream.rep_hdr.request_id, status, replyInputStream.getGIOPMinor() ); break; } case ReplyStatusType_1_2._USER_EXCEPTION : { //uh oh, can't reply with user exception if (logger.isErrorEnabled()) { logger.error("Received an exception when processing a LocateRequest - mapping to UNKNOWN system exception" ); } result = new LocateReplyOutputStream( orb, replyInputStream.rep_hdr.request_id, LocateStatusType_1_2._LOC_SYSTEM_EXCEPTION, replyInputStream.getGIOPMinor() ); SystemExceptionHelper.write( result, new org.omg.CORBA.UNKNOWN() ); break; } case ReplyStatusType_1_2._SYSTEM_EXCEPTION : { result = new LocateReplyOutputStream( orb, replyInputStream.rep_hdr.request_id, LocateStatusType_1_2._LOC_SYSTEM_EXCEPTION, replyInputStream.getGIOPMinor() ); //FIXME: inefficient, use copying SystemExceptionHelper.write( result, SystemExceptionHelper.read( replyInputStream )); break; } case ReplyStatusType_1_2._LOCATION_FORWARD : { result = new LocateReplyOutputStream( orb, replyInputStream.rep_hdr.request_id, LocateStatusType_1_2._OBJECT_FORWARD, replyInputStream.getGIOPMinor() ); //FIXME: it would be more efficient to copy //the body part of this buffer to the new //buffer result.write_IOR( org.omg.IOP.IORHelper.read( replyInputStream )); break; } default: throw new IllegalArgumentException("ReplyStatus is invalid"); } } return result; } }