4
|
1 |
/*
|
5555
|
2 |
* Copyright (c) 1997, 2004, Oracle and/or its affiliates. All rights reserved.
|
4
|
3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
4 |
*
|
|
5 |
* This code is free software; you can redistribute it and/or modify it
|
|
6 |
* under the terms of the GNU General Public License version 2 only, as
|
5555
|
7 |
* published by the Free Software Foundation. Oracle designates this
|
4
|
8 |
* particular file as subject to the "Classpath" exception as provided
|
5555
|
9 |
* by Oracle in the LICENSE file that accompanied this code.
|
4
|
10 |
*
|
|
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that
|
|
15 |
* accompanied this code).
|
|
16 |
*
|
|
17 |
* You should have received a copy of the GNU General Public License version
|
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
20 |
*
|
5555
|
21 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
22 |
* or visit www.oracle.com if you need additional information or have any
|
|
23 |
* questions.
|
4
|
24 |
*/
|
|
25 |
|
|
26 |
/*
|
|
27 |
* Licensed Materials - Property of IBM
|
|
28 |
* RMI-IIOP v1.0
|
|
29 |
* Copyright IBM Corp. 1998 1999 All Rights Reserved
|
|
30 |
*
|
|
31 |
*/
|
|
32 |
|
|
33 |
package com.sun.corba.se.impl.encoding;
|
|
34 |
|
|
35 |
import java.io.IOException;
|
|
36 |
import java.io.Serializable;
|
|
37 |
import java.io.ByteArrayInputStream;
|
|
38 |
import java.io.ObjectInputStream;
|
|
39 |
import java.io.IOException;
|
|
40 |
import java.io.StreamCorruptedException;
|
|
41 |
import java.io.OptionalDataException;
|
|
42 |
import java.io.IOException;
|
|
43 |
|
|
44 |
import java.util.Stack;
|
|
45 |
|
|
46 |
import java.net.URL;
|
|
47 |
import java.net.MalformedURLException;
|
|
48 |
|
|
49 |
import java.nio.ByteBuffer;
|
|
50 |
|
|
51 |
import java.lang.reflect.InvocationTargetException;
|
|
52 |
import java.lang.reflect.Method;
|
|
53 |
|
|
54 |
import java.math.BigDecimal;
|
|
55 |
|
|
56 |
import java.rmi.Remote;
|
|
57 |
import java.rmi.StubNotFoundException;
|
|
58 |
|
|
59 |
import java.security.AccessController;
|
|
60 |
import java.security.PrivilegedExceptionAction;
|
|
61 |
import java.security.PrivilegedActionException;
|
|
62 |
|
|
63 |
import org.omg.CORBA.SystemException;
|
|
64 |
import org.omg.CORBA.Object;
|
|
65 |
import org.omg.CORBA.Principal;
|
|
66 |
import org.omg.CORBA.TypeCode;
|
|
67 |
import org.omg.CORBA.Any;
|
|
68 |
import org.omg.CORBA.portable.Delegate;
|
|
69 |
import org.omg.CORBA.portable.ValueBase;
|
|
70 |
import org.omg.CORBA.portable.IndirectionException;
|
|
71 |
import org.omg.CORBA.CompletionStatus;
|
|
72 |
import org.omg.CORBA.TCKind;
|
|
73 |
import org.omg.CORBA.TypeCodePackage.BadKind;
|
|
74 |
import org.omg.CORBA.CustomMarshal;
|
|
75 |
import org.omg.CORBA.TypeCode;
|
|
76 |
import org.omg.CORBA.Principal;
|
|
77 |
import org.omg.CORBA.Any;
|
|
78 |
import org.omg.CORBA.portable.BoxedValueHelper;
|
|
79 |
import org.omg.CORBA.portable.ValueFactory;
|
|
80 |
import org.omg.CORBA.portable.CustomValue;
|
|
81 |
import org.omg.CORBA.portable.StreamableValue;
|
|
82 |
import org.omg.CORBA.MARSHAL;
|
|
83 |
import org.omg.CORBA.portable.IDLEntity;
|
|
84 |
|
|
85 |
import javax.rmi.PortableRemoteObject;
|
|
86 |
import javax.rmi.CORBA.Tie;
|
|
87 |
import javax.rmi.CORBA.Util;
|
|
88 |
import javax.rmi.CORBA.ValueHandler;
|
|
89 |
|
|
90 |
import com.sun.corba.se.pept.protocol.MessageMediator;
|
|
91 |
import com.sun.corba.se.pept.transport.ByteBufferPool;
|
|
92 |
|
|
93 |
import com.sun.corba.se.spi.protocol.RequestDispatcherRegistry;
|
|
94 |
import com.sun.corba.se.spi.protocol.CorbaClientDelegate;
|
|
95 |
|
|
96 |
import com.sun.corba.se.spi.ior.IOR;
|
|
97 |
import com.sun.corba.se.spi.ior.IORFactories;
|
|
98 |
import com.sun.corba.se.spi.ior.iiop.GIOPVersion;
|
|
99 |
|
|
100 |
import com.sun.corba.se.spi.orb.ORB;
|
|
101 |
import com.sun.corba.se.spi.orb.ORBVersionFactory;
|
|
102 |
import com.sun.corba.se.spi.orb.ORBVersion;
|
|
103 |
|
|
104 |
import com.sun.corba.se.spi.protocol.CorbaMessageMediator;
|
|
105 |
|
|
106 |
import com.sun.corba.se.spi.logging.CORBALogDomains;
|
|
107 |
import com.sun.corba.se.spi.presentation.rmi.PresentationManager;
|
|
108 |
import com.sun.corba.se.spi.presentation.rmi.StubAdapter;
|
|
109 |
import com.sun.corba.se.spi.presentation.rmi.PresentationDefaults;
|
|
110 |
|
|
111 |
import com.sun.corba.se.impl.logging.ORBUtilSystemException;
|
|
112 |
import com.sun.corba.se.impl.logging.OMGSystemException;
|
|
113 |
|
|
114 |
import com.sun.corba.se.impl.corba.PrincipalImpl;
|
|
115 |
import com.sun.corba.se.impl.corba.TypeCodeImpl;
|
|
116 |
import com.sun.corba.se.impl.corba.CORBAObjectImpl;
|
|
117 |
|
|
118 |
import com.sun.corba.se.impl.encoding.CDROutputObject;
|
|
119 |
import com.sun.corba.se.impl.encoding.CodeSetConversion;
|
|
120 |
|
|
121 |
import com.sun.corba.se.impl.util.Utility;
|
|
122 |
import com.sun.corba.se.impl.util.RepositoryId;
|
|
123 |
|
|
124 |
import com.sun.corba.se.impl.orbutil.RepositoryIdStrings;
|
|
125 |
import com.sun.corba.se.impl.orbutil.RepositoryIdInterface;
|
|
126 |
import com.sun.corba.se.impl.orbutil.RepositoryIdUtility;
|
|
127 |
import com.sun.corba.se.impl.orbutil.RepositoryIdFactory;
|
|
128 |
|
|
129 |
import com.sun.corba.se.impl.orbutil.ORBUtility;
|
|
130 |
import com.sun.corba.se.impl.orbutil.CacheTable;
|
|
131 |
|
|
132 |
|
|
133 |
import com.sun.org.omg.CORBA.portable.ValueHelper;
|
|
134 |
|
|
135 |
import com.sun.org.omg.SendingContext.CodeBase;
|
|
136 |
|
|
137 |
public class CDRInputStream_1_0 extends CDRInputStreamBase
|
|
138 |
implements RestorableInputStream
|
|
139 |
{
|
|
140 |
private static final String kReadMethod = "read";
|
|
141 |
private static final int maxBlockLength = 0x7fffff00;
|
|
142 |
|
|
143 |
protected BufferManagerRead bufferManagerRead;
|
|
144 |
protected ByteBufferWithInfo bbwi;
|
|
145 |
|
|
146 |
// Set to the ORB's transportDebugFlag value. This value is
|
|
147 |
// used if the ORB is null.
|
|
148 |
private boolean debug = false;
|
|
149 |
|
|
150 |
protected boolean littleEndian;
|
|
151 |
protected ORB orb;
|
|
152 |
protected ORBUtilSystemException wrapper ;
|
|
153 |
protected OMGSystemException omgWrapper ;
|
|
154 |
protected ValueHandler valueHandler = null;
|
|
155 |
|
|
156 |
// Value cache
|
|
157 |
private CacheTable valueCache = null;
|
|
158 |
|
|
159 |
// Repository ID cache
|
|
160 |
private CacheTable repositoryIdCache = null;
|
|
161 |
|
|
162 |
// codebase cache
|
|
163 |
private CacheTable codebaseCache = null;
|
|
164 |
|
|
165 |
// Current Class Stack (repository Ids of current class being read)
|
|
166 |
// private Stack currentStack = null;
|
|
167 |
|
|
168 |
// Length of current chunk, or a large positive number if not in a chunk
|
|
169 |
protected int blockLength = maxBlockLength;
|
|
170 |
|
|
171 |
// Read end flag (value nesting depth)
|
|
172 |
protected int end_flag = 0;
|
|
173 |
|
|
174 |
// Beginning with the resolution to interop issue 3526 (4328?),
|
|
175 |
// only enclosing chunked valuetypes are taken into account
|
|
176 |
// when computing the nesting level. However, we still need
|
|
177 |
// the old computation around for interoperability with our
|
|
178 |
// older ORBs.
|
|
179 |
private int chunkedValueNestingLevel = 0;
|
|
180 |
|
|
181 |
// Flag used to determine whether blocksize was zero
|
|
182 |
// private int checkForNullBlock = -1;
|
|
183 |
|
|
184 |
// In block flag
|
|
185 |
// private boolean inBlock = false;
|
|
186 |
|
|
187 |
// Indicates whether we are inside a value
|
|
188 |
// private boolean outerValueDone = true;
|
|
189 |
|
|
190 |
// Int used by read_value(Serializable) that is set by this class
|
|
191 |
// before calling ValueFactory.read_value
|
|
192 |
protected int valueIndirection = 0;
|
|
193 |
|
|
194 |
// Int set by readStringOrIndirection to communicate the actual
|
|
195 |
// offset of the string length field back to the caller
|
|
196 |
protected int stringIndirection = 0;
|
|
197 |
|
|
198 |
// Flag indicating whether we are unmarshalling a chunked value
|
|
199 |
protected boolean isChunked = false;
|
|
200 |
|
|
201 |
// Repository ID handlers
|
|
202 |
private RepositoryIdUtility repIdUtil;
|
|
203 |
private RepositoryIdStrings repIdStrs;
|
|
204 |
|
|
205 |
// Code set converters (created when first needed)
|
|
206 |
private CodeSetConversion.BTCConverter charConverter;
|
|
207 |
private CodeSetConversion.BTCConverter wcharConverter;
|
|
208 |
|
|
209 |
// RMI-IIOP stream format version 2 case in which we know
|
|
210 |
// that there is no more optional data available. If the
|
|
211 |
// Serializable's readObject method tries to read anything,
|
|
212 |
// we must throw a MARSHAL with the special minor code
|
|
213 |
// so that the ValueHandler can give the correct exception
|
|
214 |
// to readObject. The state is cleared when the ValueHandler
|
|
215 |
// calls end_value after the readObject method exits.
|
|
216 |
private boolean specialNoOptionalDataState = false;
|
|
217 |
|
|
218 |
// Template method
|
|
219 |
public CDRInputStreamBase dup()
|
|
220 |
{
|
|
221 |
CDRInputStreamBase result = null ;
|
|
222 |
|
|
223 |
try {
|
|
224 |
result = (CDRInputStreamBase)this.getClass().newInstance();
|
|
225 |
} catch (Exception e) {
|
|
226 |
throw wrapper.couldNotDuplicateCdrInputStream( e ) ;
|
|
227 |
}
|
|
228 |
result.init(this.orb,
|
|
229 |
this.bbwi.byteBuffer,
|
|
230 |
this.bbwi.buflen,
|
|
231 |
this.littleEndian,
|
|
232 |
this.bufferManagerRead);
|
|
233 |
|
|
234 |
((CDRInputStream_1_0)result).bbwi.position(this.bbwi.position());
|
|
235 |
// To ensure we keep bbwi.byteBuffer.limit in sync with bbwi.buflen.
|
|
236 |
((CDRInputStream_1_0)result).bbwi.byteBuffer.limit(this.bbwi.buflen);
|
|
237 |
|
|
238 |
return result;
|
|
239 |
}
|
|
240 |
|
|
241 |
/**
|
|
242 |
* NOTE: size passed to init means buffer size
|
|
243 |
*/
|
|
244 |
public void init(org.omg.CORBA.ORB orb,
|
|
245 |
ByteBuffer byteBuffer,
|
|
246 |
int size,
|
|
247 |
boolean littleEndian,
|
|
248 |
BufferManagerRead bufferManager)
|
|
249 |
{
|
|
250 |
this.orb = (ORB)orb;
|
|
251 |
this.wrapper = ORBUtilSystemException.get( (ORB)orb,
|
|
252 |
CORBALogDomains.RPC_ENCODING ) ;
|
|
253 |
this.omgWrapper = OMGSystemException.get( (ORB)orb,
|
|
254 |
CORBALogDomains.RPC_ENCODING ) ;
|
|
255 |
this.littleEndian = littleEndian;
|
|
256 |
this.bufferManagerRead = bufferManager;
|
|
257 |
this.bbwi = new ByteBufferWithInfo(orb,byteBuffer,0);
|
|
258 |
this.bbwi.buflen = size;
|
|
259 |
this.bbwi.byteBuffer.limit(bbwi.buflen);
|
|
260 |
this.markAndResetHandler = bufferManagerRead.getMarkAndResetHandler();
|
|
261 |
|
|
262 |
debug = ((ORB)orb).transportDebugFlag;
|
|
263 |
}
|
|
264 |
|
|
265 |
// See description in CDRInputStream
|
|
266 |
void performORBVersionSpecificInit() {
|
|
267 |
createRepositoryIdHandlers();
|
|
268 |
}
|
|
269 |
|
|
270 |
private final void createRepositoryIdHandlers()
|
|
271 |
{
|
|
272 |
repIdUtil = RepositoryIdFactory.getRepIdUtility(orb);
|
|
273 |
repIdStrs = RepositoryIdFactory.getRepIdStringsFactory(orb);
|
|
274 |
}
|
|
275 |
|
|
276 |
public GIOPVersion getGIOPVersion() {
|
|
277 |
return GIOPVersion.V1_0;
|
|
278 |
}
|
|
279 |
|
|
280 |
// Called by Request and Reply message. Valid for GIOP versions >= 1.2 only.
|
|
281 |
// Illegal for GIOP versions < 1.2.
|
|
282 |
void setHeaderPadding(boolean headerPadding) {
|
|
283 |
throw wrapper.giopVersionError();
|
|
284 |
}
|
|
285 |
|
|
286 |
protected final int computeAlignment(int index, int align) {
|
|
287 |
if (align > 1) {
|
|
288 |
int incr = index & (align - 1);
|
|
289 |
if (incr != 0)
|
|
290 |
return align - incr;
|
|
291 |
}
|
|
292 |
|
|
293 |
return 0;
|
|
294 |
}
|
|
295 |
|
|
296 |
public int getSize()
|
|
297 |
{
|
|
298 |
return bbwi.position();
|
|
299 |
}
|
|
300 |
|
|
301 |
protected void checkBlockLength(int align, int dataSize) {
|
|
302 |
// Since chunks can end at arbitrary points (though not within
|
|
303 |
// primitive CDR types, arrays of primitives, strings, wstrings,
|
|
304 |
// or indirections),
|
|
305 |
// we must check here for termination of the current chunk.
|
|
306 |
if (!isChunked)
|
|
307 |
return;
|
|
308 |
|
|
309 |
// RMI-IIOP stream format version 2 case in which we know
|
|
310 |
// that there is no more optional data available. If the
|
|
311 |
// Serializable's readObject method tries to read anything,
|
|
312 |
// we must throw a MARSHAL exception with the special minor code
|
|
313 |
// so that the ValueHandler can give the correct exception
|
|
314 |
// to readObject. The state is cleared when the ValueHandler
|
|
315 |
// calls end_value after the readObject method exits.
|
|
316 |
if (specialNoOptionalDataState) {
|
|
317 |
throw omgWrapper.rmiiiopOptionalDataIncompatible1() ;
|
|
318 |
}
|
|
319 |
|
|
320 |
boolean checkForEndTag = false;
|
|
321 |
|
|
322 |
// Are we at the end of the current chunk? If so,
|
|
323 |
// try to interpret the next long as a chunk length.
|
|
324 |
// (It has to be either a chunk length, end tag,
|
|
325 |
// or valuetag.)
|
|
326 |
//
|
|
327 |
// If it isn't a chunk length, blockLength will
|
|
328 |
// remain set to maxBlockLength.
|
|
329 |
if (blockLength == get_offset()) {
|
|
330 |
|
|
331 |
blockLength = maxBlockLength;
|
|
332 |
start_block();
|
|
333 |
|
|
334 |
// What's next is either a valuetag or
|
|
335 |
// an end tag. If it's a valuetag, we're
|
|
336 |
// probably being called as part of the process
|
|
337 |
// to read the valuetag. If it's an end tag,
|
|
338 |
// then there isn't enough data left in
|
|
339 |
// this valuetype to read!
|
|
340 |
if (blockLength == maxBlockLength)
|
|
341 |
checkForEndTag = true;
|
|
342 |
|
|
343 |
} else
|
|
344 |
if (blockLength < get_offset()) {
|
|
345 |
// Are we already past the end of the current chunk?
|
|
346 |
// This is always an error.
|
|
347 |
throw wrapper.chunkOverflow() ;
|
|
348 |
}
|
|
349 |
|
|
350 |
// If what's next on the wire isn't a chunk length or
|
|
351 |
// what we want to read (which can't be split across chunks)
|
|
352 |
// won't fit in the current chunk, throw this exception.
|
|
353 |
// This probably means that we're in an RMI-IIOP
|
|
354 |
// Serializable's readObject method or a custom marshaled
|
|
355 |
// IDL type is reading too much/in an incorrect order
|
|
356 |
int requiredNumBytes =
|
|
357 |
computeAlignment(bbwi.position(), align) + dataSize;
|
|
358 |
|
|
359 |
if (blockLength != maxBlockLength &&
|
|
360 |
blockLength < get_offset() + requiredNumBytes) {
|
|
361 |
throw omgWrapper.rmiiiopOptionalDataIncompatible2() ;
|
|
362 |
}
|
|
363 |
|
|
364 |
// REVISIT - We should look at using the built in advancement
|
|
365 |
// of using ByteBuffer.get() rather than explicitly
|
|
366 |
// advancing the ByteBuffer's position.
|
|
367 |
// This is true for anywhere we are incrementing
|
|
368 |
// the ByteBuffer's position.
|
|
369 |
if (checkForEndTag) {
|
|
370 |
int nextLong = read_long();
|
|
371 |
bbwi.position(bbwi.position() - 4);
|
|
372 |
|
|
373 |
// It was an end tag, so there wasn't enough data
|
|
374 |
// left in the valuetype's encoding on the wire
|
|
375 |
// to read what we wanted
|
|
376 |
if (nextLong < 0)
|
|
377 |
throw omgWrapper.rmiiiopOptionalDataIncompatible3() ;
|
|
378 |
}
|
|
379 |
}
|
|
380 |
|
|
381 |
protected void alignAndCheck(int align, int n) {
|
|
382 |
|
|
383 |
checkBlockLength(align, n);
|
|
384 |
|
|
385 |
// WARNING: Must compute real alignment after calling
|
|
386 |
// checkBlockLength since it may move the position
|
|
387 |
int alignResult = computeAlignment(bbwi.position(), align);
|
|
388 |
bbwi.position(bbwi.position() + alignResult);
|
|
389 |
|
|
390 |
if (bbwi.position() + n > bbwi.buflen)
|
|
391 |
grow(align, n);
|
|
392 |
}
|
|
393 |
|
|
394 |
//
|
|
395 |
// This can be overridden....
|
|
396 |
//
|
|
397 |
protected void grow(int align, int n) {
|
|
398 |
|
|
399 |
bbwi.needed = n;
|
|
400 |
|
|
401 |
bbwi = bufferManagerRead.underflow(bbwi);
|
|
402 |
|
|
403 |
}
|
|
404 |
|
|
405 |
//
|
|
406 |
// Marshal primitives.
|
|
407 |
//
|
|
408 |
|
|
409 |
public final void consumeEndian() {
|
|
410 |
littleEndian = read_boolean();
|
|
411 |
}
|
|
412 |
|
|
413 |
// No such type in java
|
|
414 |
public final double read_longdouble() {
|
|
415 |
throw wrapper.longDoubleNotImplemented( CompletionStatus.COMPLETED_MAYBE);
|
|
416 |
}
|
|
417 |
|
|
418 |
public final boolean read_boolean() {
|
|
419 |
return (read_octet() != 0);
|
|
420 |
}
|
|
421 |
|
|
422 |
public final char read_char() {
|
|
423 |
alignAndCheck(1, 1);
|
|
424 |
|
|
425 |
return getConvertedChars(1, getCharConverter())[0];
|
|
426 |
}
|
|
427 |
|
|
428 |
public char read_wchar() {
|
|
429 |
|
|
430 |
// Don't allow transmission of wchar/wstring data with
|
|
431 |
// foreign ORBs since it's against the spec.
|
|
432 |
if (ORBUtility.isForeignORB((ORB)orb)) {
|
|
433 |
throw wrapper.wcharDataInGiop10( CompletionStatus.COMPLETED_MAYBE);
|
|
434 |
}
|
|
435 |
|
|
436 |
// If we're talking to one of our legacy ORBs, do what
|
|
437 |
// they did:
|
|
438 |
int b1, b2;
|
|
439 |
|
|
440 |
alignAndCheck(2, 2);
|
|
441 |
|
|
442 |
if (littleEndian) {
|
|
443 |
b2 = bbwi.byteBuffer.get(bbwi.position()) & 0x00FF;
|
|
444 |
bbwi.position(bbwi.position() + 1);
|
|
445 |
b1 = bbwi.byteBuffer.get(bbwi.position()) & 0x00FF;
|
|
446 |
bbwi.position(bbwi.position() + 1);
|
|
447 |
} else {
|
|
448 |
b1 = bbwi.byteBuffer.get(bbwi.position()) & 0x00FF;
|
|
449 |
bbwi.position(bbwi.position() + 1);
|
|
450 |
b2 = bbwi.byteBuffer.get(bbwi.position()) & 0x00FF;
|
|
451 |
bbwi.position(bbwi.position() + 1);
|
|
452 |
}
|
|
453 |
|
|
454 |
return (char)((b1 << 8) + (b2 << 0));
|
|
455 |
}
|
|
456 |
|
|
457 |
public final byte read_octet() {
|
|
458 |
|
|
459 |
alignAndCheck(1, 1);
|
|
460 |
|
|
461 |
byte b = bbwi.byteBuffer.get(bbwi.position());
|
|
462 |
bbwi.position(bbwi.position() + 1);
|
|
463 |
|
|
464 |
return b;
|
|
465 |
}
|
|
466 |
|
|
467 |
public final short read_short() {
|
|
468 |
int b1, b2;
|
|
469 |
|
|
470 |
alignAndCheck(2, 2);
|
|
471 |
|
|
472 |
if (littleEndian) {
|
|
473 |
b2 = (bbwi.byteBuffer.get(bbwi.position()) << 0) & 0x000000FF;
|
|
474 |
bbwi.position(bbwi.position() + 1);
|
|
475 |
b1 = (bbwi.byteBuffer.get(bbwi.position()) << 8) & 0x0000FF00;
|
|
476 |
bbwi.position(bbwi.position() + 1);
|
|
477 |
} else {
|
|
478 |
b1 = (bbwi.byteBuffer.get(bbwi.position()) << 8) & 0x0000FF00;
|
|
479 |
bbwi.position(bbwi.position() + 1);
|
|
480 |
b2 = (bbwi.byteBuffer.get(bbwi.position()) << 0) & 0x000000FF;
|
|
481 |
bbwi.position(bbwi.position() + 1);
|
|
482 |
}
|
|
483 |
|
|
484 |
return (short)(b1 | b2);
|
|
485 |
}
|
|
486 |
|
|
487 |
public final short read_ushort() {
|
|
488 |
return read_short();
|
|
489 |
}
|
|
490 |
|
|
491 |
public final int read_long() {
|
|
492 |
int b1, b2, b3, b4;
|
|
493 |
|
|
494 |
alignAndCheck(4, 4);
|
|
495 |
|
|
496 |
int bufPos = bbwi.position();
|
|
497 |
if (littleEndian) {
|
|
498 |
b4 = bbwi.byteBuffer.get(bufPos++) & 0xFF;
|
|
499 |
b3 = bbwi.byteBuffer.get(bufPos++) & 0xFF;
|
|
500 |
b2 = bbwi.byteBuffer.get(bufPos++) & 0xFF;
|
|
501 |
b1 = bbwi.byteBuffer.get(bufPos++) & 0xFF;
|
|
502 |
} else {
|
|
503 |
b1 = bbwi.byteBuffer.get(bufPos++) & 0xFF;
|
|
504 |
b2 = bbwi.byteBuffer.get(bufPos++) & 0xFF;
|
|
505 |
b3 = bbwi.byteBuffer.get(bufPos++) & 0xFF;
|
|
506 |
b4 = bbwi.byteBuffer.get(bufPos++) & 0xFF;
|
|
507 |
}
|
|
508 |
bbwi.position(bufPos);
|
|
509 |
|
|
510 |
return (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
|
|
511 |
}
|
|
512 |
|
|
513 |
public final int read_ulong() {
|
|
514 |
return read_long();
|
|
515 |
}
|
|
516 |
|
|
517 |
public final long read_longlong() {
|
|
518 |
long i1, i2;
|
|
519 |
|
|
520 |
alignAndCheck(8, 8);
|
|
521 |
|
|
522 |
if (littleEndian) {
|
|
523 |
i2 = read_long() & 0xFFFFFFFFL;
|
|
524 |
i1 = (long)read_long() << 32;
|
|
525 |
} else {
|
|
526 |
i1 = (long)read_long() << 32;
|
|
527 |
i2 = read_long() & 0xFFFFFFFFL;
|
|
528 |
}
|
|
529 |
|
|
530 |
return (i1 | i2);
|
|
531 |
}
|
|
532 |
|
|
533 |
public final long read_ulonglong() {
|
|
534 |
return read_longlong();
|
|
535 |
}
|
|
536 |
|
|
537 |
public final float read_float() {
|
|
538 |
return Float.intBitsToFloat(read_long());
|
|
539 |
}
|
|
540 |
|
|
541 |
public final double read_double() {
|
|
542 |
return Double.longBitsToDouble(read_longlong());
|
|
543 |
}
|
|
544 |
|
|
545 |
protected final void checkForNegativeLength(int length) {
|
|
546 |
if (length < 0)
|
|
547 |
throw wrapper.negativeStringLength( CompletionStatus.COMPLETED_MAYBE,
|
|
548 |
new Integer(length) ) ;
|
|
549 |
}
|
|
550 |
|
|
551 |
protected final String readStringOrIndirection(boolean allowIndirection) {
|
|
552 |
|
|
553 |
int len = read_long();
|
|
554 |
|
|
555 |
//
|
|
556 |
// Check for indirection
|
|
557 |
//
|
|
558 |
if (allowIndirection) {
|
|
559 |
if (len == 0xffffffff)
|
|
560 |
return null;
|
|
561 |
else
|
|
562 |
stringIndirection = get_offset() - 4;
|
|
563 |
}
|
|
564 |
|
|
565 |
checkForNegativeLength(len);
|
|
566 |
|
|
567 |
if (orb != null && ORBUtility.isLegacyORB((ORB)orb))
|
|
568 |
return legacyReadString(len);
|
|
569 |
else
|
|
570 |
return internalReadString(len);
|
|
571 |
}
|
|
572 |
|
|
573 |
private final String internalReadString(int len) {
|
|
574 |
// Workaround for ORBs which send string lengths of
|
|
575 |
// zero to mean empty string.
|
|
576 |
//
|
|
577 |
// IMPORTANT: Do not replace 'new String("")' with "", it may result
|
|
578 |
// in a Serialization bug (See serialization.zerolengthstring) and
|
|
579 |
// bug id: 4728756 for details
|
|
580 |
if (len == 0)
|
|
581 |
return new String("");
|
|
582 |
|
|
583 |
char[] result = getConvertedChars(len - 1, getCharConverter());
|
|
584 |
|
|
585 |
// Skip over the 1 byte null
|
|
586 |
read_octet();
|
|
587 |
|
|
588 |
return new String(result, 0, getCharConverter().getNumChars());
|
|
589 |
}
|
|
590 |
|
|
591 |
private final String legacyReadString(int len) {
|
|
592 |
|
|
593 |
//
|
|
594 |
// Workaround for ORBs which send string lengths of
|
|
595 |
// zero to mean empty string.
|
|
596 |
//
|
|
597 |
//
|
|
598 |
// IMPORTANT: Do not replace 'new String("")' with "", it may result
|
|
599 |
// in a Serialization bug (See serialization.zerolengthstring) and
|
|
600 |
// bug id: 4728756 for details
|
|
601 |
if (len == 0)
|
|
602 |
return new String("");
|
|
603 |
|
|
604 |
len--;
|
|
605 |
char[] c = new char[len];
|
|
606 |
|
|
607 |
int n = 0;
|
|
608 |
while (n < len) {
|
|
609 |
int avail;
|
|
610 |
int bytes;
|
|
611 |
int wanted;
|
|
612 |
|
|
613 |
avail = bbwi.buflen - bbwi.position();
|
|
614 |
if (avail <= 0) {
|
|
615 |
grow(1, 1);
|
|
616 |
avail = bbwi.buflen - bbwi.position();
|
|
617 |
}
|
|
618 |
wanted = len - n;
|
|
619 |
bytes = (wanted < avail) ? wanted : avail;
|
|
620 |
// Microbenchmarks are showing a loop of ByteBuffer.get(int) being
|
|
621 |
// faster than ByteBuffer.get(byte[], int, int).
|
|
622 |
for (int i=0; i<bytes; i++) {
|
|
623 |
c[n+i] = (char) (bbwi.byteBuffer.get(bbwi.position()+i) & 0xFF);
|
|
624 |
}
|
|
625 |
bbwi.position(bbwi.position() + bytes);
|
|
626 |
n += bytes;
|
|
627 |
}
|
|
628 |
|
|
629 |
//
|
|
630 |
// Skip past terminating null byte
|
|
631 |
//
|
|
632 |
if (bbwi.position() + 1 > bbwi.buflen)
|
|
633 |
alignAndCheck(1, 1);
|
|
634 |
bbwi.position(bbwi.position() + 1);
|
|
635 |
|
|
636 |
return new String(c);
|
|
637 |
}
|
|
638 |
|
|
639 |
public final String read_string() {
|
|
640 |
return readStringOrIndirection(false);
|
|
641 |
}
|
|
642 |
|
|
643 |
public String read_wstring() {
|
|
644 |
// Don't allow transmission of wchar/wstring data with
|
|
645 |
// foreign ORBs since it's against the spec.
|
|
646 |
if (ORBUtility.isForeignORB((ORB)orb)) {
|
|
647 |
throw wrapper.wcharDataInGiop10( CompletionStatus.COMPLETED_MAYBE);
|
|
648 |
}
|
|
649 |
|
|
650 |
int len = read_long();
|
|
651 |
|
|
652 |
//
|
|
653 |
// Workaround for ORBs which send string lengths of
|
|
654 |
// zero to mean empty string.
|
|
655 |
//
|
|
656 |
//
|
|
657 |
// IMPORTANT: Do not replace 'new String("")' with "", it may result
|
|
658 |
// in a Serialization bug (See serialization.zerolengthstring) and
|
|
659 |
// bug id: 4728756 for details
|
|
660 |
if (len == 0)
|
|
661 |
return new String("");
|
|
662 |
|
|
663 |
checkForNegativeLength(len);
|
|
664 |
|
|
665 |
len--;
|
|
666 |
char[] c = new char[len];
|
|
667 |
|
|
668 |
for (int i = 0; i < len; i++)
|
|
669 |
c[i] = read_wchar();
|
|
670 |
|
|
671 |
// skip the two null terminator bytes
|
|
672 |
read_wchar();
|
|
673 |
// bbwi.position(bbwi.position() + 2);
|
|
674 |
|
|
675 |
return new String(c);
|
|
676 |
}
|
|
677 |
|
|
678 |
public final void read_octet_array(byte[] b, int offset, int length) {
|
|
679 |
if ( b == null )
|
|
680 |
throw wrapper.nullParam() ;
|
|
681 |
|
|
682 |
// Must call alignAndCheck at least once to ensure
|
|
683 |
// we aren't at the end of a chunk. Of course, we
|
|
684 |
// should only call it if we actually need to read
|
|
685 |
// something, otherwise we might end up with an
|
|
686 |
// exception at the end of the stream.
|
|
687 |
if (length == 0)
|
|
688 |
return;
|
|
689 |
|
|
690 |
alignAndCheck(1, 1);
|
|
691 |
|
|
692 |
int n = offset;
|
|
693 |
while (n < length+offset) {
|
|
694 |
int avail;
|
|
695 |
int bytes;
|
|
696 |
int wanted;
|
|
697 |
|
|
698 |
avail = bbwi.buflen - bbwi.position();
|
|
699 |
if (avail <= 0) {
|
|
700 |
grow(1, 1);
|
|
701 |
avail = bbwi.buflen - bbwi.position();
|
|
702 |
}
|
|
703 |
wanted = (length + offset) - n;
|
|
704 |
bytes = (wanted < avail) ? wanted : avail;
|
|
705 |
// Microbenchmarks are showing a loop of ByteBuffer.get(int) being
|
|
706 |
// faster than ByteBuffer.get(byte[], int, int).
|
|
707 |
for (int i = 0; i < bytes; i++) {
|
|
708 |
b[n+i] = bbwi.byteBuffer.get(bbwi.position() + i);
|
|
709 |
}
|
|
710 |
|
|
711 |
bbwi.position(bbwi.position() + bytes);
|
|
712 |
|
|
713 |
n += bytes;
|
|
714 |
}
|
|
715 |
}
|
|
716 |
|
|
717 |
public Principal read_Principal() {
|
|
718 |
int len = read_long();
|
|
719 |
byte[] pvalue = new byte[len];
|
|
720 |
read_octet_array(pvalue,0,len);
|
|
721 |
|
|
722 |
Principal p = new PrincipalImpl();
|
|
723 |
p.name(pvalue);
|
|
724 |
return p;
|
|
725 |
}
|
|
726 |
|
|
727 |
public TypeCode read_TypeCode() {
|
|
728 |
TypeCodeImpl tc = new TypeCodeImpl(orb);
|
|
729 |
tc.read_value(parent);
|
|
730 |
return tc;
|
|
731 |
}
|
|
732 |
|
|
733 |
public Any read_any() {
|
|
734 |
Any any = orb.create_any();
|
|
735 |
TypeCodeImpl tc = new TypeCodeImpl(orb);
|
|
736 |
|
|
737 |
// read off the typecode
|
|
738 |
|
|
739 |
// REVISIT We could avoid this try-catch if we could peek the typecode
|
|
740 |
// kind off this stream and see if it is a tk_value. Looking at the
|
|
741 |
// code we know that for tk_value the Any.read_value() below
|
|
742 |
// ignores the tc argument anyway (except for the kind field).
|
|
743 |
// But still we would need to make sure that the whole typecode,
|
|
744 |
// including encapsulations, is read off.
|
|
745 |
try {
|
|
746 |
tc.read_value(parent);
|
|
747 |
} catch (MARSHAL ex) {
|
|
748 |
if (tc.kind().value() != TCKind._tk_value)
|
|
749 |
throw ex;
|
|
750 |
// We can be sure that the whole typecode encapsulation has been
|
|
751 |
// read off.
|
|
752 |
dprintThrowable(ex);
|
|
753 |
}
|
|
754 |
// read off the value of the any
|
|
755 |
any.read_value(parent, tc);
|
|
756 |
|
|
757 |
return any;
|
|
758 |
}
|
|
759 |
|
|
760 |
public org.omg.CORBA.Object read_Object() {
|
|
761 |
return read_Object(null);
|
|
762 |
}
|
|
763 |
|
|
764 |
// ------------ RMI related methods --------------------------
|
|
765 |
|
|
766 |
// IDL to Java ptc-00-01-08 1.21.4.1
|
|
767 |
//
|
|
768 |
// The clz argument to read_Object can be either a stub
|
|
769 |
// Class or the "Class object for the RMI/IDL interface type
|
|
770 |
// that is statically expected."
|
|
771 |
// This functions as follows:
|
|
772 |
// 1. If clz==null, just use the repository ID from the stub
|
|
773 |
// 2. If clz is a stub class, just use it as a static factory.
|
|
774 |
// clz is a stub class iff StubAdapter.isStubClass( clz ).
|
|
775 |
// In addition, clz is a IDL stub class iff
|
|
776 |
// IDLEntity.class.isAssignableFrom( clz ).
|
|
777 |
// 3. If clz is an interface, use it to create the appropriate
|
|
778 |
// stub factory.
|
|
779 |
public org.omg.CORBA.Object read_Object(Class clz)
|
|
780 |
{
|
|
781 |
// In any case, we must first read the IOR.
|
|
782 |
IOR ior = IORFactories.makeIOR(parent) ;
|
|
783 |
if (ior.isNil())
|
|
784 |
return null ;
|
|
785 |
|
|
786 |
PresentationManager.StubFactoryFactory sff = ORB.getStubFactoryFactory() ;
|
|
787 |
String codeBase = ior.getProfile().getCodebase() ;
|
|
788 |
PresentationManager.StubFactory stubFactory = null ;
|
|
789 |
|
|
790 |
if (clz == null) {
|
|
791 |
RepositoryId rid = RepositoryId.cache.getId( ior.getTypeId() ) ;
|
|
792 |
String className = rid.getClassName() ;
|
|
793 |
boolean isIDLInterface = rid.isIDLType() ;
|
|
794 |
|
|
795 |
if (className == null || className.equals( "" ))
|
|
796 |
stubFactory = null ;
|
|
797 |
else
|
|
798 |
try {
|
|
799 |
stubFactory = sff.createStubFactory( className,
|
|
800 |
isIDLInterface, codeBase, (Class)null,
|
|
801 |
(ClassLoader)null );
|
|
802 |
} catch (Exception exc) {
|
|
803 |
// Could not create stubFactory, so use null.
|
|
804 |
// XXX stubFactory handling is still too complex:
|
|
805 |
// Can we resolve the stubFactory question once in
|
|
806 |
// a single place?
|
|
807 |
stubFactory = null ;
|
|
808 |
}
|
|
809 |
} else if (StubAdapter.isStubClass( clz )) {
|
|
810 |
stubFactory = PresentationDefaults.makeStaticStubFactory(
|
|
811 |
clz ) ;
|
|
812 |
} else {
|
|
813 |
// clz is an interface class
|
|
814 |
boolean isIDL = IDLEntity.class.isAssignableFrom( clz ) ;
|
|
815 |
|
|
816 |
stubFactory = sff.createStubFactory( clz.getName(),
|
|
817 |
isIDL, codeBase, clz, clz.getClassLoader() ) ;
|
|
818 |
}
|
|
819 |
|
|
820 |
return internalIORToObject( ior, stubFactory, orb ) ;
|
|
821 |
}
|
|
822 |
|
|
823 |
/*
|
|
824 |
* This is used as a general utility (e.g., the PortableInterceptor
|
|
825 |
* implementation uses it. If stubFactory is null, the ior's
|
|
826 |
* IIOPProfile must support getServant.
|
|
827 |
*/
|
|
828 |
public static org.omg.CORBA.Object internalIORToObject(
|
|
829 |
IOR ior, PresentationManager.StubFactory stubFactory, ORB orb)
|
|
830 |
{
|
|
831 |
ORBUtilSystemException wrapper = ORBUtilSystemException.get(
|
|
832 |
(ORB)orb, CORBALogDomains.RPC_ENCODING ) ;
|
|
833 |
|
|
834 |
java.lang.Object servant = ior.getProfile().getServant() ;
|
|
835 |
if (servant != null ) {
|
|
836 |
if (servant instanceof Tie) {
|
|
837 |
String codebase = ior.getProfile().getCodebase();
|
|
838 |
org.omg.CORBA.Object objref = (org.omg.CORBA.Object)
|
|
839 |
Utility.loadStub( (Tie)servant, stubFactory, codebase,
|
|
840 |
false);
|
|
841 |
|
|
842 |
// If we managed to load a stub, return it, otherwise we
|
|
843 |
// must fail...
|
|
844 |
if (objref != null) {
|
|
845 |
return objref;
|
|
846 |
} else {
|
|
847 |
throw wrapper.readObjectException() ;
|
|
848 |
}
|
|
849 |
} else if (servant instanceof org.omg.CORBA.Object) {
|
|
850 |
if (!(servant instanceof
|
|
851 |
org.omg.CORBA.portable.InvokeHandler)) {
|
|
852 |
return (org.omg.CORBA.Object) servant;
|
|
853 |
}
|
|
854 |
} else
|
|
855 |
throw wrapper.badServantReadObject() ;
|
|
856 |
}
|
|
857 |
|
|
858 |
CorbaClientDelegate del = ORBUtility.makeClientDelegate( ior ) ;
|
|
859 |
org.omg.CORBA.Object objref = null ;
|
|
860 |
try {
|
|
861 |
objref = stubFactory.makeStub() ;
|
|
862 |
} catch (Throwable e) {
|
|
863 |
wrapper.stubCreateError( e ) ;
|
|
864 |
|
|
865 |
if (e instanceof ThreadDeath) {
|
|
866 |
throw (ThreadDeath) e;
|
|
867 |
}
|
|
868 |
|
|
869 |
// Return the "default" stub...
|
|
870 |
objref = new CORBAObjectImpl() ;
|
|
871 |
}
|
|
872 |
|
|
873 |
StubAdapter.setDelegate( objref, del ) ;
|
|
874 |
return objref;
|
|
875 |
}
|
|
876 |
|
|
877 |
public java.lang.Object read_abstract_interface()
|
|
878 |
{
|
|
879 |
return read_abstract_interface(null);
|
|
880 |
}
|
|
881 |
|
|
882 |
public java.lang.Object read_abstract_interface(java.lang.Class clz)
|
|
883 |
{
|
|
884 |
boolean object = read_boolean();
|
|
885 |
|
|
886 |
if (object) {
|
|
887 |
return read_Object(clz);
|
|
888 |
} else {
|
|
889 |
return read_value();
|
|
890 |
}
|
|
891 |
}
|
|
892 |
|
|
893 |
public Serializable read_value()
|
|
894 |
{
|
|
895 |
return read_value((Class)null);
|
|
896 |
}
|
|
897 |
|
|
898 |
private Serializable handleIndirection() {
|
|
899 |
int indirection = read_long() + get_offset() - 4;
|
|
900 |
if (valueCache != null && valueCache.containsVal(indirection)) {
|
|
901 |
|
|
902 |
java.io.Serializable cachedValue
|
|
903 |
= (java.io.Serializable)valueCache.getKey(indirection);
|
|
904 |
return cachedValue;
|
|
905 |
} else {
|
|
906 |
// In RMI-IIOP the ValueHandler will recognize this
|
|
907 |
// exception and use the provided indirection value
|
|
908 |
// to lookup a possible indirection to an object
|
|
909 |
// currently on the deserialization stack.
|
|
910 |
throw new IndirectionException(indirection);
|
|
911 |
}
|
|
912 |
}
|
|
913 |
|
|
914 |
private String readRepositoryIds(int valueTag,
|
|
915 |
Class expectedType,
|
|
916 |
String expectedTypeRepId) {
|
|
917 |
return readRepositoryIds(valueTag, expectedType,
|
|
918 |
expectedTypeRepId, null);
|
|
919 |
}
|
|
920 |
|
|
921 |
/**
|
|
922 |
* Examines the valuetag to see how many (if any) repository IDs
|
|
923 |
* are present on the wire. If no repository ID information
|
|
924 |
* is on the wire but the expectedType or expectedTypeRepId
|
|
925 |
* is known, it will return one of those (favoring the
|
|
926 |
* expectedType's repId). Failing that, it uses the supplied
|
|
927 |
* BoxedValueHelper to obtain the repository ID, as a last resort.
|
|
928 |
*/
|
|
929 |
private String readRepositoryIds(int valueTag,
|
|
930 |
Class expectedType,
|
|
931 |
String expectedTypeRepId,
|
|
932 |
BoxedValueHelper factory) {
|
|
933 |
switch(repIdUtil.getTypeInfo(valueTag)) {
|
|
934 |
case RepositoryIdUtility.NO_TYPE_INFO :
|
|
935 |
// Throw an exception if we have no repository ID info and
|
|
936 |
// no expectedType to work with. Otherwise, how would we
|
|
937 |
// know what to unmarshal?
|
|
938 |
if (expectedType == null) {
|
|
939 |
if (expectedTypeRepId != null) {
|
|
940 |
return expectedTypeRepId;
|
|
941 |
} else if (factory != null) {
|
|
942 |
return factory.get_id();
|
|
943 |
} else {
|
|
944 |
throw wrapper.expectedTypeNullAndNoRepId(
|
|
945 |
CompletionStatus.COMPLETED_MAYBE);
|
|
946 |
}
|
|
947 |
}
|
|
948 |
return repIdStrs.createForAnyType(expectedType);
|
|
949 |
case RepositoryIdUtility.SINGLE_REP_TYPE_INFO :
|
|
950 |
return read_repositoryId();
|
|
951 |
case RepositoryIdUtility.PARTIAL_LIST_TYPE_INFO :
|
|
952 |
return read_repositoryIds();
|
|
953 |
default:
|
|
954 |
throw wrapper.badValueTag( CompletionStatus.COMPLETED_MAYBE,
|
|
955 |
Integer.toHexString(valueTag) ) ;
|
|
956 |
}
|
|
957 |
}
|
|
958 |
|
|
959 |
public Serializable read_value(Class expectedType) {
|
|
960 |
|
|
961 |
// Read value tag
|
|
962 |
int vType = readValueTag();
|
|
963 |
|
|
964 |
// Is value null?
|
|
965 |
if (vType == 0)
|
|
966 |
return null;
|
|
967 |
|
|
968 |
// Is this an indirection to a previously
|
|
969 |
// read valuetype?
|
|
970 |
if (vType == 0xffffffff)
|
|
971 |
return handleIndirection();
|
|
972 |
|
|
973 |
// Save where this valuetype started so we
|
|
974 |
// can put it in the indirection valueCache
|
|
975 |
// later
|
|
976 |
int indirection = get_offset() - 4;
|
|
977 |
|
|
978 |
// Need to save this special marker variable
|
|
979 |
// to restore its value during recursion
|
|
980 |
boolean saveIsChunked = isChunked;
|
|
981 |
|
|
982 |
isChunked = repIdUtil.isChunkedEncoding(vType);
|
|
983 |
|
|
984 |
java.lang.Object value = null;
|
|
985 |
|
|
986 |
String codebase_URL = null;
|
|
987 |
if (repIdUtil.isCodeBasePresent(vType)) {
|
|
988 |
codebase_URL = read_codebase_URL();
|
|
989 |
}
|
|
990 |
|
|
991 |
// Read repository id(s)
|
|
992 |
String repositoryIDString
|
|
993 |
= readRepositoryIds(vType, expectedType, null);
|
|
994 |
|
|
995 |
// If isChunked was determined to be true based
|
|
996 |
// on the valuetag, this will read a chunk length
|
|
997 |
start_block();
|
|
998 |
|
|
999 |
// Remember that end_flag keeps track of all nested
|
|
1000 |
// valuetypes and is used for older ORBs
|
|
1001 |
end_flag--;
|
|
1002 |
if (isChunked)
|
|
1003 |
chunkedValueNestingLevel--;
|
|
1004 |
|
|
1005 |
if (repositoryIDString.equals(repIdStrs.getWStringValueRepId())) {
|
|
1006 |
value = read_wstring();
|
|
1007 |
} else
|
|
1008 |
if (repositoryIDString.equals(repIdStrs.getClassDescValueRepId())) {
|
|
1009 |
// read in the class whether with the old ClassDesc or the
|
|
1010 |
// new one
|
|
1011 |
value = readClass();
|
|
1012 |
} else {
|
|
1013 |
|
|
1014 |
Class valueClass = expectedType;
|
|
1015 |
|
|
1016 |
// By this point, either the expectedType or repositoryIDString
|
|
1017 |
// is guaranteed to be non-null.
|
|
1018 |
if (expectedType == null ||
|
|
1019 |
!repositoryIDString.equals(repIdStrs.createForAnyType(expectedType))) {
|
|
1020 |
|
|
1021 |
valueClass = getClassFromString(repositoryIDString,
|
|
1022 |
codebase_URL,
|
|
1023 |
expectedType);
|
|
1024 |
}
|
|
1025 |
|
|
1026 |
if (valueClass == null) {
|
|
1027 |
// No point attempting to use value handler below, since the
|
|
1028 |
// class information is not available.
|
|
1029 |
throw wrapper.couldNotFindClass(
|
|
1030 |
CompletionStatus.COMPLETED_MAYBE,
|
|
1031 |
new ClassNotFoundException());
|
|
1032 |
}
|
|
1033 |
|
|
1034 |
if (valueClass != null &&
|
|
1035 |
org.omg.CORBA.portable.IDLEntity.class.isAssignableFrom(valueClass)) {
|
|
1036 |
|
|
1037 |
value = readIDLValue(indirection,
|
|
1038 |
repositoryIDString,
|
|
1039 |
valueClass,
|
|
1040 |
codebase_URL);
|
|
1041 |
|
|
1042 |
} else {
|
|
1043 |
|
|
1044 |
// Must be some form of RMI-IIOP valuetype
|
|
1045 |
|
|
1046 |
try {
|
|
1047 |
if (valueHandler == null)
|
|
1048 |
valueHandler = ORBUtility.createValueHandler(orb);
|
|
1049 |
|
|
1050 |
value = valueHandler.readValue(parent,
|
|
1051 |
indirection,
|
|
1052 |
valueClass,
|
|
1053 |
repositoryIDString,
|
|
1054 |
getCodeBase());
|
|
1055 |
|
|
1056 |
} catch(SystemException sysEx) {
|
|
1057 |
// Just rethrow any CORBA system exceptions
|
|
1058 |
// that come out of the ValueHandler
|
|
1059 |
throw sysEx;
|
|
1060 |
} catch(Exception ex) {
|
|
1061 |
throw wrapper.valuehandlerReadException(
|
|
1062 |
CompletionStatus.COMPLETED_MAYBE, ex ) ;
|
|
1063 |
} catch(Error e) {
|
|
1064 |
throw wrapper.valuehandlerReadError(
|
|
1065 |
CompletionStatus.COMPLETED_MAYBE, e ) ;
|
|
1066 |
}
|
|
1067 |
}
|
|
1068 |
}
|
|
1069 |
|
|
1070 |
// Skip any remaining chunks until we get to
|
|
1071 |
// an end tag or a valuetag. If we see a valuetag,
|
|
1072 |
// that means there was another valuetype in the sender's
|
|
1073 |
// version of this class that we need to skip over.
|
|
1074 |
handleEndOfValue();
|
|
1075 |
|
|
1076 |
// Read and process the end tag if we're chunking.
|
|
1077 |
// Assumes that we're at the position of the end tag
|
|
1078 |
// (handleEndOfValue should assure this)
|
|
1079 |
readEndTag();
|
|
1080 |
|
|
1081 |
// Cache the valuetype that we read
|
|
1082 |
if (valueCache == null)
|
|
1083 |
valueCache = new CacheTable(orb,false);
|
|
1084 |
valueCache.put(value, indirection);
|
|
1085 |
|
|
1086 |
// Allow for possible continuation chunk.
|
|
1087 |
// If we're a nested valuetype inside of a chunked
|
|
1088 |
// valuetype, and that enclosing valuetype has
|
|
1089 |
// more data to write, it will need to have this
|
|
1090 |
// new chunk begin after we wrote our end tag.
|
|
1091 |
isChunked = saveIsChunked;
|
|
1092 |
start_block();
|
|
1093 |
|
|
1094 |
return (java.io.Serializable)value;
|
|
1095 |
}
|
|
1096 |
|
|
1097 |
public Serializable read_value(BoxedValueHelper factory) {
|
|
1098 |
|
|
1099 |
// Read value tag
|
|
1100 |
int vType = readValueTag();
|
|
1101 |
|
|
1102 |
if (vType == 0)
|
|
1103 |
return null; // value is null
|
|
1104 |
else if (vType == 0xffffffff) { // Indirection tag
|
|
1105 |
int indirection = read_long() + get_offset() - 4;
|
|
1106 |
if (valueCache != null && valueCache.containsVal(indirection))
|
|
1107 |
{
|
|
1108 |
java.io.Serializable cachedValue =
|
|
1109 |
(java.io.Serializable)valueCache.getKey(indirection);
|
|
1110 |
return cachedValue;
|
|
1111 |
}
|
|
1112 |
else {
|
|
1113 |
throw new IndirectionException(indirection);
|
|
1114 |
}
|
|
1115 |
}
|
|
1116 |
else {
|
|
1117 |
int indirection = get_offset() - 4;
|
|
1118 |
|
|
1119 |
// end_block();
|
|
1120 |
|
|
1121 |
boolean saveIsChunked = isChunked;
|
|
1122 |
isChunked = repIdUtil.isChunkedEncoding(vType);
|
|
1123 |
|
|
1124 |
java.lang.Object value = null;
|
|
1125 |
|
|
1126 |
String codebase_URL = null;
|
|
1127 |
if (repIdUtil.isCodeBasePresent(vType)){
|
|
1128 |
codebase_URL = read_codebase_URL();
|
|
1129 |
}
|
|
1130 |
|
|
1131 |
// Read repository id
|
|
1132 |
String repositoryIDString
|
|
1133 |
= readRepositoryIds(vType, null, null, factory);
|
|
1134 |
|
|
1135 |
// Compare rep. ids to see if we should use passed helper
|
|
1136 |
if (!repositoryIDString.equals(factory.get_id()))
|
|
1137 |
factory = Utility.getHelper(null, codebase_URL, repositoryIDString);
|
|
1138 |
|
|
1139 |
start_block();
|
|
1140 |
end_flag--;
|
|
1141 |
if (isChunked)
|
|
1142 |
chunkedValueNestingLevel--;
|
|
1143 |
|
|
1144 |
if (factory instanceof ValueHelper) {
|
|
1145 |
value = readIDLValueWithHelper((ValueHelper)factory, indirection);
|
|
1146 |
} else {
|
|
1147 |
valueIndirection = indirection; // for callback
|
|
1148 |
value = factory.read_value(parent);
|
|
1149 |
}
|
|
1150 |
|
|
1151 |
handleEndOfValue();
|
|
1152 |
readEndTag();
|
|
1153 |
|
|
1154 |
// Put into valueCache
|
|
1155 |
if (valueCache == null)
|
|
1156 |
valueCache = new CacheTable(orb,false);
|
|
1157 |
valueCache.put(value, indirection);
|
|
1158 |
|
|
1159 |
// allow for possible continuation chunk
|
|
1160 |
isChunked = saveIsChunked;
|
|
1161 |
start_block();
|
|
1162 |
|
|
1163 |
return (java.io.Serializable)value;
|
|
1164 |
}
|
|
1165 |
}
|
|
1166 |
|
|
1167 |
private boolean isCustomType(ValueHelper helper) {
|
|
1168 |
try{
|
|
1169 |
TypeCode tc = helper.get_type();
|
|
1170 |
int kind = tc.kind().value();
|
|
1171 |
if (kind == TCKind._tk_value) {
|
|
1172 |
return (tc.type_modifier() == org.omg.CORBA.VM_CUSTOM.value);
|
|
1173 |
}
|
|
1174 |
} catch(BadKind ex) {
|
|
1175 |
throw wrapper.badKind(ex) ;
|
|
1176 |
}
|
|
1177 |
|
|
1178 |
return false;
|
|
1179 |
}
|
|
1180 |
|
|
1181 |
// This method is actually called indirectly by
|
|
1182 |
// read_value(String repositoryId).
|
|
1183 |
// Therefore, it is not a truly independent read call that handles
|
|
1184 |
// header information itself.
|
|
1185 |
public java.io.Serializable read_value(java.io.Serializable value) {
|
|
1186 |
|
|
1187 |
// Put into valueCache using valueIndirection
|
|
1188 |
if (valueCache == null)
|
|
1189 |
valueCache = new CacheTable(orb,false);
|
|
1190 |
valueCache.put(value, valueIndirection);
|
|
1191 |
|
|
1192 |
if (value instanceof StreamableValue)
|
|
1193 |
((StreamableValue)value)._read(parent);
|
|
1194 |
else if (value instanceof CustomValue)
|
|
1195 |
((CustomValue)value).unmarshal(parent);
|
|
1196 |
|
|
1197 |
return value;
|
|
1198 |
}
|
|
1199 |
|
|
1200 |
public java.io.Serializable read_value(java.lang.String repositoryId) {
|
|
1201 |
|
|
1202 |
// if (inBlock)
|
|
1203 |
// end_block();
|
|
1204 |
|
|
1205 |
// Read value tag
|
|
1206 |
int vType = readValueTag();
|
|
1207 |
|
|
1208 |
if (vType == 0)
|
|
1209 |
return null; // value is null
|
|
1210 |
else if (vType == 0xffffffff) { // Indirection tag
|
|
1211 |
int indirection = read_long() + get_offset() - 4;
|
|
1212 |
if (valueCache != null && valueCache.containsVal(indirection))
|
|
1213 |
{
|
|
1214 |
java.io.Serializable cachedValue =
|
|
1215 |
(java.io.Serializable)valueCache.getKey(indirection);
|
|
1216 |
return cachedValue;
|
|
1217 |
}
|
|
1218 |
else {
|
|
1219 |
throw new IndirectionException(indirection);
|
|
1220 |
}
|
|
1221 |
}
|
|
1222 |
else {
|
|
1223 |
int indirection = get_offset() - 4;
|
|
1224 |
|
|
1225 |
// end_block();
|
|
1226 |
|
|
1227 |
boolean saveIsChunked = isChunked;
|
|
1228 |
isChunked = repIdUtil.isChunkedEncoding(vType);
|
|
1229 |
|
|
1230 |
java.lang.Object value = null;
|
|
1231 |
|
|
1232 |
String codebase_URL = null;
|
|
1233 |
if (repIdUtil.isCodeBasePresent(vType)){
|
|
1234 |
codebase_URL = read_codebase_URL();
|
|
1235 |
}
|
|
1236 |
|
|
1237 |
// Read repository id
|
|
1238 |
String repositoryIDString
|
|
1239 |
= readRepositoryIds(vType, null, repositoryId);
|
|
1240 |
|
|
1241 |
ValueFactory factory =
|
|
1242 |
Utility.getFactory(null, codebase_URL, orb, repositoryIDString);
|
|
1243 |
|
|
1244 |
start_block();
|
|
1245 |
end_flag--;
|
|
1246 |
if (isChunked)
|
|
1247 |
chunkedValueNestingLevel--;
|
|
1248 |
|
|
1249 |
valueIndirection = indirection; // for callback
|
|
1250 |
value = factory.read_value(parent);
|
|
1251 |
|
|
1252 |
handleEndOfValue();
|
|
1253 |
readEndTag();
|
|
1254 |
|
|
1255 |
// Put into valueCache
|
|
1256 |
if (valueCache == null)
|
|
1257 |
valueCache = new CacheTable(orb,false);
|
|
1258 |
valueCache.put(value, indirection);
|
|
1259 |
|
|
1260 |
// allow for possible continuation chunk
|
|
1261 |
isChunked = saveIsChunked;
|
|
1262 |
start_block();
|
|
1263 |
|
|
1264 |
return (java.io.Serializable)value;
|
|
1265 |
}
|
|
1266 |
}
|
|
1267 |
|
|
1268 |
private Class readClass() {
|
|
1269 |
|
|
1270 |
String codebases = null, classRepId = null;
|
|
1271 |
|
|
1272 |
if (orb == null ||
|
|
1273 |
ORBVersionFactory.getFOREIGN().equals(orb.getORBVersion()) ||
|
|
1274 |
ORBVersionFactory.getNEWER().compareTo(orb.getORBVersion()) <= 0) {
|
|
1275 |
|
|
1276 |
codebases = (String)read_value(java.lang.String.class);
|
|
1277 |
classRepId = (String)read_value(java.lang.String.class);
|
|
1278 |
} else {
|
|
1279 |
// Pre-Merlin/J2EE 1.3 ORBs wrote the repository ID
|
|
1280 |
// and codebase strings in the wrong order.
|
|
1281 |
classRepId = (String)read_value(java.lang.String.class);
|
|
1282 |
codebases = (String)read_value(java.lang.String.class);
|
|
1283 |
}
|
|
1284 |
|
|
1285 |
if (debug) {
|
|
1286 |
dprint("readClass codebases: "
|
|
1287 |
+ codebases
|
|
1288 |
+ " rep Id: "
|
|
1289 |
+ classRepId);
|
|
1290 |
}
|
|
1291 |
|
|
1292 |
Class cl = null;
|
|
1293 |
|
|
1294 |
RepositoryIdInterface repositoryID
|
|
1295 |
= repIdStrs.getFromString(classRepId);
|
|
1296 |
|
|
1297 |
try {
|
|
1298 |
cl = repositoryID.getClassFromType(codebases);
|
|
1299 |
} catch(ClassNotFoundException cnfe) {
|
|
1300 |
throw wrapper.cnfeReadClass( CompletionStatus.COMPLETED_MAYBE,
|
|
1301 |
cnfe, repositoryID.getClassName() ) ;
|
|
1302 |
} catch(MalformedURLException me) {
|
|
1303 |
throw wrapper.malformedUrl( CompletionStatus.COMPLETED_MAYBE,
|
|
1304 |
me, repositoryID.getClassName(), codebases ) ;
|
|
1305 |
}
|
|
1306 |
|
|
1307 |
return cl;
|
|
1308 |
}
|
|
1309 |
|
|
1310 |
private java.lang.Object readIDLValueWithHelper(ValueHelper helper, int indirection)
|
|
1311 |
{
|
|
1312 |
// look for two-argument static read method
|
|
1313 |
Method readMethod;
|
|
1314 |
try {
|
|
1315 |
Class argTypes[] = {org.omg.CORBA.portable.InputStream.class, helper.get_class()};
|
|
1316 |
readMethod = helper.getClass().getDeclaredMethod(kReadMethod, argTypes);
|
|
1317 |
}
|
|
1318 |
catch(NoSuchMethodException nsme) { // must be boxed value helper
|
|
1319 |
java.lang.Object result = helper.read_value(parent);
|
|
1320 |
return result;
|
|
1321 |
}
|
|
1322 |
|
|
1323 |
// found two-argument read method, so must be non-boxed value...
|
|
1324 |
// ...create a blank instance
|
|
1325 |
java.lang.Object val = null;
|
|
1326 |
try {
|
|
1327 |
val = helper.get_class().newInstance();
|
|
1328 |
} catch(java.lang.InstantiationException ie) {
|
|
1329 |
throw wrapper.couldNotInstantiateHelper( ie,
|
|
1330 |
helper.get_class() ) ;
|
|
1331 |
} catch(IllegalAccessException iae){
|
|
1332 |
// Value's constructor is protected or private
|
|
1333 |
//
|
|
1334 |
// So, use the helper to read the value.
|
|
1335 |
//
|
|
1336 |
// NOTE : This means that in this particular case a recursive ref.
|
|
1337 |
// would fail.
|
|
1338 |
return helper.read_value(parent);
|
|
1339 |
}
|
|
1340 |
|
|
1341 |
// add blank instance to cache table
|
|
1342 |
if (valueCache == null)
|
|
1343 |
valueCache = new CacheTable(orb,false);
|
|
1344 |
valueCache.put(val, indirection);
|
|
1345 |
|
|
1346 |
// if custom type, call unmarshal method
|
|
1347 |
if (val instanceof CustomMarshal && isCustomType(helper)) {
|
|
1348 |
((CustomMarshal)val).unmarshal(parent);
|
|
1349 |
return val;
|
|
1350 |
}
|
|
1351 |
|
|
1352 |
// call two-argument read method using reflection
|
|
1353 |
try {
|
|
1354 |
java.lang.Object args[] = {parent, val};
|
|
1355 |
readMethod.invoke(helper, args);
|
|
1356 |
return val;
|
|
1357 |
} catch(IllegalAccessException iae2) {
|
|
1358 |
throw wrapper.couldNotInvokeHelperReadMethod( iae2, helper.get_class() ) ;
|
|
1359 |
} catch(InvocationTargetException ite){
|
|
1360 |
throw wrapper.couldNotInvokeHelperReadMethod( ite, helper.get_class() ) ;
|
|
1361 |
}
|
|
1362 |
}
|
|
1363 |
|
|
1364 |
private java.lang.Object readBoxedIDLEntity(Class clazz, String codebase)
|
|
1365 |
{
|
|
1366 |
Class cls = null ;
|
|
1367 |
|
|
1368 |
try {
|
|
1369 |
ClassLoader clazzLoader = (clazz == null ? null : clazz.getClassLoader());
|
|
1370 |
|
|
1371 |
cls = Utility.loadClassForClass(clazz.getName()+"Helper", codebase,
|
|
1372 |
clazzLoader, clazz, clazzLoader);
|
|
1373 |
final Class helperClass = cls ;
|
|
1374 |
|
|
1375 |
final Class argTypes[] = {org.omg.CORBA.portable.InputStream.class};
|
|
1376 |
|
|
1377 |
// getDeclaredMethod requires RuntimePermission accessDeclaredMembers
|
|
1378 |
// if a different class loader is used (even though the javadoc says otherwise)
|
|
1379 |
Method readMethod = null;
|
|
1380 |
try {
|
|
1381 |
readMethod = (Method)AccessController.doPrivileged(
|
|
1382 |
new PrivilegedExceptionAction() {
|
|
1383 |
public java.lang.Object run() throws NoSuchMethodException {
|
|
1384 |
return helperClass.getDeclaredMethod(kReadMethod, argTypes);
|
|
1385 |
}
|
|
1386 |
}
|
|
1387 |
);
|
|
1388 |
} catch (PrivilegedActionException pae) {
|
|
1389 |
// this gets caught below
|
|
1390 |
throw (NoSuchMethodException)pae.getException();
|
|
1391 |
}
|
|
1392 |
|
|
1393 |
java.lang.Object args[] = {parent};
|
|
1394 |
return readMethod.invoke(null, args);
|
|
1395 |
|
|
1396 |
} catch (ClassNotFoundException cnfe) {
|
|
1397 |
throw wrapper.couldNotInvokeHelperReadMethod( cnfe, cls ) ;
|
|
1398 |
} catch(NoSuchMethodException nsme) {
|
|
1399 |
throw wrapper.couldNotInvokeHelperReadMethod( nsme, cls ) ;
|
|
1400 |
} catch(IllegalAccessException iae) {
|
|
1401 |
throw wrapper.couldNotInvokeHelperReadMethod( iae, cls ) ;
|
|
1402 |
} catch(InvocationTargetException ite) {
|
|
1403 |
throw wrapper.couldNotInvokeHelperReadMethod( ite, cls ) ;
|
|
1404 |
}
|
|
1405 |
}
|
|
1406 |
|
|
1407 |
private java.lang.Object readIDLValue(int indirection, String repId,
|
|
1408 |
Class clazz, String codebase)
|
|
1409 |
{
|
|
1410 |
ValueFactory factory ;
|
|
1411 |
|
|
1412 |
// Always try to find a ValueFactory first, as required by the spec.
|
|
1413 |
// There are some complications here in the IDL 3.0 mapping (see 1.13.8),
|
|
1414 |
// but basically we must always be able to override the DefaultFactory
|
|
1415 |
// or Helper mappings that are also used. This appears to be the case
|
|
1416 |
// even in the boxed value cases. The original code only did the lookup
|
|
1417 |
// in the case of class implementing either StreamableValue or CustomValue,
|
|
1418 |
// but abstract valuetypes only implement ValueBase, and really require
|
|
1419 |
// the use of the repId to find a factory (including the DefaultFactory).
|
|
1420 |
try {
|
|
1421 |
// use new-style OBV support (factory object)
|
|
1422 |
factory = Utility.getFactory(clazz, codebase, orb, repId);
|
|
1423 |
} catch (MARSHAL marshal) {
|
|
1424 |
// XXX log marshal at one of the INFO levels
|
|
1425 |
|
|
1426 |
// Could not get a factory, so try alternatives
|
|
1427 |
if (!StreamableValue.class.isAssignableFrom(clazz) &&
|
|
1428 |
!CustomValue.class.isAssignableFrom(clazz) &&
|
|
1429 |
ValueBase.class.isAssignableFrom(clazz)) {
|
|
1430 |
// use old-style OBV support (helper object)
|
|
1431 |
BoxedValueHelper helper = Utility.getHelper(clazz, codebase, repId);
|
|
1432 |
if (helper instanceof ValueHelper)
|
|
1433 |
return readIDLValueWithHelper((ValueHelper)helper, indirection);
|
|
1434 |
else
|
|
1435 |
return helper.read_value(parent);
|
|
1436 |
} else {
|
|
1437 |
// must be a boxed IDLEntity, so make a reflective call to the
|
|
1438 |
// helper's static read method...
|
|
1439 |
return readBoxedIDLEntity(clazz, codebase);
|
|
1440 |
}
|
|
1441 |
}
|
|
1442 |
|
|
1443 |
// If there was no error in getting the factory, use it.
|
|
1444 |
valueIndirection = indirection; // for callback
|
|
1445 |
return factory.read_value(parent);
|
|
1446 |
}
|
|
1447 |
|
|
1448 |
/**
|
|
1449 |
* End tags are only written for chunked valuetypes.
|
|
1450 |
*
|
|
1451 |
* Before Merlin, our ORBs wrote end tags which took into account
|
|
1452 |
* all enclosing valuetypes. This was changed by an interop resolution
|
|
1453 |
* (see details around chunkedValueNestingLevel) to only include
|
|
1454 |
* enclosing chunked types.
|
|
1455 |
*
|
|
1456 |
* ORB versioning and end tag compaction are handled here.
|
|
1457 |
*/
|
|
1458 |
private void readEndTag() {
|
|
1459 |
if (isChunked) {
|
|
1460 |
|
|
1461 |
// Read the end tag
|
|
1462 |
int anEndTag = read_long();
|
|
1463 |
|
|
1464 |
// End tags should always be negative, and the outermost
|
|
1465 |
// enclosing chunked valuetype should have a -1 end tag.
|
|
1466 |
//
|
|
1467 |
// handleEndOfValue should have assured that we were
|
|
1468 |
// at the end tag position!
|
|
1469 |
if (anEndTag >= 0) {
|
|
1470 |
throw wrapper.positiveEndTag( CompletionStatus.COMPLETED_MAYBE,
|
|
1471 |
new Integer(anEndTag), new Integer( get_offset() - 4 ) ) ;
|
|
1472 |
}
|
|
1473 |
|
|
1474 |
// If the ORB is null, or if we're sure we're talking to
|
|
1475 |
// a foreign ORB, Merlin, or something more recent, we
|
|
1476 |
// use the updated end tag computation, and are more strenuous
|
|
1477 |
// about the values.
|
|
1478 |
if (orb == null ||
|
|
1479 |
ORBVersionFactory.getFOREIGN().equals(orb.getORBVersion()) ||
|
|
1480 |
ORBVersionFactory.getNEWER().compareTo(orb.getORBVersion()) <= 0) {
|
|
1481 |
|
|
1482 |
// If the end tag we read was less than what we were expecting,
|
|
1483 |
// then the sender must think it's sent more enclosing
|
|
1484 |
// chunked valuetypes than we have. Throw an exception.
|
|
1485 |
if (anEndTag < chunkedValueNestingLevel)
|
|
1486 |
throw wrapper.unexpectedEnclosingValuetype(
|
|
1487 |
CompletionStatus.COMPLETED_MAYBE, new Integer( anEndTag ),
|
|
1488 |
new Integer( chunkedValueNestingLevel ) ) ;
|
|
1489 |
|
|
1490 |
// If the end tag is bigger than what we expected, but
|
|
1491 |
// still negative, then the sender has done some end tag
|
|
1492 |
// compaction. We back up the stream 4 bytes so that the
|
|
1493 |
// next time readEndTag is called, it will get down here
|
|
1494 |
// again. Even with fragmentation, we'll always be able
|
|
1495 |
// to do this.
|
|
1496 |
if (anEndTag != chunkedValueNestingLevel) {
|
|
1497 |
bbwi.position(bbwi.position() - 4);
|
|
1498 |
}
|
|
1499 |
|
|
1500 |
} else {
|
|
1501 |
|
|
1502 |
// When talking to Kestrel or Ladybird, we use our old
|
|
1503 |
// end tag rules and are less strict. If the end tag
|
|
1504 |
// isn't what we expected, we back up, assuming
|
|
1505 |
// compaction.
|
|
1506 |
if (anEndTag != end_flag) {
|
|
1507 |
bbwi.position(bbwi.position() - 4);
|
|
1508 |
}
|
|
1509 |
}
|
|
1510 |
|
|
1511 |
// This only keeps track of the enclosing chunked
|
|
1512 |
// valuetypes
|
|
1513 |
chunkedValueNestingLevel++;
|
|
1514 |
}
|
|
1515 |
|
|
1516 |
// This keeps track of all enclosing valuetypes
|
|
1517 |
end_flag++;
|
|
1518 |
}
|
|
1519 |
|
|
1520 |
protected int get_offset() {
|
|
1521 |
return bbwi.position();
|
|
1522 |
}
|
|
1523 |
|
|
1524 |
private void start_block() {
|
|
1525 |
|
|
1526 |
// if (outerValueDone)
|
|
1527 |
if (!isChunked)
|
|
1528 |
return;
|
|
1529 |
|
|
1530 |
// if called from alignAndCheck, need to reset blockLength
|
|
1531 |
// to avoid an infinite recursion loop on read_long() call
|
|
1532 |
blockLength = maxBlockLength;
|
|
1533 |
|
|
1534 |
blockLength = read_long();
|
|
1535 |
|
|
1536 |
// Must remember where we began the chunk to calculate how far
|
|
1537 |
// along we are. See notes above about chunkBeginPos.
|
|
1538 |
|
|
1539 |
if (blockLength > 0 && blockLength < maxBlockLength) {
|
|
1540 |
blockLength += get_offset(); // _REVISIT_ unsafe, should use a Java long
|
|
1541 |
|
|
1542 |
// inBlock = true;
|
|
1543 |
} else {
|
|
1544 |
|
|
1545 |
// System.out.println("start_block snooped a " + Integer.toHexString(blockLength));
|
|
1546 |
|
|
1547 |
// not a chunk length field
|
|
1548 |
blockLength = maxBlockLength;
|
|
1549 |
|
|
1550 |
bbwi.position(bbwi.position() - 4);
|
|
1551 |
}
|
|
1552 |
}
|
|
1553 |
|
|
1554 |
// Makes sure that if we were reading a chunked value, we end up
|
|
1555 |
// at the right place in the stream, no matter how little the
|
|
1556 |
// unmarshalling code read.
|
|
1557 |
//
|
|
1558 |
// After calling this method, if we are chunking, we should be
|
|
1559 |
// in position to read the end tag.
|
|
1560 |
private void handleEndOfValue() {
|
|
1561 |
|
|
1562 |
// If we're not chunking, we don't have to worry about
|
|
1563 |
// skipping remaining chunks or finding end tags
|
|
1564 |
if (!isChunked)
|
|
1565 |
return;
|
|
1566 |
|
|
1567 |
// Skip any remaining chunks
|
|
1568 |
while (blockLength != maxBlockLength) {
|
|
1569 |
end_block();
|
|
1570 |
start_block();
|
|
1571 |
}
|
|
1572 |
|
|
1573 |
// Now look for the end tag
|
|
1574 |
|
|
1575 |
// This is a little wasteful since we're reading
|
|
1576 |
// this long up to 3 times in the worst cases (once
|
|
1577 |
// in start_block, once here, and once in readEndTag
|
|
1578 |
//
|
|
1579 |
// Peek next long
|
|
1580 |
int nextLong = read_long();
|
|
1581 |
bbwi.position(bbwi.position() - 4);
|
|
1582 |
|
|
1583 |
// We did find an end tag, so we're done. readEndTag
|
|
1584 |
// should take care of making sure it's the correct
|
|
1585 |
// end tag, etc. Remember that since end tags,
|
|
1586 |
// chunk lengths, and valuetags have non overlapping
|
|
1587 |
// ranges, we can tell by the value what the longs are.
|
|
1588 |
if (nextLong < 0)
|
|
1589 |
return;
|
|
1590 |
|
|
1591 |
if (nextLong == 0 || nextLong >= maxBlockLength) {
|
|
1592 |
|
|
1593 |
// A custom marshaled valuetype left extra data
|
|
1594 |
// on the wire, and that data had another
|
|
1595 |
// nested value inside of it. We've just
|
|
1596 |
// read the value tag or null of that nested value.
|
|
1597 |
//
|
|
1598 |
// In an attempt to get by it, we'll try to call
|
|
1599 |
// read_value() to get the nested value off of
|
|
1600 |
// the wire. Afterwards, we must call handleEndOfValue
|
|
1601 |
// recursively to read any further chunks that the containing
|
|
1602 |
// valuetype might still have after the nested
|
|
1603 |
// value.
|
|
1604 |
read_value();
|
|
1605 |
handleEndOfValue();
|
|
1606 |
} else {
|
|
1607 |
// This probably means that the code to skip chunks has
|
|
1608 |
// an error, and ended up setting blockLength to something
|
|
1609 |
// other than maxBlockLength even though we weren't
|
|
1610 |
// starting a new chunk.
|
|
1611 |
throw wrapper.couldNotSkipBytes( CompletionStatus.COMPLETED_MAYBE,
|
|
1612 |
new Integer( nextLong ), new Integer( get_offset() ) ) ;
|
|
1613 |
}
|
|
1614 |
}
|
|
1615 |
|
|
1616 |
private void end_block() {
|
|
1617 |
|
|
1618 |
// if in a chunk, check for underflow or overflow
|
|
1619 |
if (blockLength != maxBlockLength) {
|
|
1620 |
if (blockLength == get_offset()) {
|
|
1621 |
// Chunk ended correctly
|
|
1622 |
blockLength = maxBlockLength;
|
|
1623 |
} else {
|
|
1624 |
// Skip over anything left by bad unmarshaling code (ex:
|
|
1625 |
// a buggy custom unmarshaler). See handleEndOfValue.
|
|
1626 |
if (blockLength > get_offset()) {
|
|
1627 |
skipToOffset(blockLength);
|
|
1628 |
} else {
|
|
1629 |
throw wrapper.badChunkLength( new Integer( blockLength ),
|
|
1630 |
new Integer( get_offset() ) ) ;
|
|
1631 |
}
|
|
1632 |
}
|
|
1633 |
}
|
|
1634 |
}
|
|
1635 |
|
|
1636 |
private int readValueTag(){
|
|
1637 |
// outerValueDone = false;
|
|
1638 |
return read_long();
|
|
1639 |
}
|
|
1640 |
|
|
1641 |
public org.omg.CORBA.ORB orb() {
|
|
1642 |
return orb;
|
|
1643 |
}
|
|
1644 |
|
|
1645 |
// ------------ End RMI related methods --------------------------
|
|
1646 |
|
|
1647 |
public final void read_boolean_array(boolean[] value, int offset, int length) {
|
|
1648 |
for(int i=0; i < length; i++) {
|
|
1649 |
value[i+offset] = read_boolean();
|
|
1650 |
}
|
|
1651 |
}
|
|
1652 |
|
|
1653 |
public final void read_char_array(char[] value, int offset, int length) {
|
|
1654 |
for(int i=0; i < length; i++) {
|
|
1655 |
value[i+offset] = read_char();
|
|
1656 |
}
|
|
1657 |
}
|
|
1658 |
|
|
1659 |
public final void read_wchar_array(char[] value, int offset, int length) {
|
|
1660 |
for(int i=0; i < length; i++) {
|
|
1661 |
value[i+offset] = read_wchar();
|
|
1662 |
}
|
|
1663 |
}
|
|
1664 |
|
|
1665 |
public final void read_short_array(short[] value, int offset, int length) {
|
|
1666 |
for(int i=0; i < length; i++) {
|
|
1667 |
value[i+offset] = read_short();
|
|
1668 |
}
|
|
1669 |
}
|
|
1670 |
|
|
1671 |
public final void read_ushort_array(short[] value, int offset, int length) {
|
|
1672 |
read_short_array(value, offset, length);
|
|
1673 |
}
|
|
1674 |
|
|
1675 |
public final void read_long_array(int[] value, int offset, int length) {
|
|
1676 |
for(int i=0; i < length; i++) {
|
|
1677 |
value[i+offset] = read_long();
|
|
1678 |
}
|
|
1679 |
}
|
|
1680 |
|
|
1681 |
public final void read_ulong_array(int[] value, int offset, int length) {
|
|
1682 |
read_long_array(value, offset, length);
|
|
1683 |
}
|
|
1684 |
|
|
1685 |
public final void read_longlong_array(long[] value, int offset, int length) {
|
|
1686 |
for(int i=0; i < length; i++) {
|
|
1687 |
value[i+offset] = read_longlong();
|
|
1688 |
}
|
|
1689 |
}
|
|
1690 |
|
|
1691 |
public final void read_ulonglong_array(long[] value, int offset, int length) {
|
|
1692 |
read_longlong_array(value, offset, length);
|
|
1693 |
}
|
|
1694 |
|
|
1695 |
public final void read_float_array(float[] value, int offset, int length) {
|
|
1696 |
for(int i=0; i < length; i++) {
|
|
1697 |
value[i+offset] = read_float();
|
|
1698 |
}
|
|
1699 |
}
|
|
1700 |
|
|
1701 |
public final void read_double_array(double[] value, int offset, int length) {
|
|
1702 |
for(int i=0; i < length; i++) {
|
|
1703 |
value[i+offset] = read_double();
|
|
1704 |
}
|
|
1705 |
}
|
|
1706 |
|
|
1707 |
public final void read_any_array(org.omg.CORBA.Any[] value, int offset, int length) {
|
|
1708 |
for(int i=0; i < length; i++) {
|
|
1709 |
value[i+offset] = read_any();
|
|
1710 |
}
|
|
1711 |
}
|
|
1712 |
|
|
1713 |
//--------------------------------------------------------------------//
|
|
1714 |
// CDRInputStream state management.
|
|
1715 |
//
|
|
1716 |
|
|
1717 |
/**
|
|
1718 |
* Are we at the end of the input stream?
|
|
1719 |
*/
|
|
1720 |
// public final boolean isAtEnd() {
|
|
1721 |
// return bbwi.position() == bbwi.buflen;
|
|
1722 |
// }
|
|
1723 |
|
|
1724 |
// public int available() throws IOException {
|
|
1725 |
// return bbwi.buflen - bbwi.position();
|
|
1726 |
// }
|
|
1727 |
|
|
1728 |
private String read_repositoryIds() {
|
|
1729 |
|
|
1730 |
// Read # of repository ids
|
|
1731 |
int numRepIds = read_long();
|
|
1732 |
if (numRepIds == 0xffffffff) {
|
|
1733 |
int indirection = read_long() + get_offset() - 4;
|
|
1734 |
if (repositoryIdCache != null && repositoryIdCache.containsOrderedVal(indirection))
|
|
1735 |
return (String)repositoryIdCache.getKey(indirection);
|
|
1736 |
else
|
|
1737 |
throw wrapper.unableToLocateRepIdArray( new Integer( indirection ) ) ;
|
|
1738 |
} else {
|
|
1739 |
|
|
1740 |
// read first array element and store it as an indirection to the whole array
|
|
1741 |
int indirection = get_offset();
|
|
1742 |
String repID = read_repositoryId();
|
|
1743 |
if (repositoryIdCache == null)
|
|
1744 |
repositoryIdCache = new CacheTable(orb,false);
|
|
1745 |
repositoryIdCache.put(repID, indirection);
|
|
1746 |
|
|
1747 |
// read and ignore the subsequent array elements, but put them in the
|
|
1748 |
// indirection table in case there are later indirections back to them
|
|
1749 |
for (int i = 1; i < numRepIds; i++) {
|
|
1750 |
read_repositoryId();
|
|
1751 |
}
|
|
1752 |
|
|
1753 |
return repID;
|
|
1754 |
}
|
|
1755 |
}
|
|
1756 |
|
|
1757 |
private final String read_repositoryId()
|
|
1758 |
{
|
|
1759 |
String result = readStringOrIndirection(true);
|
|
1760 |
|
|
1761 |
if (result == null) { // Indirection
|
|
1762 |
int indirection = read_long() + get_offset() - 4;
|
|
1763 |
|
|
1764 |
if (repositoryIdCache != null && repositoryIdCache.containsOrderedVal(indirection))
|
|
1765 |
return (String)repositoryIdCache.getKey(indirection);
|
|
1766 |
else
|
|
1767 |
throw wrapper.badRepIdIndirection( CompletionStatus.COMPLETED_MAYBE,
|
|
1768 |
new Integer(bbwi.position()) ) ;
|
|
1769 |
} else {
|
|
1770 |
if (repositoryIdCache == null)
|
|
1771 |
repositoryIdCache = new CacheTable(orb,false);
|
|
1772 |
repositoryIdCache.put(result, stringIndirection);
|
|
1773 |
}
|
|
1774 |
|
|
1775 |
return result ;
|
|
1776 |
}
|
|
1777 |
|
|
1778 |
private final String read_codebase_URL()
|
|
1779 |
{
|
|
1780 |
String result = readStringOrIndirection(true);
|
|
1781 |
|
|
1782 |
if (result == null) { // Indirection
|
|
1783 |
int indirection = read_long() + get_offset() - 4;
|
|
1784 |
|
|
1785 |
if (codebaseCache != null && codebaseCache.containsVal(indirection))
|
|
1786 |
return (String)codebaseCache.getKey(indirection);
|
|
1787 |
else
|
|
1788 |
throw wrapper.badCodebaseIndirection(
|
|
1789 |
CompletionStatus.COMPLETED_MAYBE,
|
|
1790 |
new Integer(bbwi.position()) ) ;
|
|
1791 |
} else {
|
|
1792 |
if (codebaseCache == null)
|
|
1793 |
codebaseCache = new CacheTable(orb,false);
|
|
1794 |
codebaseCache.put(result, stringIndirection);
|
|
1795 |
}
|
|
1796 |
|
|
1797 |
return result;
|
|
1798 |
}
|
|
1799 |
|
|
1800 |
/* DataInputStream methods */
|
|
1801 |
|
|
1802 |
public java.lang.Object read_Abstract () {
|
|
1803 |
return read_abstract_interface();
|
|
1804 |
}
|
|
1805 |
|
|
1806 |
public java.io.Serializable read_Value () {
|
|
1807 |
return read_value();
|
|
1808 |
}
|
|
1809 |
|
|
1810 |
public void read_any_array (org.omg.CORBA.AnySeqHolder seq, int offset, int length) {
|
|
1811 |
read_any_array(seq.value, offset, length);
|
|
1812 |
}
|
|
1813 |
|
|
1814 |
public void read_boolean_array (org.omg.CORBA.BooleanSeqHolder seq, int offset, int length) {
|
|
1815 |
read_boolean_array(seq.value, offset, length);
|
|
1816 |
}
|
|
1817 |
|
|
1818 |
public void read_char_array (org.omg.CORBA.CharSeqHolder seq, int offset, int length) {
|
|
1819 |
read_char_array(seq.value, offset, length);
|
|
1820 |
}
|
|
1821 |
|
|
1822 |
public void read_wchar_array (org.omg.CORBA.WCharSeqHolder seq, int offset, int length) {
|
|
1823 |
read_wchar_array(seq.value, offset, length);
|
|
1824 |
}
|
|
1825 |
|
|
1826 |
public void read_octet_array (org.omg.CORBA.OctetSeqHolder seq, int offset, int length) {
|
|
1827 |
read_octet_array(seq.value, offset, length);
|
|
1828 |
}
|
|
1829 |
|
|
1830 |
public void read_short_array (org.omg.CORBA.ShortSeqHolder seq, int offset, int length) {
|
|
1831 |
read_short_array(seq.value, offset, length);
|
|
1832 |
}
|
|
1833 |
|
|
1834 |
public void read_ushort_array (org.omg.CORBA.UShortSeqHolder seq, int offset, int length) {
|
|
1835 |
read_ushort_array(seq.value, offset, length);
|
|
1836 |
}
|
|
1837 |
|
|
1838 |
public void read_long_array (org.omg.CORBA.LongSeqHolder seq, int offset, int length) {
|
|
1839 |
read_long_array(seq.value, offset, length);
|
|
1840 |
}
|
|
1841 |
|
|
1842 |
public void read_ulong_array (org.omg.CORBA.ULongSeqHolder seq, int offset, int length) {
|
|
1843 |
read_ulong_array(seq.value, offset, length);
|
|
1844 |
}
|
|
1845 |
|
|
1846 |
public void read_ulonglong_array (org.omg.CORBA.ULongLongSeqHolder seq, int offset, int length) {
|
|
1847 |
read_ulonglong_array(seq.value, offset, length);
|
|
1848 |
}
|
|
1849 |
|
|
1850 |
public void read_longlong_array (org.omg.CORBA.LongLongSeqHolder seq, int offset, int length) {
|
|
1851 |
read_longlong_array(seq.value, offset, length);
|
|
1852 |
}
|
|
1853 |
|
|
1854 |
public void read_float_array (org.omg.CORBA.FloatSeqHolder seq, int offset, int length) {
|
|
1855 |
read_float_array(seq.value, offset, length);
|
|
1856 |
}
|
|
1857 |
|
|
1858 |
public void read_double_array (org.omg.CORBA.DoubleSeqHolder seq, int offset, int length) {
|
|
1859 |
read_double_array(seq.value, offset, length);
|
|
1860 |
}
|
|
1861 |
|
|
1862 |
public java.math.BigDecimal read_fixed(short digits, short scale) {
|
|
1863 |
// digits isn't really needed here
|
|
1864 |
StringBuffer buffer = read_fixed_buffer();
|
|
1865 |
if (digits != buffer.length())
|
|
1866 |
throw wrapper.badFixed( new Integer(digits),
|
|
1867 |
new Integer(buffer.length()) ) ;
|
|
1868 |
buffer.insert(digits - scale, '.');
|
|
1869 |
return new BigDecimal(buffer.toString());
|
|
1870 |
}
|
|
1871 |
|
|
1872 |
// This method is unable to yield the correct scale.
|
|
1873 |
public java.math.BigDecimal read_fixed() {
|
|
1874 |
return new BigDecimal(read_fixed_buffer().toString());
|
|
1875 |
}
|
|
1876 |
|
|
1877 |
// Each octet contains (up to) two decimal digits.
|
|
1878 |
// If the fixed type has an odd number of decimal digits, then the representation
|
|
1879 |
// begins with the first (most significant) digit.
|
|
1880 |
// Otherwise, this first half-octet is all zero, and the first digit
|
|
1881 |
// is in the second half-octet.
|
|
1882 |
// The sign configuration, in the last half-octet of the representation,
|
|
1883 |
// is 0xD for negative numbers and 0xC for positive and zero values.
|
|
1884 |
private StringBuffer read_fixed_buffer() {
|
|
1885 |
StringBuffer buffer = new StringBuffer(64);
|
|
1886 |
byte doubleDigit;
|
|
1887 |
int firstDigit;
|
|
1888 |
int secondDigit;
|
|
1889 |
boolean wroteFirstDigit = false;
|
|
1890 |
boolean more = true;
|
|
1891 |
while (more) {
|
|
1892 |
doubleDigit = this.read_octet();
|
|
1893 |
firstDigit = (int)((doubleDigit & 0xf0) >> 4);
|
|
1894 |
secondDigit = (int)(doubleDigit & 0x0f);
|
|
1895 |
if (wroteFirstDigit || firstDigit != 0) {
|
|
1896 |
buffer.append(Character.forDigit(firstDigit, 10));
|
|
1897 |
wroteFirstDigit = true;
|
|
1898 |
}
|
|
1899 |
if (secondDigit == 12) {
|
|
1900 |
// positive number or zero
|
|
1901 |
if ( ! wroteFirstDigit) {
|
|
1902 |
// zero
|
|
1903 |
return new StringBuffer("0.0");
|
|
1904 |
} else {
|
|
1905 |
// positive number
|
|
1906 |
// done
|
|
1907 |
}
|
|
1908 |
more = false;
|
|
1909 |
} else if (secondDigit == 13) {
|
|
1910 |
// negative number
|
|
1911 |
buffer.insert(0, '-');
|
|
1912 |
more = false;
|
|
1913 |
} else {
|
|
1914 |
buffer.append(Character.forDigit(secondDigit, 10));
|
|
1915 |
wroteFirstDigit = true;
|
|
1916 |
}
|
|
1917 |
}
|
|
1918 |
return buffer;
|
|
1919 |
}
|
|
1920 |
|
|
1921 |
private final static String _id = "IDL:omg.org/CORBA/DataInputStream:1.0";
|
|
1922 |
private final static String[] _ids = { _id };
|
|
1923 |
|
|
1924 |
public String[] _truncatable_ids() {
|
|
1925 |
if (_ids == null)
|
|
1926 |
return null;
|
|
1927 |
|
|
1928 |
return (String[])_ids.clone();
|
|
1929 |
}
|
|
1930 |
|
|
1931 |
/* for debugging */
|
|
1932 |
|
|
1933 |
public void printBuffer() {
|
|
1934 |
CDRInputStream_1_0.printBuffer(this.bbwi);
|
|
1935 |
}
|
|
1936 |
|
|
1937 |
public static void printBuffer(ByteBufferWithInfo bbwi) {
|
|
1938 |
|
|
1939 |
System.out.println("----- Input Buffer -----");
|
|
1940 |
System.out.println();
|
|
1941 |
System.out.println("Current position: " + bbwi.position());
|
|
1942 |
System.out.println("Total length : " + bbwi.buflen);
|
|
1943 |
System.out.println();
|
|
1944 |
|
|
1945 |
try {
|
|
1946 |
|
|
1947 |
char[] charBuf = new char[16];
|
|
1948 |
|
|
1949 |
for (int i = 0; i < bbwi.buflen; i += 16) {
|
|
1950 |
|
|
1951 |
int j = 0;
|
|
1952 |
|
|
1953 |
// For every 16 bytes, there is one line
|
|
1954 |
// of output. First, the hex output of
|
|
1955 |
// the 16 bytes with each byte separated
|
|
1956 |
// by a space.
|
|
1957 |
while (j < 16 && j + i < bbwi.buflen) {
|
|
1958 |
int k = bbwi.byteBuffer.get(i + j);
|
|
1959 |
if (k < 0)
|
|
1960 |
k = 256 + k;
|
|
1961 |
String hex = Integer.toHexString(k);
|
|
1962 |
if (hex.length() == 1)
|
|
1963 |
hex = "0" + hex;
|
|
1964 |
System.out.print(hex + " ");
|
|
1965 |
j++;
|
|
1966 |
}
|
|
1967 |
|
|
1968 |
// Add any extra spaces to align the
|
|
1969 |
// text column in case we didn't end
|
|
1970 |
// at 16
|
|
1971 |
while (j < 16) {
|
|
1972 |
System.out.print(" ");
|
|
1973 |
j++;
|
|
1974 |
}
|
|
1975 |
|
|
1976 |
// Now output the ASCII equivalents. Non-ASCII
|
|
1977 |
// characters are shown as periods.
|
|
1978 |
int x = 0;
|
|
1979 |
while (x < 16 && x + i < bbwi.buflen) {
|
|
1980 |
if (ORBUtility.isPrintable((char)bbwi.byteBuffer.get(i + x)))
|
|
1981 |
charBuf[x] = (char)bbwi.byteBuffer.get(i + x);
|
|
1982 |
else
|
|
1983 |
charBuf[x] = '.';
|
|
1984 |
x++;
|
|
1985 |
}
|
|
1986 |
System.out.println(new String(charBuf, 0, x));
|
|
1987 |
}
|
|
1988 |
|
|
1989 |
} catch (Throwable t) {
|
|
1990 |
t.printStackTrace();
|
|
1991 |
}
|
|
1992 |
|
|
1993 |
System.out.println("------------------------");
|
|
1994 |
}
|
|
1995 |
|
|
1996 |
public ByteBuffer getByteBuffer() {
|
|
1997 |
ByteBuffer result = null;
|
|
1998 |
if (bbwi != null) {
|
|
1999 |
result = bbwi.byteBuffer;
|
|
2000 |
}
|
|
2001 |
return result;
|
|
2002 |
}
|
|
2003 |
|
|
2004 |
public int getBufferLength() {
|
|
2005 |
return bbwi.buflen;
|
|
2006 |
}
|
|
2007 |
|
|
2008 |
public void setBufferLength(int value) {
|
|
2009 |
bbwi.buflen = value;
|
|
2010 |
bbwi.byteBuffer.limit(bbwi.buflen);
|
|
2011 |
}
|
|
2012 |
|
|
2013 |
public void setByteBufferWithInfo(ByteBufferWithInfo bbwi) {
|
|
2014 |
this.bbwi = bbwi;
|
|
2015 |
}
|
|
2016 |
|
|
2017 |
public void setByteBuffer(ByteBuffer byteBuffer) {
|
|
2018 |
bbwi.byteBuffer = byteBuffer;
|
|
2019 |
}
|
|
2020 |
|
|
2021 |
public int getIndex() {
|
|
2022 |
return bbwi.position();
|
|
2023 |
}
|
|
2024 |
|
|
2025 |
public void setIndex(int value) {
|
|
2026 |
bbwi.position(value);
|
|
2027 |
}
|
|
2028 |
|
|
2029 |
public boolean isLittleEndian() {
|
|
2030 |
return littleEndian;
|
|
2031 |
}
|
|
2032 |
|
|
2033 |
public void orb(org.omg.CORBA.ORB orb) {
|
|
2034 |
this.orb = (ORB)orb;
|
|
2035 |
}
|
|
2036 |
|
|
2037 |
public BufferManagerRead getBufferManager() {
|
|
2038 |
return bufferManagerRead;
|
|
2039 |
}
|
|
2040 |
|
|
2041 |
private void skipToOffset(int offset) {
|
|
2042 |
|
|
2043 |
// Number of bytes to skip
|
|
2044 |
int len = offset - get_offset();
|
|
2045 |
|
|
2046 |
int n = 0;
|
|
2047 |
|
|
2048 |
while (n < len) {
|
|
2049 |
int avail;
|
|
2050 |
int bytes;
|
|
2051 |
int wanted;
|
|
2052 |
|
|
2053 |
avail = bbwi.buflen - bbwi.position();
|
|
2054 |
if (avail <= 0) {
|
|
2055 |
grow(1, 1);
|
|
2056 |
avail = bbwi.buflen - bbwi.position();
|
|
2057 |
}
|
|
2058 |
|
|
2059 |
wanted = len - n;
|
|
2060 |
bytes = (wanted < avail) ? wanted : avail;
|
|
2061 |
bbwi.position(bbwi.position() + bytes);
|
|
2062 |
n += bytes;
|
|
2063 |
}
|
|
2064 |
}
|
|
2065 |
|
|
2066 |
|
|
2067 |
// Mark and reset -------------------------------------------------
|
|
2068 |
|
|
2069 |
protected MarkAndResetHandler markAndResetHandler = null;
|
|
2070 |
|
|
2071 |
protected class StreamMemento
|
|
2072 |
{
|
|
2073 |
// These are the fields that may change after marking
|
|
2074 |
// the stream position, so we need to save them.
|
|
2075 |
private int blockLength_;
|
|
2076 |
private int end_flag_;
|
|
2077 |
private int chunkedValueNestingLevel_;
|
|
2078 |
private int valueIndirection_;
|
|
2079 |
private int stringIndirection_;
|
|
2080 |
private boolean isChunked_;
|
|
2081 |
private javax.rmi.CORBA.ValueHandler valueHandler_;
|
|
2082 |
private ByteBufferWithInfo bbwi_;
|
|
2083 |
private boolean specialNoOptionalDataState_;
|
|
2084 |
|
|
2085 |
public StreamMemento()
|
|
2086 |
{
|
|
2087 |
blockLength_ = blockLength;
|
|
2088 |
end_flag_ = end_flag;
|
|
2089 |
chunkedValueNestingLevel_ = chunkedValueNestingLevel;
|
|
2090 |
valueIndirection_ = valueIndirection;
|
|
2091 |
stringIndirection_ = stringIndirection;
|
|
2092 |
isChunked_ = isChunked;
|
|
2093 |
valueHandler_ = valueHandler;
|
|
2094 |
specialNoOptionalDataState_ = specialNoOptionalDataState;
|
|
2095 |
bbwi_ = new ByteBufferWithInfo(bbwi);
|
|
2096 |
}
|
|
2097 |
}
|
|
2098 |
|
|
2099 |
public java.lang.Object createStreamMemento() {
|
|
2100 |
return new StreamMemento();
|
|
2101 |
}
|
|
2102 |
|
|
2103 |
public void restoreInternalState(java.lang.Object streamMemento) {
|
|
2104 |
|
|
2105 |
StreamMemento mem = (StreamMemento)streamMemento;
|
|
2106 |
|
|
2107 |
blockLength = mem.blockLength_;
|
|
2108 |
end_flag = mem.end_flag_;
|
|
2109 |
chunkedValueNestingLevel = mem.chunkedValueNestingLevel_;
|
|
2110 |
valueIndirection = mem.valueIndirection_;
|
|
2111 |
stringIndirection = mem.stringIndirection_;
|
|
2112 |
isChunked = mem.isChunked_;
|
|
2113 |
valueHandler = mem.valueHandler_;
|
|
2114 |
specialNoOptionalDataState = mem.specialNoOptionalDataState_;
|
|
2115 |
bbwi = mem.bbwi_;
|
|
2116 |
}
|
|
2117 |
|
|
2118 |
public int getPosition() {
|
|
2119 |
return get_offset();
|
|
2120 |
}
|
|
2121 |
|
|
2122 |
public void mark(int readlimit) {
|
|
2123 |
markAndResetHandler.mark(this);
|
|
2124 |
}
|
|
2125 |
|
|
2126 |
public void reset() {
|
|
2127 |
markAndResetHandler.reset();
|
|
2128 |
}
|
|
2129 |
|
|
2130 |
// ---------------------------------- end Mark and Reset
|
|
2131 |
|
|
2132 |
// Provides a hook so subclasses of CDRInputStream can provide
|
|
2133 |
// a CodeBase. This ultimately allows us to grab a Connection
|
|
2134 |
// instance in IIOPInputStream, the only subclass where this
|
|
2135 |
// is actually used.
|
|
2136 |
CodeBase getCodeBase() {
|
|
2137 |
return parent.getCodeBase();
|
|
2138 |
}
|
|
2139 |
|
|
2140 |
/**
|
|
2141 |
* Attempts to find the class described by the given
|
|
2142 |
* repository ID string and expected type. The first
|
|
2143 |
* attempt is to find the class locally, falling back
|
|
2144 |
* on the URL that came with the value. The second
|
|
2145 |
* attempt is to use a URL from the remote CodeBase.
|
|
2146 |
*/
|
|
2147 |
private Class getClassFromString(String repositoryIDString,
|
|
2148 |
String codebaseURL,
|
|
2149 |
Class expectedType)
|
|
2150 |
{
|
|
2151 |
RepositoryIdInterface repositoryID
|
|
2152 |
= repIdStrs.getFromString(repositoryIDString);
|
|
2153 |
|
|
2154 |
try {
|
|
2155 |
try {
|
|
2156 |
// First try to load the class locally, then use
|
|
2157 |
// the provided URL (if it isn't null)
|
|
2158 |
return repositoryID.getClassFromType(expectedType,
|
|
2159 |
codebaseURL);
|
|
2160 |
} catch (ClassNotFoundException cnfeOuter) {
|
|
2161 |
|
|
2162 |
try {
|
|
2163 |
|
|
2164 |
if (getCodeBase() == null) {
|
|
2165 |
return null; // class cannot be loaded remotely.
|
|
2166 |
}
|
|
2167 |
|
|
2168 |
// Get a URL from the remote CodeBase and retry
|
|
2169 |
codebaseURL = getCodeBase().implementation(repositoryIDString);
|
|
2170 |
|
|
2171 |
// Don't bother trying to find it locally again if
|
|
2172 |
// we got a null URL
|
|
2173 |
if (codebaseURL == null)
|
|
2174 |
return null;
|
|
2175 |
|
|
2176 |
return repositoryID.getClassFromType(expectedType,
|
|
2177 |
codebaseURL);
|
|
2178 |
} catch (ClassNotFoundException cnfeInner) {
|
|
2179 |
dprintThrowable(cnfeInner);
|
|
2180 |
// Failed to load the class
|
|
2181 |
return null;
|
|
2182 |
}
|
|
2183 |
}
|
|
2184 |
} catch (MalformedURLException mue) {
|
|
2185 |
// Always report a bad URL
|
|
2186 |
throw wrapper.malformedUrl( CompletionStatus.COMPLETED_MAYBE,
|
|
2187 |
mue, repositoryIDString, codebaseURL ) ;
|
|
2188 |
}
|
|
2189 |
}
|
|
2190 |
|
|
2191 |
/**
|
|
2192 |
* Attempts to find the class described by the given
|
|
2193 |
* repository ID string. At most, three attempts are made:
|
|
2194 |
* Try to find it locally, through the provided URL, and
|
|
2195 |
* finally, via a URL from the remote CodeBase.
|
|
2196 |
*/
|
|
2197 |
private Class getClassFromString(String repositoryIDString,
|
|
2198 |
String codebaseURL)
|
|
2199 |
{
|
|
2200 |
RepositoryIdInterface repositoryID
|
|
2201 |
= repIdStrs.getFromString(repositoryIDString);
|
|
2202 |
|
|
2203 |
for (int i = 0; i < 3; i++) {
|
|
2204 |
|
|
2205 |
try {
|
|
2206 |
|
|
2207 |
switch (i)
|
|
2208 |
{
|
|
2209 |
case 0:
|
|
2210 |
// First try to load the class locally
|
|
2211 |
return repositoryID.getClassFromType();
|
|
2212 |
case 1:
|
|
2213 |
// Try to load the class using the provided
|
|
2214 |
// codebase URL (falls out below)
|
|
2215 |
break;
|
|
2216 |
case 2:
|
|
2217 |
// Try to load the class using a URL from the
|
|
2218 |
// remote CodeBase
|
|
2219 |
codebaseURL = getCodeBase().implementation(repositoryIDString);
|
|
2220 |
break;
|
|
2221 |
}
|
|
2222 |
|
|
2223 |
// Don't bother if the codebaseURL is null
|
|
2224 |
if (codebaseURL == null)
|
|
2225 |
continue;
|
|
2226 |
|
|
2227 |
return repositoryID.getClassFromType(codebaseURL);
|
|
2228 |
|
|
2229 |
} catch(ClassNotFoundException cnfe) {
|
|
2230 |
// Will ultimately return null if all three
|
|
2231 |
// attempts fail, but don't do anything here.
|
|
2232 |
} catch (MalformedURLException mue) {
|
|
2233 |
throw wrapper.malformedUrl( CompletionStatus.COMPLETED_MAYBE,
|
|
2234 |
mue, repositoryIDString, codebaseURL ) ;
|
|
2235 |
}
|
|
2236 |
}
|
|
2237 |
|
|
2238 |
// If we get here, we have failed to load the class
|
|
2239 |
dprint("getClassFromString failed with rep id "
|
|
2240 |
+ repositoryIDString
|
|
2241 |
+ " and codebase "
|
|
2242 |
+ codebaseURL);
|
|
2243 |
|
|
2244 |
return null;
|
|
2245 |
}
|
|
2246 |
|
|
2247 |
// Utility method used to get chars from bytes
|
|
2248 |
char[] getConvertedChars(int numBytes,
|
|
2249 |
CodeSetConversion.BTCConverter converter) {
|
|
2250 |
|
|
2251 |
// REVISIT - Look at CodeSetConversion.BTCConverter to see
|
|
2252 |
// if it can work with an NIO ByteBuffer. We should
|
|
2253 |
// avoid getting the bytes into an array if possible.
|
|
2254 |
|
|
2255 |
// To be honest, I doubt this saves much real time
|
|
2256 |
if (bbwi.buflen - bbwi.position() >= numBytes) {
|
|
2257 |
// If the entire string is in this buffer,
|
|
2258 |
// just convert directly from the bbwi rather than
|
|
2259 |
// allocating and copying.
|
|
2260 |
byte[] tmpBuf;
|
|
2261 |
if (bbwi.byteBuffer.hasArray())
|
|
2262 |
{
|
|
2263 |
tmpBuf = bbwi.byteBuffer.array();
|
|
2264 |
}
|
|
2265 |
else
|
|
2266 |
{
|
|
2267 |
tmpBuf = new byte[bbwi.buflen];
|
|
2268 |
// Microbenchmarks are showing a loop of ByteBuffer.get(int)
|
|
2269 |
// being faster than ByteBuffer.get(byte[], int, int).
|
|
2270 |
for (int i = 0; i < bbwi.buflen; i++)
|
|
2271 |
tmpBuf[i] = bbwi.byteBuffer.get(i);
|
|
2272 |
}
|
|
2273 |
char[] result = converter.getChars(tmpBuf,bbwi.position(),numBytes);
|
|
2274 |
|
|
2275 |
bbwi.position(bbwi.position() + numBytes);
|
|
2276 |
return result;
|
|
2277 |
} else {
|
|
2278 |
// Stretches across buffers. Unless we provide an
|
|
2279 |
// incremental conversion interface, allocate and
|
|
2280 |
// copy the bytes.
|
|
2281 |
byte[] bytes = new byte[numBytes];
|
|
2282 |
read_octet_array(bytes, 0, bytes.length);
|
|
2283 |
|
|
2284 |
return converter.getChars(bytes, 0, numBytes);
|
|
2285 |
}
|
|
2286 |
}
|
|
2287 |
|
|
2288 |
protected CodeSetConversion.BTCConverter getCharConverter() {
|
|
2289 |
if (charConverter == null)
|
|
2290 |
charConverter = parent.createCharBTCConverter();
|
|
2291 |
|
|
2292 |
return charConverter;
|
|
2293 |
}
|
|
2294 |
|
|
2295 |
protected CodeSetConversion.BTCConverter getWCharConverter() {
|
|
2296 |
if (wcharConverter == null)
|
|
2297 |
wcharConverter = parent.createWCharBTCConverter();
|
|
2298 |
|
|
2299 |
return wcharConverter;
|
|
2300 |
}
|
|
2301 |
|
|
2302 |
protected void dprintThrowable(Throwable t) {
|
|
2303 |
if (debug && t != null)
|
|
2304 |
t.printStackTrace();
|
|
2305 |
}
|
|
2306 |
|
|
2307 |
protected void dprint(String msg) {
|
|
2308 |
if (debug) {
|
|
2309 |
ORBUtility.dprint(this, msg);
|
|
2310 |
}
|
|
2311 |
}
|
|
2312 |
|
|
2313 |
/**
|
|
2314 |
* Aligns the current position on the given octet boundary
|
|
2315 |
* if there are enough bytes available to do so. Otherwise,
|
|
2316 |
* it just returns. This is used for some (but not all)
|
|
2317 |
* GIOP 1.2 message headers.
|
|
2318 |
*/
|
|
2319 |
|
|
2320 |
void alignOnBoundary(int octetBoundary) {
|
|
2321 |
int needed = computeAlignment(bbwi.position(), octetBoundary);
|
|
2322 |
|
|
2323 |
if (bbwi.position() + needed <= bbwi.buflen)
|
|
2324 |
{
|
|
2325 |
bbwi.position(bbwi.position() + needed);
|
|
2326 |
}
|
|
2327 |
}
|
|
2328 |
|
|
2329 |
public void resetCodeSetConverters() {
|
|
2330 |
charConverter = null;
|
|
2331 |
wcharConverter = null;
|
|
2332 |
}
|
|
2333 |
|
|
2334 |
public void start_value() {
|
|
2335 |
// Read value tag
|
|
2336 |
int vType = readValueTag();
|
|
2337 |
|
|
2338 |
if (vType == 0) {
|
|
2339 |
// Stream needs to go into a state where it
|
|
2340 |
// throws standard exception until end_value
|
|
2341 |
// is called. This means the sender didn't
|
|
2342 |
// send any custom data. If the reader here
|
|
2343 |
// tries to read more, we need to throw an
|
|
2344 |
// exception before reading beyond where
|
|
2345 |
// we're supposed to
|
|
2346 |
specialNoOptionalDataState = true;
|
|
2347 |
|
|
2348 |
return;
|
|
2349 |
}
|
|
2350 |
|
|
2351 |
if (vType == 0xffffffff) {
|
|
2352 |
// One should never indirect to a custom wrapper
|
|
2353 |
throw wrapper.customWrapperIndirection(
|
|
2354 |
CompletionStatus.COMPLETED_MAYBE);
|
|
2355 |
}
|
|
2356 |
|
|
2357 |
if (repIdUtil.isCodeBasePresent(vType)) {
|
|
2358 |
throw wrapper.customWrapperWithCodebase(
|
|
2359 |
CompletionStatus.COMPLETED_MAYBE);
|
|
2360 |
}
|
|
2361 |
|
|
2362 |
if (repIdUtil.getTypeInfo(vType)
|
|
2363 |
!= RepositoryIdUtility.SINGLE_REP_TYPE_INFO) {
|
|
2364 |
throw wrapper.customWrapperNotSingleRepid(
|
|
2365 |
CompletionStatus.COMPLETED_MAYBE);
|
|
2366 |
}
|
|
2367 |
|
|
2368 |
|
|
2369 |
// REVISIT - Could verify repository ID even though
|
|
2370 |
// it isn't used elsewhere
|
|
2371 |
read_repositoryId();
|
|
2372 |
|
|
2373 |
// Note: isChunked should be true here. Should have
|
|
2374 |
// been set to true in the containing value's read_value
|
|
2375 |
// method.
|
|
2376 |
|
|
2377 |
start_block();
|
|
2378 |
end_flag--;
|
|
2379 |
chunkedValueNestingLevel--;
|
|
2380 |
}
|
|
2381 |
|
|
2382 |
public void end_value() {
|
|
2383 |
|
|
2384 |
if (specialNoOptionalDataState) {
|
|
2385 |
specialNoOptionalDataState = false;
|
|
2386 |
return;
|
|
2387 |
}
|
|
2388 |
|
|
2389 |
handleEndOfValue();
|
|
2390 |
readEndTag();
|
|
2391 |
|
|
2392 |
// Note that isChunked should still be true here.
|
|
2393 |
// If the containing valuetype is the highest
|
|
2394 |
// chunked value, it will get set to false
|
|
2395 |
// at the end of read_value.
|
|
2396 |
|
|
2397 |
// allow for possible continuation chunk
|
|
2398 |
start_block();
|
|
2399 |
}
|
|
2400 |
|
|
2401 |
public void close() throws IOException
|
|
2402 |
{
|
|
2403 |
|
|
2404 |
// tell BufferManagerRead to release any ByteBuffers
|
|
2405 |
getBufferManager().close(bbwi);
|
|
2406 |
|
|
2407 |
// It's possible bbwi.byteBuffer is shared between
|
|
2408 |
// this InputStream and an OutputStream. Thus, we check
|
|
2409 |
// if the Input/Output streams are using the same ByteBuffer.
|
|
2410 |
// If they sharing the same ByteBuffer we need to ensure only
|
|
2411 |
// one of those ByteBuffers are released to the ByteBufferPool.
|
|
2412 |
|
|
2413 |
if (bbwi != null && getByteBuffer() != null)
|
|
2414 |
{
|
|
2415 |
int bbHash = System.identityHashCode(bbwi.byteBuffer);
|
|
2416 |
MessageMediator messageMediator = parent.getMessageMediator();
|
|
2417 |
if (messageMediator != null)
|
|
2418 |
{
|
|
2419 |
CDROutputObject outputObj =
|
|
2420 |
(CDROutputObject)messageMediator.getOutputObject();
|
|
2421 |
if (outputObj != null)
|
|
2422 |
{
|
|
2423 |
ByteBuffer outputBb = outputObj.getByteBuffer();
|
|
2424 |
|
|
2425 |
int oBbHash = 0;
|
|
2426 |
if (outputBb != null)
|
|
2427 |
{
|
|
2428 |
oBbHash = System.identityHashCode(outputBb);
|
|
2429 |
if (bbHash == oBbHash) // shared?
|
|
2430 |
{
|
|
2431 |
// Set OutputStream's ByteBuffer and bbwi to null
|
|
2432 |
// so its ByteBuffer cannot be released to the pool
|
|
2433 |
outputObj.setByteBuffer(null);
|
|
2434 |
outputObj.setByteBufferWithInfo(null);
|
|
2435 |
}
|
|
2436 |
}
|
|
2437 |
}
|
|
2438 |
}
|
|
2439 |
|
|
2440 |
// release this stream's ByteBuffer to the pool
|
|
2441 |
ByteBufferPool byteBufferPool = orb.getByteBufferPool();
|
|
2442 |
if (debug)
|
|
2443 |
{
|
|
2444 |
// print address of ByteBuffer being released
|
|
2445 |
int bbAddress = System.identityHashCode(bbwi.byteBuffer);
|
|
2446 |
StringBuffer sb = new StringBuffer(80);
|
|
2447 |
sb.append(".close - releasing ByteBuffer id (");
|
|
2448 |
sb.append(bbAddress).append(") to ByteBufferPool.");
|
|
2449 |
String msg = sb.toString();
|
|
2450 |
dprint(msg);
|
|
2451 |
}
|
|
2452 |
byteBufferPool.releaseByteBuffer(bbwi.byteBuffer);
|
|
2453 |
bbwi.byteBuffer = null;
|
|
2454 |
bbwi = null;
|
|
2455 |
}
|
|
2456 |
}
|
|
2457 |
}
|