1717 */
1818package org .apache .yoko .orb .OB ;
1919
20+ import org .apache .yoko .io .SimplyCloseable ;
2021import org .apache .yoko .orb .CORBA .YokoInputStream ;
22+ import org .apache .yoko .util .cmsf .Cmsf ;
23+ import org .apache .yoko .util .concurrent .LazyReference ;
24+ import org .apache .yoko .util .rofl .Rofl ;
25+ import org .apache .yoko .util .yasf .Yasf ;
2126import org .omg .CORBA .Any ;
2227import org .omg .CORBA .Context ;
2328import org .omg .CORBA .INTERNAL ;
3035
3136import java .io .Serializable ;
3237import java .math .BigDecimal ;
38+ import java .util .Set ;
3339import java .util .function .Supplier ;
3440
3541import static org .apache .yoko .util .Exceptions .as ;
42+ import static org .apache .yoko .util .ThreadLocalStack .CMSF_THREAD_LOCAL ;
43+ import static org .apache .yoko .util .ThreadLocalStack .ROFL_THREAD_LOCAL ;
44+ import static org .apache .yoko .util .ThreadLocalStack .YASF_THREAD_LOCAL ;
3645
3746/**
3847 * Wrapper for InputStream that intercepts the first read operation to trigger
@@ -46,18 +55,47 @@ final class WrappedReplyInputStream extends InputStream {
4655 private final YokoInputStream yokoStream ;
4756 private final Downcall downcall ;
4857 private boolean readYet ;
58+ private final LazyReference <Supplier <SimplyCloseable >> configFrameRef ;
4959
5060 WrappedReplyInputStream (YokoInputStream yokoStream , Downcall downcall ) {
5161 this .yokoStream = yokoStream ;
5262 this .downcall = downcall ;
63+
64+ // Initialize LazyReference with a function that captures thread local values and returns a Supplier
65+ // The Supplier, when invoked, pushes captured values and returns a composite closer
66+ this .configFrameRef = new LazyReference <>(() -> {
67+ // Capture current thread local values at initialization time
68+ final Set <Yasf > yasf = YASF_THREAD_LOCAL .get ();
69+ final Cmsf cmsf = CMSF_THREAD_LOCAL .get ();
70+ final Rofl rofl = ROFL_THREAD_LOCAL .get ();
71+
72+ // Return a Supplier that pushes the captured values and returns a composite closer
73+ return () -> {
74+ // Push the captured values onto their respective thread local stacks
75+ @ SuppressWarnings ("resource" )
76+ SimplyCloseable ignored0 = YASF_THREAD_LOCAL .push (yasf );
77+ @ SuppressWarnings ("resource" )
78+ SimplyCloseable ignored1 = CMSF_THREAD_LOCAL .push (cmsf );
79+ @ SuppressWarnings ("resource" )
80+ SimplyCloseable ignored2 = ROFL_THREAD_LOCAL .push (rofl );
81+
82+ // Return a composite SimplyCloseable that pops all three in reverse order
83+ return () -> {
84+ ROFL_THREAD_LOCAL .pop ();
85+ CMSF_THREAD_LOCAL .pop ();
86+ YASF_THREAD_LOCAL .pop ();
87+ };
88+ };
89+ });
5390 }
5491
5592 /**
5693 * Wraps a read operation with first-read interception logic.
5794 * Handles both value-returning and void operations uniformly.
95+ * Establishes thread local frame before unmarshalling.
5896 */
5997 private <T > T wrapRead (Supplier <T > readOp ) {
60- try {
98+ try ( SimplyCloseable ignored = configFrameRef . get (). get ()) {
6199 T result = readOp .get ();
62100 triggerInterceptorsOnFirstRead ();
63101 return result ;
@@ -68,9 +106,10 @@ private <T> T wrapRead(Supplier<T> readOp) {
68106
69107 /**
70108 * Wraps a void read operation (array reads) with first-read interception logic.
109+ * Establishes thread local frame before unmarshalling.
71110 */
72111 private void wrapVoidRead (Runnable readOp ) {
73- try {
112+ try ( SimplyCloseable ignored = configFrameRef . get (). get ()) {
74113 readOp .run ();
75114 triggerInterceptorsOnFirstRead ();
76115 } catch (SystemException ex ) {
@@ -81,6 +120,11 @@ private void wrapVoidRead(Runnable readOp) {
81120 /**
82121 * Called before the first read operation returns to trigger interceptors.
83122 * Subsequent reads bypass this check.
123+ * <p>
124+ * <em>Note: this approach may be insufficient in the edge case of an IDL-defined
125+ * interface with out or inout parameters in addition to the return value,
126+ * but only if those subsequent values are unmarshalled differently according to context
127+ * (e.g. YASF, CMSF, or ROFL).</em>
84128 */
85129 private void triggerInterceptorsOnFirstRead () throws SystemException {
86130 if (readYet ) return ;
@@ -98,11 +142,12 @@ private void triggerInterceptorsOnFirstRead() throws SystemException {
98142 /**
99143 * Handles SystemException during first read by reporting to interceptors
100144 * via receive_exception before propagating the exception.
145+ * Establishes thread local frame before unmarshalling exception.
101146 */
102147 private <T > T handleFirstReadException (SystemException ex ) throws SystemException {
103148 if (readYet ) throw ex ;
104149 readYet = true ;
105- try {
150+ try ( SimplyCloseable ignored = configFrameRef . get (). get ()) {
106151 downcall .unmarshalEx (ex );
107152 downcall .postUnmarshal ();
108153 throw ex ;
0 commit comments