diff --git a/core/src/main/java/org/jacorb/orb/CDRInputStream.java b/core/src/main/java/org/jacorb/orb/CDRInputStream.java index 5c04b916d..404064a9f 100644 --- a/core/src/main/java/org/jacorb/orb/CDRInputStream.java +++ b/core/src/main/java/org/jacorb/orb/CDRInputStream.java @@ -79,10 +79,21 @@ public class CDRInputStream private Map recursiveTCMap; /** indexes to support mark/reset */ - private int marked_pos; - private int marked_index; - private int marked_chunk_end_pos; - private int marked_valueNestingLevel; + public class MarkedPosition { + public final int pos; + public final int index; + public final int chunk_end_pos; + public final int valueNestingLevel; + + public MarkedPosition(int pos, int index, int chunk_end_pos, int valueNestingLevel) + { + this.pos = pos; + this.index = index; + this.chunk_end_pos = chunk_end_pos; + this.valueNestingLevel = valueNestingLevel; + } + } + private MarkedPosition markedPosition; private boolean closed; @@ -1247,7 +1258,7 @@ public final String read_string() } else if (buffer.length < stringTerminatorPosition + 1) { - throw new MARSHAL("buffer too small"); + throw new MARSHAL("buffer too small: " + buffer.length + " < " + (stringTerminatorPosition + 1)); } if ((buffer[stringTerminatorPosition] == 0)) @@ -1647,24 +1658,46 @@ public boolean markSupported() @Override public void mark(final int readLimit) { - marked_pos = pos; - marked_index = index; - marked_chunk_end_pos = chunk_end_pos; - marked_valueNestingLevel = valueNestingLevel; + markedPosition = getCurrentPosition(); + } + + /** + * Gets the current position of the input stream without setting + * the internal marked position. + * + * @return The current position. + */ + public MarkedPosition getCurrentPosition() + { + return new MarkedPosition(pos, index, chunk_end_pos, valueNestingLevel); } @Override public void reset() throws IOException { - if( pos < 0 ) + if( this.pos < 0 ) + { + throw new MARSHAL("Mark has not been set!"); + } + + setCurrentPosition(markedPosition); + } + + /** + * Reset the input stream to a specific marked position. + */ + public void setCurrentPosition(MarkedPosition mark) + throws IOException + { + if (markedPosition == null) { throw new MARSHAL("Mark has not been set!"); } - pos = marked_pos; - index = marked_index; - chunk_end_pos = marked_chunk_end_pos; - valueNestingLevel = marked_valueNestingLevel; + this.pos = mark.pos; + this.index = mark.index; + this.chunk_end_pos = mark.chunk_end_pos; + this.valueNestingLevel = mark.valueNestingLevel; } // JacORB-specific diff --git a/core/src/main/java/org/jacorb/orb/portableInterceptor/DefaultClientInterceptorHandler.java b/core/src/main/java/org/jacorb/orb/portableInterceptor/DefaultClientInterceptorHandler.java index 02ea69d77..2eee1e3eb 100644 --- a/core/src/main/java/org/jacorb/orb/portableInterceptor/DefaultClientInterceptorHandler.java +++ b/core/src/main/java/org/jacorb/orb/portableInterceptor/DefaultClientInterceptorHandler.java @@ -25,6 +25,7 @@ import java.util.Map; import org.jacorb.orb.ApplicationExceptionHelper; +import org.jacorb.orb.CDRInputStream; import org.jacorb.orb.Delegate; import org.jacorb.orb.Delegate.INVOCATION_KEY; import org.jacorb.orb.SystemExceptionHelper; @@ -272,6 +273,18 @@ public void handle_receive_exception ( ApplicationException exception, { if ( info != null ) { + // Save the position in the reply. If the user exception type has + // any valuetype data, the reply stream will get marked during + // insert and a call to reset will reset to that marker instead of + // the start of the exception. Later calls to the UserException catch + // block in the idl generated Stub code will try to unmarshal the specific + // exception and will fail if reply is not at the correct mark. + CDRInputStream.MarkedPosition replyPosition = null; + if (reply != null) + { + replyPosition = reply.getCurrentPosition(); + } + info.received_exception_id = exception.getId(); try { @@ -294,7 +307,7 @@ public void handle_receive_exception ( ApplicationException exception, { try { - reply.reset(); + reply.setCurrentPosition(replyPosition); } catch ( Exception e ) { diff --git a/test/regression/src/test/idl/ExceptionServer.idl b/test/regression/src/test/idl/ExceptionServer.idl index 523ae6c59..c62af035f 100644 --- a/test/regression/src/test/idl/ExceptionServer.idl +++ b/test/regression/src/test/idl/ExceptionServer.idl @@ -12,6 +12,7 @@ module org string message; }; + interface ExceptionServer { void throwRuntimeException(in string message); @@ -23,6 +24,9 @@ module org void throwUserExceptionWithMessage2(in string reason, in string message) raises (MyUserException); + + void throwAnyException(in string reason, in any anything) + raises (AnyException); }; }; }; diff --git a/test/regression/src/test/idl/Tests.idl b/test/regression/src/test/idl/Tests.idl index 39adeb0b0..accd2bd5f 100644 --- a/test/regression/src/test/idl/Tests.idl +++ b/test/regression/src/test/idl/Tests.idl @@ -26,6 +26,12 @@ module org string field2; }; + // example Exception with any type + exception AnyException + { + any anything; + }; + // example unbounded Sequence typedef sequence< long > UnboundedData; diff --git a/test/regression/src/test/idl/TimingServer.idl b/test/regression/src/test/idl/TimingServer.idl index c2677bf71..72ab02192 100644 --- a/test/regression/src/test/idl/TimingServer.idl +++ b/test/regression/src/test/idl/TimingServer.idl @@ -10,6 +10,7 @@ module org { long operation (in long id, in long delay); char ex_op (in char ch, in long delay) raises (EmptyException); + void any_ex_op (in string reason, in any anything, in long delay) raises (AnyException); long long server_time (in long delay); }; diff --git a/test/regression/src/test/java/org/jacorb/test/bugs/bug940/TimingServerImpl.java b/test/regression/src/test/java/org/jacorb/test/bugs/bug940/TimingServerImpl.java index bc71bba85..50b26fc73 100644 --- a/test/regression/src/test/java/org/jacorb/test/bugs/bug940/TimingServerImpl.java +++ b/test/regression/src/test/java/org/jacorb/test/bugs/bug940/TimingServerImpl.java @@ -1,7 +1,9 @@ package org.jacorb.test.bugs.bug940; +import org.jacorb.test.AnyException; import org.jacorb.test.EmptyException; import org.jacorb.test.TimingServerPOA; +import org.omg.CORBA.Any; public class TimingServerImpl extends TimingServerPOA { @@ -30,6 +32,13 @@ else if (ch == '$') } } + @Override + public void any_ex_op(String reason, Any anything, int delay) throws AnyException + { + sleep(delay); + throw new AnyException(reason, anything); + } + @Override public long server_time(int delay) { diff --git a/test/regression/src/test/java/org/jacorb/test/bugs/bugjac493/TimingServerImpl.java b/test/regression/src/test/java/org/jacorb/test/bugs/bugjac493/TimingServerImpl.java index ebbef08ba..c3db86be1 100644 --- a/test/regression/src/test/java/org/jacorb/test/bugs/bugjac493/TimingServerImpl.java +++ b/test/regression/src/test/java/org/jacorb/test/bugs/bugjac493/TimingServerImpl.java @@ -1,7 +1,9 @@ package org.jacorb.test.bugs.bugjac493; +import org.jacorb.test.AnyException; import org.jacorb.test.EmptyException; import org.jacorb.test.TimingServerPOA; +import org.omg.CORBA.Any; public class TimingServerImpl extends TimingServerPOA { @@ -28,6 +30,12 @@ else if (ch == '$') } } + public void any_ex_op(String reason, Any anything, int delay) throws AnyException + { + sleep(delay); + throw new AnyException(reason, anything); + } + public long server_time(int delay) { long time = System.currentTimeMillis(); diff --git a/test/regression/src/test/java/org/jacorb/test/bugs/bugjac493/TimingTest.java b/test/regression/src/test/java/org/jacorb/test/bugs/bugjac493/TimingTest.java index d1d83d1b4..f6d10c720 100644 --- a/test/regression/src/test/java/org/jacorb/test/bugs/bugjac493/TimingTest.java +++ b/test/regression/src/test/java/org/jacorb/test/bugs/bugjac493/TimingTest.java @@ -174,11 +174,21 @@ public void ex_op_excep(ExceptionHolder excep_holder) wrong_exception ("ex_op_excep", excep_holder); } + public void any_ex_op_excep(ExceptionHolder excep_holder) + { + wrong_exception ("any_ex_op_excep", excep_holder); + } + public void ex_op(char ami_return_val) { wrong_reply ("ex_op"); } + public void any_ex_op() + { + wrong_reply ("any_ex_op"); + } + public void operation_excep(ExceptionHolder excep_holder) { wrong_exception ("operation_excep", excep_holder); diff --git a/test/regression/src/test/java/org/jacorb/test/bugs/bugrtj634/TimingServerImpl.java b/test/regression/src/test/java/org/jacorb/test/bugs/bugrtj634/TimingServerImpl.java index fb51dad98..28da0eb7c 100644 --- a/test/regression/src/test/java/org/jacorb/test/bugs/bugrtj634/TimingServerImpl.java +++ b/test/regression/src/test/java/org/jacorb/test/bugs/bugrtj634/TimingServerImpl.java @@ -1,7 +1,9 @@ package org.jacorb.test.bugs.bugrtj634; +import org.jacorb.test.AnyException; import org.jacorb.test.ComplexTimingServerPOA; import org.jacorb.test.EmptyException; +import org.omg.CORBA.Any; import org.omg.CORBA.NO_IMPLEMENT; import org.omg.CORBA.Object; @@ -30,6 +32,11 @@ public char ex_op(char ch, int delay) throws EmptyException throw new NO_IMPLEMENT(); } + public void any_ex_op(String reason, Any anything, int delay) throws AnyException + { + throw new NO_IMPLEMENT(); + } + public long server_time(int delay) { throw new NO_IMPLEMENT(); diff --git a/test/regression/src/test/java/org/jacorb/test/orb/ExceptionServerImpl.java b/test/regression/src/test/java/org/jacorb/test/orb/ExceptionServerImpl.java index 2dd7f165b..0f8b49d5a 100644 --- a/test/regression/src/test/java/org/jacorb/test/orb/ExceptionServerImpl.java +++ b/test/regression/src/test/java/org/jacorb/test/orb/ExceptionServerImpl.java @@ -1,8 +1,10 @@ package org.jacorb.test.orb; +import org.jacorb.test.AnyException; import org.jacorb.test.ExceptionServerPOA; import org.jacorb.test.MyUserException; import org.jacorb.test.NonEmptyException; +import org.omg.CORBA.Any; public class ExceptionServerImpl extends ExceptionServerPOA { @@ -25,4 +27,10 @@ public void throwUserExceptionWithMessage2(String reason, String message) throws { throw new MyUserException(reason, message); } + + public void throwAnyException(String reason, Any anything) throws AnyException + { + throw new AnyException(reason, anything); + } + } diff --git a/test/regression/src/test/java/org/jacorb/test/orb/ExceptionTest.java b/test/regression/src/test/java/org/jacorb/test/orb/ExceptionTest.java index 343e5227f..018eb5508 100644 --- a/test/regression/src/test/java/org/jacorb/test/orb/ExceptionTest.java +++ b/test/regression/src/test/java/org/jacorb/test/orb/ExceptionTest.java @@ -2,6 +2,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; +import org.jacorb.test.AnyException; import org.jacorb.test.ExceptionServer; import org.jacorb.test.ExceptionServerHelper; import org.jacorb.test.MyUserException; @@ -13,6 +14,7 @@ import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; +import org.omg.CORBA.Any; /** * This class gathers all sorts of exception-related tests. @@ -109,4 +111,23 @@ public void testUserExceptionWithData() assertEquals("sample message", e.message); } } + + @Test + public void testExceptionWithAny() + { + try + { + Any any = setup.getClientOrb().create_any(); + any.insert_long(73); + server.throwAnyException("sample reason", any); + fail("Expected an exception to be thrown"); + } + catch(AnyException e) + { + // expected + assertEquals("sample reason", e.getMessage()); + assertEquals(73, e.anything.extract_long()); + } + } + } diff --git a/test/regression/src/test/java/org/jacorb/test/orb/policies/ComplexTimingServerImpl.java b/test/regression/src/test/java/org/jacorb/test/orb/policies/ComplexTimingServerImpl.java index c86ad8035..d3ac7f6bb 100644 --- a/test/regression/src/test/java/org/jacorb/test/orb/policies/ComplexTimingServerImpl.java +++ b/test/regression/src/test/java/org/jacorb/test/orb/policies/ComplexTimingServerImpl.java @@ -1,7 +1,9 @@ package org.jacorb.test.orb.policies; +import org.jacorb.test.AnyException; import org.jacorb.test.ComplexTimingServerPOA; import org.jacorb.test.EmptyException; +import org.omg.CORBA.Any; public class ComplexTimingServerImpl extends ComplexTimingServerPOA { @@ -43,6 +45,12 @@ else if (ch == '$') } } + public void any_ex_op(String reason, Any anything, int delay) throws AnyException + { + sleep(delay); + throw new AnyException(reason, anything); + } + public long server_time(int delay) { long time = System.currentTimeMillis(); diff --git a/test/regression/src/test/java/org/jacorb/test/orb/policies/ComplexTimingWithPIsTest.java b/test/regression/src/test/java/org/jacorb/test/orb/policies/ComplexTimingWithPIsTest.java index 99ec9cfd6..6dc94e381 100644 --- a/test/regression/src/test/java/org/jacorb/test/orb/policies/ComplexTimingWithPIsTest.java +++ b/test/regression/src/test/java/org/jacorb/test/orb/policies/ComplexTimingWithPIsTest.java @@ -6,6 +6,7 @@ import org.jacorb.test.AMI_ComplexTimingServerHandler; import org.jacorb.test.AMI_ComplexTimingServerHandlerOperations; import org.jacorb.test.AMI_ComplexTimingServerHandlerPOATie; +import org.jacorb.test.AnyException; import org.jacorb.test.ComplexTimingServer; import org.jacorb.test.ComplexTimingServerHelper; import org.jacorb.test.EmptyException; @@ -18,6 +19,7 @@ import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; +import org.omg.CORBA.Any; import org.omg.CORBA.Policy; import org.omg.CORBA.PolicyError; import org.omg.CORBA.SetOverrideType; @@ -87,11 +89,21 @@ public void ex_op_excep (ExceptionHolder excep_holder) wrong_exception ("ex_op_excep", excep_holder); } + public void any_ex_op_excep(ExceptionHolder excep_holder) + { + wrong_exception ("any_ex_op_excep", excep_holder); + } + public void ex_op (char ami_return_val) { wrong_reply ("ex_op"); } + public void any_ex_op() + { + wrong_reply ("any_ex_op"); + } + public void operation_excep (ExceptionHolder excep_holder) { wrong_exception ("operation_excep", excep_holder); @@ -643,6 +655,7 @@ public void test_relative_roundtrip_fwdcall_at_rec_exc_OK() try { server.ex_op ('e', 50); + fail("EmptyException is expected"); } catch (org.omg.CORBA.TIMEOUT t) { @@ -654,6 +667,34 @@ public void test_relative_roundtrip_fwdcall_at_rec_exc_OK() } } + @Test + public void test_relative_roundtrip_fwdcall_at_rec_exc_with_any_OK() + { + server = clearPolicies (server); + server = setRelativeRoundtripTimeout (server, 400); + + ClientInterceptor.forwardCallMade = false; + + TestConfig.setConfig (TestConfig.CALL_AT_REC_EX, + fwdServer); + + try + { + Any any = setup.getClientOrb().create_any(); + any.insert_long(73); + server.any_ex_op ("message", any, 50); + fail("AnyException is expected"); + } + catch (org.omg.CORBA.TIMEOUT t) + { + fail ("FAIL TIMEOUT not expected"); + } + catch (AnyException ee) + { + // OK + } + } + @Test public void test_relative_roundtrip_fwdcall_at_rec_exc_exp() { diff --git a/test/regression/src/test/java/org/jacorb/test/orb/policies/TimingServerImpl.java b/test/regression/src/test/java/org/jacorb/test/orb/policies/TimingServerImpl.java index 02f188145..8421551d0 100644 --- a/test/regression/src/test/java/org/jacorb/test/orb/policies/TimingServerImpl.java +++ b/test/regression/src/test/java/org/jacorb/test/orb/policies/TimingServerImpl.java @@ -1,7 +1,9 @@ package org.jacorb.test.orb.policies; +import org.jacorb.test.AnyException; import org.jacorb.test.EmptyException; import org.jacorb.test.TimingServerPOA; +import org.omg.CORBA.Any; public class TimingServerImpl extends TimingServerPOA { @@ -28,6 +30,12 @@ else if (ch == '$') } } + public void any_ex_op(String reason, Any anything, int delay) throws AnyException + { + sleep(delay); + throw new AnyException(reason, anything); + } + public long server_time(int delay) { long time = System.currentTimeMillis(); diff --git a/test/regression/src/test/java/org/jacorb/test/orb/policies/TimingTest.java b/test/regression/src/test/java/org/jacorb/test/orb/policies/TimingTest.java index 0cea92a2d..a09a55387 100644 --- a/test/regression/src/test/java/org/jacorb/test/orb/policies/TimingTest.java +++ b/test/regression/src/test/java/org/jacorb/test/orb/policies/TimingTest.java @@ -54,11 +54,21 @@ public void ex_op_excep(ExceptionHolder excep_holder) wrong_exception ("ex_op_excep", excep_holder); } + public void any_ex_op_excep(ExceptionHolder excep_holder) + { + wrong_exception ("any_ex_op_excep", excep_holder); + } + public void ex_op(char ami_return_val) { wrong_reply ("ex_op"); } + public void any_ex_op() + { + wrong_reply ("any_ex_op"); + } + public void operation_excep(ExceptionHolder excep_holder) { wrong_exception ("operation_excep", excep_holder);