Defer unmarshalling UnknownExceptionInfo data
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OB/Downcall.java b/yoko-core/src/main/java/org/apache/yoko/orb/OB/Downcall.java
index 68b0832..5ae2c2c 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OB/Downcall.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OB/Downcall.java
@@ -591,6 +591,7 @@
} catch (InterruptedException ex) {
}
}
+ if (ex_ instanceof UnresolvedException) ex_ = ((UnresolvedException)ex_).resolve();
//
// The downcall has completed
//
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OB/GIOPConnection.java b/yoko-core/src/main/java/org/apache/yoko/orb/OB/GIOPConnection.java
index 966fed1..2280516 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OB/GIOPConnection.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OB/GIOPConnection.java
@@ -630,38 +630,7 @@
if (ex instanceof UNKNOWN) {
for (ServiceContext sc : scl) {
if (sc.context_id == UnknownExceptionInfo.value) {
- final byte[] data = sc.context_data;
- Buffer buf = new Buffer(data, data.length);
- try (org.apache.yoko.orb.CORBA.InputStream in =
- new org.apache.yoko.orb.CORBA.InputStream(buf, 0, false, is._OB_codeConverters(), GIOP1_2)) {
- try {
- in.__setSendingContextRuntime(is.__getSendingContextRuntime());
- in.__setCodeBase(is.__getCodeBase());
- in._OB_readEndian();
- Throwable t = (Throwable) in.read_value();
- UnknownException x = new UnknownException(t);
- x.completed = ex.completed;
- x.minor = ex.minor;
- return x;
- } catch (Exception e) {
- final String dump = in.dumpData();
- final int curPos = in.buf_.pos();
- in.buf_.pos(0);
- final String fullDump = in.dumpData();
- in.buf_.pos(curPos);
- try (StringWriter sw = new StringWriter();
- PrintWriter pw = new PrintWriter(sw)) {
- e.printStackTrace(pw);
- logger.severe(String.format("%s:%n%s:%n%s%n%s:%n%s%n%s:%n%s",
- "Exception reading UnknownExceptionInfo service context",
- "Remaining data", dump, "Full data", fullDump,
- "Exception thrown", sw.toString()));
- }
- }
- } catch (IOException e) {
- //ignore IOException from AutoCloseable.close()
- }
- break;
+ return new UnresolvedException((UNKNOWN) ex, sc.context_data, is);
}
}
}
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OB/GIOPConnectionThreaded.java b/yoko-core/src/main/java/org/apache/yoko/orb/OB/GIOPConnectionThreaded.java
index bc250df..c6d6c2e 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OB/GIOPConnectionThreaded.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OB/GIOPConnectionThreaded.java
@@ -378,7 +378,7 @@
//
try {
inMsg.extractHeader(buf);
- logger.fine("Header received for message of size " + inMsg.size());
+ logger.fine("Header received for message of size " + inMsg.size());
buf.realloc(12 + inMsg.size());
} catch (org.omg.CORBA.SystemException ex) {
processException(State.Error, ex, false);
@@ -718,7 +718,7 @@
//
try {
boolean result = down.waitUntilCompleted(block);
- logger.fine("Completed eceiving response with Downcall of type " + down.getClass().getName());
+ logger.fine("Completed receiving response with Downcall of type " + down.getClass().getName());
return result;
} catch (org.omg.CORBA.SystemException ex) {
processException(State.Closed, ex, false);
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OB/UnresolvedException.java b/yoko-core/src/main/java/org/apache/yoko/orb/OB/UnresolvedException.java
new file mode 100644
index 0000000..8d0aaf5
--- /dev/null
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OB/UnresolvedException.java
@@ -0,0 +1,82 @@
+package org.apache.yoko.orb.OB;
+
+import static org.apache.yoko.orb.OCI.GiopVersion.GIOP1_2;
+
+import java.io.IOException;
+import java.io.NotSerializableException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.yoko.orb.CORBA.InputStream;
+import org.apache.yoko.orb.OCI.Buffer;
+import org.omg.CORBA.SystemException;
+import org.omg.CORBA.UNKNOWN;
+import org.omg.CORBA.portable.UnknownException;
+import org.omg.SendingContext.CodeBase;
+
+public class UnresolvedException extends UnknownException {
+ private static final Logger LOGGER = Logger.getLogger(UnresolvedException.class.getName());
+ private final UNKNOWN ex;
+ private final byte[] data;
+ private final CodeConverters converters;
+ private final CodeBase sendingContextRuntime;
+ private final String codebase;
+
+ UnresolvedException(UNKNOWN ex, byte[] data, InputStream is) {
+ super(ex);
+ super.completed = ex.completed;
+ super.minor = ex.minor;
+ this.ex = ex;
+ this.data = data;
+ this.converters = is._OB_codeConverters();
+ this.sendingContextRuntime = is.__getSendingContextRuntime();
+ this.codebase = is.__getCodeBase();
+ }
+
+ public SystemException resolve() {
+ Buffer buf = new Buffer(data, data.length);
+ try (org.apache.yoko.orb.CORBA.InputStream in =
+ new org.apache.yoko.orb.CORBA.InputStream(buf, 0, false, converters, GIOP1_2)) {
+ if (LOGGER.isLoggable(Level.FINE))
+ LOGGER.fine(String.format("Unpacking Unknown Exception Info%n%s", in.dumpData()));
+ try {
+ in.__setSendingContextRuntime(sendingContextRuntime);
+ in.__setCodeBase(codebase);
+ in._OB_readEndian();
+ Throwable t = (Throwable) in.read_value();
+ UnknownException x = new UnknownException(t);
+ x.completed = ex.completed;
+ x.minor = ex.minor;
+ return x;
+ } catch (Exception e) {
+ final String dump = in.dumpData();
+ final int curPos = in.buf_.pos();
+ in.buf_.pos(0);
+ final String fullDump = in.dumpData();
+ in.buf_.pos(curPos);
+ try (StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw)) {
+ e.printStackTrace(pw);
+ LOGGER.severe(String.format("%s:%n%s:%n%s%n%s:%n%s%n%s:%n%s",
+ "Exception reading UnknownExceptionInfo service context",
+ "Remaining data", dump, "Full data", fullDump,
+ "Exception thrown", sw.toString()));
+ }
+ }
+ } catch (IOException e) {
+ //ignore IOException from AutoCloseable.close()
+ }
+ return ex;
+ }
+
+ private void readObject(ObjectInputStream ois) throws IOException {
+ throw new NotSerializableException();
+ }
+ private void writeObject(ObjectOutputStream oos) throws IOException {
+ throw new NotSerializableException();
+ }
+}
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/util/AutoLock.java b/yoko-core/src/main/java/org/apache/yoko/orb/util/AutoLock.java
index c9dea93..c2dbf5d 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/util/AutoLock.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/util/AutoLock.java
@@ -4,21 +4,48 @@
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
-public class AutoLock implements AutoCloseable{
+public class AutoLock implements AutoCloseable {
final AtomicReference<Lock> lockRef;
-
+ final Lock downgradeLock;
+ final int downgradeHeld;
+
AutoLock(Lock lock) {
+ this(lock, null, 0);
+ }
+
+ AutoLock(Lock lock, Lock downgradeLock, int downgradeHeld) {
lockRef = new AtomicReference<>(lock);
+ this.downgradeLock = downgradeLock;
+ this.downgradeHeld = downgradeHeld;
+ for (int i = downgradeHeld; i > 0; i--) {
+ downgradeLock.unlock();
+ }
lock.lock();
}
-
+
@Override
public void close() {
Lock lock = lockRef.getAndSet(null);
- if (lock != null) lock.unlock();
+ if (lock == null)
+ return;
+ for (int i = 0; i < downgradeHeld; i++) {
+ downgradeLock.lock();
+ }
+ lock.unlock();
}
public Condition newCondition() {
return lockRef.get().newCondition();
}
-}
\ No newline at end of file
+
+ public boolean downgrade() {
+ if (downgradeLock == null)
+ return false;
+ Lock oldLock = lockRef.getAndSet(downgradeLock);
+ if (oldLock == downgradeLock)
+ return false;
+ downgradeLock.lock();
+ oldLock.unlock();
+ return true;
+ }
+}
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/util/AutoReadWriteLock.java b/yoko-core/src/main/java/org/apache/yoko/orb/util/AutoReadWriteLock.java
index f70c0a3..f9b47d0 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/util/AutoReadWriteLock.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/util/AutoReadWriteLock.java
@@ -1,16 +1,15 @@
package org.apache.yoko.orb.util;
-import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class AutoReadWriteLock {
- private final ReadWriteLock lock = new ReentrantReadWriteLock();
+ private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
public AutoLock getReadLock() {
return new AutoLock(lock.readLock());
}
public AutoLock getWriteLock() {
- return new AutoLock(lock.writeLock());
+ return new AutoLock(lock.writeLock(), lock.readLock(), lock.getReadHoldCount());
}
-}
\ No newline at end of file
+}