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 +}