4
|
1 |
/*
|
5555
|
2 |
* Copyright (c) 1999, 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 |
package com.sun.corba.se.spi.servicecontext;
|
|
27 |
|
|
28 |
import java.lang.reflect.InvocationTargetException ;
|
|
29 |
import java.lang.reflect.Modifier ;
|
|
30 |
import java.lang.reflect.Field ;
|
|
31 |
import java.lang.reflect.Constructor ;
|
|
32 |
import java.util.*;
|
|
33 |
|
|
34 |
import org.omg.CORBA.OctetSeqHelper;
|
|
35 |
import org.omg.CORBA.SystemException;
|
|
36 |
import org.omg.CORBA.INTERNAL;
|
|
37 |
import org.omg.CORBA.CompletionStatus;
|
|
38 |
import org.omg.CORBA_2_3.portable.OutputStream ;
|
|
39 |
import org.omg.CORBA_2_3.portable.InputStream ;
|
|
40 |
|
|
41 |
import com.sun.org.omg.SendingContext.CodeBase;
|
|
42 |
|
|
43 |
import com.sun.corba.se.spi.ior.iiop.GIOPVersion;
|
|
44 |
|
|
45 |
import com.sun.corba.se.spi.orb.ORB ;
|
|
46 |
|
|
47 |
import com.sun.corba.se.spi.logging.CORBALogDomains;
|
|
48 |
|
|
49 |
|
|
50 |
import com.sun.corba.se.spi.servicecontext.ServiceContext ;
|
|
51 |
import com.sun.corba.se.spi.servicecontext.ServiceContextRegistry ;
|
|
52 |
import com.sun.corba.se.spi.servicecontext.ServiceContextData ;
|
|
53 |
import com.sun.corba.se.spi.servicecontext.UnknownServiceContext ;
|
|
54 |
|
|
55 |
import com.sun.corba.se.impl.encoding.CDRInputStream;
|
|
56 |
import com.sun.corba.se.impl.encoding.EncapsInputStream ;
|
|
57 |
import com.sun.corba.se.impl.orbutil.ORBUtility ;
|
|
58 |
import com.sun.corba.se.impl.util.Utility ;
|
|
59 |
import com.sun.corba.se.impl.logging.ORBUtilSystemException ;
|
|
60 |
|
|
61 |
public class ServiceContexts {
|
|
62 |
private static boolean isDebugging( OutputStream os )
|
|
63 |
{
|
|
64 |
ORB orb = (ORB)(os.orb()) ;
|
|
65 |
if (orb==null)
|
|
66 |
return false ;
|
|
67 |
return orb.serviceContextDebugFlag ;
|
|
68 |
}
|
|
69 |
|
|
70 |
private static boolean isDebugging( InputStream is )
|
|
71 |
{
|
|
72 |
ORB orb = (ORB)(is.orb()) ;
|
|
73 |
if (orb==null)
|
|
74 |
return false ;
|
|
75 |
return orb.serviceContextDebugFlag ;
|
|
76 |
}
|
|
77 |
|
|
78 |
private void dprint( String msg )
|
|
79 |
{
|
|
80 |
ORBUtility.dprint( this, msg ) ;
|
|
81 |
}
|
|
82 |
|
|
83 |
public static void writeNullServiceContext( OutputStream os )
|
|
84 |
{
|
|
85 |
if (isDebugging(os))
|
|
86 |
ORBUtility.dprint( "ServiceContexts", "Writing null service context" ) ;
|
|
87 |
os.write_long( 0 ) ;
|
|
88 |
}
|
|
89 |
|
|
90 |
/**
|
|
91 |
* Given the input stream, this fills our service
|
|
92 |
* context map. See the definition of scMap for
|
|
93 |
* details. Creates a HashMap.
|
|
94 |
*
|
|
95 |
* Note that we don't actually unmarshal the
|
|
96 |
* bytes of the service contexts here. That is
|
|
97 |
* done when they are actually requested via
|
|
98 |
* get(int).
|
|
99 |
*/
|
|
100 |
private void createMapFromInputStream(InputStream is)
|
|
101 |
{
|
|
102 |
orb = (ORB)(is.orb()) ;
|
|
103 |
if (orb.serviceContextDebugFlag)
|
|
104 |
dprint( "Constructing ServiceContexts from input stream" ) ;
|
|
105 |
|
|
106 |
int numValid = is.read_long() ;
|
|
107 |
|
|
108 |
if (orb.serviceContextDebugFlag)
|
|
109 |
dprint("Number of service contexts = " + numValid);
|
|
110 |
|
|
111 |
for (int ctr = 0; ctr < numValid; ctr++) {
|
|
112 |
int scId = is.read_long();
|
|
113 |
|
|
114 |
if (orb.serviceContextDebugFlag)
|
|
115 |
dprint("Reading service context id " + scId);
|
|
116 |
|
|
117 |
byte[] data = OctetSeqHelper.read(is);
|
|
118 |
|
|
119 |
if (orb.serviceContextDebugFlag)
|
|
120 |
dprint("Service context" + scId + " length: " + data.length);
|
|
121 |
|
|
122 |
scMap.put(new Integer(scId), data);
|
|
123 |
}
|
|
124 |
}
|
|
125 |
|
|
126 |
public ServiceContexts( ORB orb )
|
|
127 |
{
|
|
128 |
this.orb = orb ;
|
|
129 |
wrapper = ORBUtilSystemException.get( orb,
|
|
130 |
CORBALogDomains.RPC_PROTOCOL ) ;
|
|
131 |
|
|
132 |
addAlignmentOnWrite = false ;
|
|
133 |
|
|
134 |
scMap = new HashMap();
|
|
135 |
|
|
136 |
// Use the GIOP version of the ORB. Should
|
|
137 |
// be specified in ServiceContext.
|
|
138 |
// See REVISIT below concerning giopVersion.
|
|
139 |
giopVersion = orb.getORBData().getGIOPVersion();
|
|
140 |
codeBase = null ;
|
|
141 |
}
|
|
142 |
|
|
143 |
/**
|
|
144 |
* Read the Service contexts from the input stream.
|
|
145 |
*/
|
|
146 |
public ServiceContexts(InputStream s)
|
|
147 |
{
|
|
148 |
this( (ORB)(s.orb()) ) ;
|
|
149 |
|
|
150 |
// We need to store this so that we can have access
|
|
151 |
// to the CodeBase for unmarshaling possible
|
|
152 |
// RMI-IIOP valuetype data within an encapsulation.
|
|
153 |
// (Known case: UnknownExceptionInfo)
|
|
154 |
codeBase = ((CDRInputStream)s).getCodeBase();
|
|
155 |
|
|
156 |
createMapFromInputStream(s);
|
|
157 |
|
|
158 |
// Fix for bug 4904723
|
|
159 |
giopVersion = ((CDRInputStream)s).getGIOPVersion();
|
|
160 |
}
|
|
161 |
|
|
162 |
/**
|
|
163 |
* Find the ServiceContextData for a given scId and unmarshal
|
|
164 |
* the bytes.
|
|
165 |
*/
|
|
166 |
private ServiceContext unmarshal(Integer scId, byte[] data) {
|
|
167 |
|
|
168 |
ServiceContextRegistry scr = orb.getServiceContextRegistry();
|
|
169 |
|
|
170 |
ServiceContextData scd = scr.findServiceContextData(scId.intValue());
|
|
171 |
ServiceContext sc = null;
|
|
172 |
|
|
173 |
if (scd == null) {
|
|
174 |
if (orb.serviceContextDebugFlag) {
|
|
175 |
dprint("Could not find ServiceContextData for "
|
|
176 |
+ scId
|
|
177 |
+ " using UnknownServiceContext");
|
|
178 |
}
|
|
179 |
|
|
180 |
sc = new UnknownServiceContext(scId.intValue(), data);
|
|
181 |
|
|
182 |
} else {
|
|
183 |
|
|
184 |
if (orb.serviceContextDebugFlag) {
|
|
185 |
dprint("Found " + scd);
|
|
186 |
}
|
|
187 |
|
|
188 |
// REVISIT. GIOP version should be specified as
|
|
189 |
// part of a service context's definition, so should
|
|
190 |
// be accessible from ServiceContextData via
|
|
191 |
// its ServiceContext implementation class.
|
|
192 |
//
|
|
193 |
// Since we don't have that, yet, I'm using the GIOP
|
|
194 |
// version of the input stream, presuming that someone
|
|
195 |
// can't send a service context of a later GIOP
|
|
196 |
// version than its stream version.
|
|
197 |
//
|
|
198 |
// Note: As of Jan 2001, no standard OMG or Sun service contexts
|
|
199 |
// ship wchar data or are defined as using anything but GIOP 1.0 CDR.
|
|
200 |
EncapsInputStream eis
|
|
201 |
= new EncapsInputStream(orb,
|
|
202 |
data,
|
|
203 |
data.length,
|
|
204 |
giopVersion,
|
|
205 |
codeBase);
|
|
206 |
eis.consumeEndian();
|
|
207 |
|
|
208 |
// Now the input stream passed to a ServiceContext
|
|
209 |
// constructor is already the encapsulation input
|
|
210 |
// stream with the endianness read off, so the
|
|
211 |
// service context should just unmarshal its own
|
|
212 |
// data.
|
|
213 |
sc = scd.makeServiceContext(eis, giopVersion);
|
|
214 |
if (sc == null)
|
|
215 |
throw wrapper.svcctxUnmarshalError(
|
|
216 |
CompletionStatus.COMPLETED_MAYBE);
|
|
217 |
}
|
|
218 |
|
|
219 |
return sc;
|
|
220 |
}
|
|
221 |
|
|
222 |
public void addAlignmentPadding()
|
|
223 |
{
|
|
224 |
// Make service context 12 bytes longer by adding
|
|
225 |
// JAVAIDL_ALIGN_SERVICE_ID service context at end.
|
|
226 |
// The exact length
|
|
227 |
// must be >8 (minimum service context size) and
|
|
228 |
// =4 mod 8, so 12 is the minimum.
|
|
229 |
addAlignmentOnWrite = true ;
|
|
230 |
}
|
|
231 |
|
|
232 |
/**
|
|
233 |
* Hopefully unused scid: This should be changed to a proper
|
|
234 |
* VMCID aligned value. REVISIT!
|
|
235 |
*/
|
|
236 |
private static final int JAVAIDL_ALIGN_SERVICE_ID = 0xbe1345cd ;
|
|
237 |
|
|
238 |
/**
|
|
239 |
* Write the service contexts to the output stream.
|
|
240 |
*
|
|
241 |
* If they haven't been unmarshaled, we don't have to
|
|
242 |
* unmarshal them.
|
|
243 |
*/
|
|
244 |
public void write(OutputStream os, GIOPVersion gv)
|
|
245 |
{
|
|
246 |
if (isDebugging(os)) {
|
|
247 |
dprint( "Writing service contexts to output stream" ) ;
|
|
248 |
Utility.printStackTrace() ;
|
|
249 |
}
|
|
250 |
|
|
251 |
int numsc = scMap.size();
|
|
252 |
|
|
253 |
if (addAlignmentOnWrite) {
|
|
254 |
if (isDebugging(os))
|
|
255 |
dprint( "Adding alignment padding" ) ;
|
|
256 |
|
|
257 |
numsc++ ;
|
|
258 |
}
|
|
259 |
|
|
260 |
if (isDebugging(os))
|
|
261 |
dprint( "Service context has " + numsc + " components" ) ;
|
|
262 |
|
|
263 |
os.write_long( numsc ) ;
|
|
264 |
|
|
265 |
writeServiceContextsInOrder(os, gv);
|
|
266 |
|
|
267 |
if (addAlignmentOnWrite) {
|
|
268 |
if (isDebugging(os))
|
|
269 |
dprint( "Writing alignment padding" ) ;
|
|
270 |
|
|
271 |
os.write_long( JAVAIDL_ALIGN_SERVICE_ID ) ;
|
|
272 |
os.write_long( 4 ) ;
|
|
273 |
os.write_octet( (byte)0 ) ;
|
|
274 |
os.write_octet( (byte)0 ) ;
|
|
275 |
os.write_octet( (byte)0 ) ;
|
|
276 |
os.write_octet( (byte)0 ) ;
|
|
277 |
}
|
|
278 |
|
|
279 |
if (isDebugging(os))
|
|
280 |
dprint( "Service context writing complete" ) ;
|
|
281 |
}
|
|
282 |
|
|
283 |
/**
|
|
284 |
* Write the service contexts in scMap in a desired order.
|
|
285 |
* Right now, the only special case we have is UnknownExceptionInfo,
|
|
286 |
* so I'm merely writing it last if present.
|
|
287 |
*/
|
|
288 |
private void writeServiceContextsInOrder(OutputStream os, GIOPVersion gv) {
|
|
289 |
|
|
290 |
// Temporarily remove this rather than check it per iteration
|
|
291 |
Integer ueInfoId
|
|
292 |
= new Integer(UEInfoServiceContext.SERVICE_CONTEXT_ID);
|
|
293 |
|
|
294 |
Object unknownExceptionInfo = scMap.remove(ueInfoId);
|
|
295 |
|
|
296 |
Iterator iter = scMap.keySet().iterator();
|
|
297 |
|
|
298 |
while (iter.hasNext()) {
|
|
299 |
Integer id = (Integer)iter.next();
|
|
300 |
|
|
301 |
writeMapEntry(os, id, scMap.get(id), gv);
|
|
302 |
}
|
|
303 |
|
|
304 |
// Write the UnknownExceptionInfo service context last
|
|
305 |
// (so it will be after the CodeBase) and restore it in
|
|
306 |
// the map.
|
|
307 |
if (unknownExceptionInfo != null) {
|
|
308 |
writeMapEntry(os, ueInfoId, unknownExceptionInfo, gv);
|
|
309 |
|
|
310 |
scMap.put(ueInfoId, unknownExceptionInfo);
|
|
311 |
}
|
|
312 |
}
|
|
313 |
|
|
314 |
/**
|
|
315 |
* Write the given entry from the scMap to the OutputStream.
|
|
316 |
* See note on giopVersion. The service context should
|
|
317 |
* know the GIOP version it is meant for.
|
|
318 |
*/
|
|
319 |
private void writeMapEntry(OutputStream os, Integer id, Object scObj, GIOPVersion gv) {
|
|
320 |
|
|
321 |
// If it's still in byte[] form, we don't need to
|
|
322 |
// unmarshal it here, just copy the bytes into
|
|
323 |
// the new stream.
|
|
324 |
|
|
325 |
if (scObj instanceof byte[]) {
|
|
326 |
if (isDebugging(os))
|
|
327 |
dprint( "Writing service context bytes for id " + id);
|
|
328 |
|
|
329 |
OctetSeqHelper.write(os, (byte[])scObj);
|
|
330 |
|
|
331 |
} else {
|
|
332 |
|
|
333 |
// We actually unmarshaled it into a ServiceContext
|
|
334 |
// at some point.
|
|
335 |
ServiceContext sc = (ServiceContext)scObj;
|
|
336 |
|
|
337 |
if (isDebugging(os))
|
|
338 |
dprint( "Writing service context " + sc ) ;
|
|
339 |
|
|
340 |
sc.write(os, gv);
|
|
341 |
}
|
|
342 |
}
|
|
343 |
|
|
344 |
/** Add a service context to the stream, if there is not already
|
|
345 |
* a service context in this object with the same id as sc.
|
|
346 |
*/
|
|
347 |
public void put( ServiceContext sc )
|
|
348 |
{
|
|
349 |
Integer id = new Integer(sc.getId());
|
|
350 |
scMap.put(id, sc);
|
|
351 |
}
|
|
352 |
|
|
353 |
public void delete( int scId ) {
|
|
354 |
this.delete(new Integer(scId));
|
|
355 |
}
|
|
356 |
|
|
357 |
public void delete(Integer id)
|
|
358 |
{
|
|
359 |
scMap.remove(id) ;
|
|
360 |
}
|
|
361 |
|
|
362 |
public ServiceContext get(int scId) {
|
|
363 |
return this.get(new Integer(scId));
|
|
364 |
}
|
|
365 |
|
|
366 |
public ServiceContext get(Integer id)
|
|
367 |
{
|
|
368 |
Object result = scMap.get(id);
|
|
369 |
if (result == null)
|
|
370 |
return null ;
|
|
371 |
|
|
372 |
// Lazy unmarshaling on first use.
|
|
373 |
if (result instanceof byte[]) {
|
|
374 |
|
|
375 |
ServiceContext sc = unmarshal(id, (byte[])result);
|
|
376 |
|
|
377 |
scMap.put(id, sc);
|
|
378 |
|
|
379 |
return sc;
|
|
380 |
} else {
|
|
381 |
return (ServiceContext)result;
|
|
382 |
}
|
|
383 |
}
|
|
384 |
|
|
385 |
private ORB orb ;
|
|
386 |
|
|
387 |
/**
|
|
388 |
* Map of all ServiceContext objects in this container.
|
|
389 |
*
|
|
390 |
* Keys are java.lang.Integers for service context IDs.
|
|
391 |
* Values are either instances of ServiceContext or the
|
|
392 |
* unmarshaled byte arrays (unmarshaled on first use).
|
|
393 |
*
|
|
394 |
* This provides a mild optimization if we don't happen to
|
|
395 |
* use a given service context, but it's main advantage is
|
|
396 |
* that it allows us to change the order in which we
|
|
397 |
* unmarshal them. We need to do the UnknownExceptionInfo service
|
|
398 |
* context after the SendingContextRunTime service context so that we can
|
|
399 |
* get the CodeBase if necessary.
|
|
400 |
*/
|
|
401 |
private Map scMap;
|
|
402 |
|
|
403 |
/**
|
|
404 |
* If true, write out a special alignment service context to force the
|
|
405 |
* correct alignment on re-marshalling.
|
|
406 |
*/
|
|
407 |
private boolean addAlignmentOnWrite ;
|
|
408 |
|
|
409 |
private CodeBase codeBase;
|
|
410 |
private GIOPVersion giopVersion;
|
|
411 |
private ORBUtilSystemException wrapper ;
|
|
412 |
}
|