KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > corba > se > spi > servicecontext > ServiceContexts


1 /*
2  * @(#)ServiceContexts.java 1.24 04/06/21
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package com.sun.corba.se.spi.servicecontext;
9
10 import java.lang.reflect.InvocationTargetException JavaDoc ;
11 import java.lang.reflect.Modifier JavaDoc ;
12 import java.lang.reflect.Field JavaDoc ;
13 import java.lang.reflect.Constructor JavaDoc ;
14 import java.util.*;
15
16 import org.omg.CORBA.OctetSeqHelper JavaDoc;
17 import org.omg.CORBA.SystemException JavaDoc;
18 import org.omg.CORBA.INTERNAL JavaDoc;
19 import org.omg.CORBA.CompletionStatus JavaDoc;
20 import org.omg.CORBA_2_3.portable.OutputStream JavaDoc ;
21 import org.omg.CORBA_2_3.portable.InputStream JavaDoc ;
22
23 import com.sun.org.omg.SendingContext.CodeBase;
24
25 import com.sun.corba.se.spi.ior.iiop.GIOPVersion;
26
27 import com.sun.corba.se.spi.orb.ORB ;
28
29 import com.sun.corba.se.spi.logging.CORBALogDomains;
30
31
32 import com.sun.corba.se.spi.servicecontext.ServiceContext ;
33 import com.sun.corba.se.spi.servicecontext.ServiceContextRegistry ;
34 import com.sun.corba.se.spi.servicecontext.ServiceContextData ;
35 import com.sun.corba.se.spi.servicecontext.UnknownServiceContext ;
36
37 import com.sun.corba.se.impl.encoding.CDRInputStream;
38 import com.sun.corba.se.impl.encoding.EncapsInputStream ;
39 import com.sun.corba.se.impl.orbutil.ORBUtility ;
40 import com.sun.corba.se.impl.util.Utility ;
41 import com.sun.corba.se.impl.logging.ORBUtilSystemException ;
42
43 public class ServiceContexts {
44     private static boolean isDebugging( OutputStream JavaDoc os )
45     {
46     ORB orb = (ORB)(os.orb()) ;
47     if (orb==null)
48         return false ;
49     return orb.serviceContextDebugFlag ;
50     }
51
52     private static boolean isDebugging( InputStream JavaDoc is )
53     {
54     ORB orb = (ORB)(is.orb()) ;
55     if (orb==null)
56         return false ;
57     return orb.serviceContextDebugFlag ;
58     }
59
60     private void dprint( String JavaDoc msg )
61     {
62     ORBUtility.dprint( this, msg ) ;
63     }
64
65     public static void writeNullServiceContext( OutputStream JavaDoc os )
66     {
67     if (isDebugging(os))
68         ORBUtility.dprint( "ServiceContexts", "Writing null service context" ) ;
69     os.write_long( 0 ) ;
70     }
71
72     /**
73      * Given the input stream, this fills our service
74      * context map. See the definition of scMap for
75      * details. Creates a HashMap.
76      *
77      * Note that we don't actually unmarshal the
78      * bytes of the service contexts here. That is
79      * done when they are actually requested via
80      * get(int).
81      */

82     private void createMapFromInputStream(InputStream JavaDoc is)
83     {
84         orb = (ORB)(is.orb()) ;
85         if (orb.serviceContextDebugFlag)
86             dprint( "Constructing ServiceContexts from input stream" ) ;
87
88         int numValid = is.read_long() ;
89
90         if (orb.serviceContextDebugFlag)
91             dprint("Number of service contexts = " + numValid);
92
93         for (int ctr = 0; ctr < numValid; ctr++) {
94             int scId = is.read_long();
95
96             if (orb.serviceContextDebugFlag)
97                 dprint("Reading service context id " + scId);
98
99             byte[] data = OctetSeqHelper.read(is);
100
101             if (orb.serviceContextDebugFlag)
102                 dprint("Service context" + scId + " length: " + data.length);
103
104             scMap.put(new Integer JavaDoc(scId), data);
105         }
106     }
107
108     public ServiceContexts( ORB orb )
109     {
110     this.orb = orb ;
111     wrapper = ORBUtilSystemException.get( orb,
112         CORBALogDomains.RPC_PROTOCOL ) ;
113
114     addAlignmentOnWrite = false ;
115
116         scMap = new HashMap();
117
118         // Use the GIOP version of the ORB. Should
119
// be specified in ServiceContext.
120
// See REVISIT below concerning giopVersion.
121
giopVersion = orb.getORBData().getGIOPVersion();
122     codeBase = null ;
123     }
124
125     /**
126      * Read the Service contexts from the input stream.
127      */

128     public ServiceContexts(InputStream JavaDoc s)
129     {
130     this( (ORB)(s.orb()) ) ;
131
132         // We need to store this so that we can have access
133
// to the CodeBase for unmarshaling possible
134
// RMI-IIOP valuetype data within an encapsulation.
135
// (Known case: UnknownExceptionInfo)
136
codeBase = ((CDRInputStream)s).getCodeBase();
137
138         createMapFromInputStream(s);
139
140     // Fix for bug 4904723
141
giopVersion = ((CDRInputStream)s).getGIOPVersion();
142     }
143
144     /**
145      * Find the ServiceContextData for a given scId and unmarshal
146      * the bytes.
147      */

148     private ServiceContext unmarshal(Integer JavaDoc scId, byte[] data) {
149
150         ServiceContextRegistry scr = orb.getServiceContextRegistry();
151
152         ServiceContextData scd = scr.findServiceContextData(scId.intValue());
153         ServiceContext sc = null;
154
155         if (scd == null) {
156             if (orb.serviceContextDebugFlag) {
157                 dprint("Could not find ServiceContextData for "
158                        + scId
159                        + " using UnknownServiceContext");
160             }
161
162             sc = new UnknownServiceContext(scId.intValue(), data);
163
164         } else {
165
166             if (orb.serviceContextDebugFlag) {
167                 dprint("Found " + scd);
168             }
169
170             // REVISIT. GIOP version should be specified as
171
// part of a service context's definition, so should
172
// be accessible from ServiceContextData via
173
// its ServiceContext implementation class.
174
//
175
// Since we don't have that, yet, I'm using the GIOP
176
// version of the input stream, presuming that someone
177
// can't send a service context of a later GIOP
178
// version than its stream version.
179
//
180
// Note: As of Jan 2001, no standard OMG or Sun service contexts
181
// ship wchar data or are defined as using anything but GIOP 1.0 CDR.
182
EncapsInputStream eis
183                 = new EncapsInputStream(orb,
184                                         data,
185                                         data.length,
186                                         giopVersion,
187                                         codeBase);
188             eis.consumeEndian();
189
190         // Now the input stream passed to a ServiceContext
191
// constructor is already the encapsulation input
192
// stream with the endianness read off, so the
193
// service context should just unmarshal its own
194
// data.
195
sc = scd.makeServiceContext(eis, giopVersion);
196         if (sc == null)
197         throw wrapper.svcctxUnmarshalError(
198             CompletionStatus.COMPLETED_MAYBE);
199         }
200
201         return sc;
202     }
203
204     public void addAlignmentPadding()
205     {
206     // Make service context 12 bytes longer by adding
207
// JAVAIDL_ALIGN_SERVICE_ID service context at end.
208
// The exact length
209
// must be >8 (minimum service context size) and
210
// =4 mod 8, so 12 is the minimum.
211
addAlignmentOnWrite = true ;
212     }
213
214     /**
215      * Hopefully unused scid: This should be changed to a proper
216      * VMCID aligned value. REVISIT!
217      */

218     private static final int JAVAIDL_ALIGN_SERVICE_ID = 0xbe1345cd ;
219
220     /**
221      * Write the service contexts to the output stream.
222      *
223      * If they haven't been unmarshaled, we don't have to
224      * unmarshal them.
225      */

226     public void write(OutputStream JavaDoc os, GIOPVersion gv)
227     {
228     if (isDebugging(os)) {
229         dprint( "Writing service contexts to output stream" ) ;
230         Utility.printStackTrace() ;
231     }
232
233     int numsc = scMap.size();
234
235     if (addAlignmentOnWrite) {
236         if (isDebugging(os))
237         dprint( "Adding alignment padding" ) ;
238
239         numsc++ ;
240     }
241
242     if (isDebugging(os))
243         dprint( "Service context has " + numsc + " components" ) ;
244
245     os.write_long( numsc ) ;
246
247         writeServiceContextsInOrder(os, gv);
248
249     if (addAlignmentOnWrite) {
250         if (isDebugging(os))
251         dprint( "Writing alignment padding" ) ;
252
253         os.write_long( JAVAIDL_ALIGN_SERVICE_ID ) ;
254         os.write_long( 4 ) ;
255         os.write_octet( (byte)0 ) ;
256         os.write_octet( (byte)0 ) ;
257         os.write_octet( (byte)0 ) ;
258         os.write_octet( (byte)0 ) ;
259     }
260
261     if (isDebugging(os))
262         dprint( "Service context writing complete" ) ;
263     }
264
265     /**
266      * Write the service contexts in scMap in a desired order.
267      * Right now, the only special case we have is UnknownExceptionInfo,
268      * so I'm merely writing it last if present.
269      */

270     private void writeServiceContextsInOrder(OutputStream JavaDoc os, GIOPVersion gv) {
271
272         // Temporarily remove this rather than check it per iteration
273
Integer JavaDoc ueInfoId
274             = new Integer JavaDoc(UEInfoServiceContext.SERVICE_CONTEXT_ID);
275
276         Object JavaDoc unknownExceptionInfo = scMap.remove(ueInfoId);
277
278     Iterator iter = scMap.keySet().iterator();
279
280     while (iter.hasNext()) {
281             Integer JavaDoc id = (Integer JavaDoc)iter.next();
282
283             writeMapEntry(os, id, scMap.get(id), gv);
284         }
285
286         // Write the UnknownExceptionInfo service context last
287
// (so it will be after the CodeBase) and restore it in
288
// the map.
289
if (unknownExceptionInfo != null) {
290             writeMapEntry(os, ueInfoId, unknownExceptionInfo, gv);
291
292             scMap.put(ueInfoId, unknownExceptionInfo);
293         }
294     }
295
296     /**
297      * Write the given entry from the scMap to the OutputStream.
298      * See note on giopVersion. The service context should
299      * know the GIOP version it is meant for.
300      */

301     private void writeMapEntry(OutputStream JavaDoc os, Integer JavaDoc id, Object JavaDoc scObj, GIOPVersion gv) {
302
303         // If it's still in byte[] form, we don't need to
304
// unmarshal it here, just copy the bytes into
305
// the new stream.
306

307         if (scObj instanceof byte[]) {
308             if (isDebugging(os))
309                 dprint( "Writing service context bytes for id " + id);
310
311             OctetSeqHelper.write(os, (byte[])scObj);
312
313         } else {
314
315             // We actually unmarshaled it into a ServiceContext
316
// at some point.
317
ServiceContext sc = (ServiceContext)scObj;
318
319             if (isDebugging(os))
320                 dprint( "Writing service context " + sc ) ;
321
322             sc.write(os, gv);
323         }
324     }
325
326     /** Add a service context to the stream, if there is not already
327      * a service context in this object with the same id as sc.
328      */

329     public void put( ServiceContext sc )
330     {
331         Integer JavaDoc id = new Integer JavaDoc(sc.getId());
332         scMap.put(id, sc);
333     }
334
335     public void delete( int scId ) {
336         this.delete(new Integer JavaDoc(scId));
337     }
338
339     public void delete(Integer JavaDoc id)
340     {
341         scMap.remove(id) ;
342     }
343
344     public ServiceContext get(int scId) {
345         return this.get(new Integer JavaDoc(scId));
346     }
347
348     public ServiceContext get(Integer JavaDoc id)
349     {
350         Object JavaDoc result = scMap.get(id);
351     if (result == null)
352         return null ;
353
354         // Lazy unmarshaling on first use.
355
if (result instanceof byte[]) {
356
357             ServiceContext sc = unmarshal(id, (byte[])result);
358
359             scMap.put(id, sc);
360
361             return sc;
362         } else {
363             return (ServiceContext)result;
364         }
365     }
366
367     private ORB orb ;
368
369     /**
370      * Map of all ServiceContext objects in this container.
371      *
372      * Keys are java.lang.Integers for service context IDs.
373      * Values are either instances of ServiceContext or the
374      * unmarshaled byte arrays (unmarshaled on first use).
375      *
376      * This provides a mild optimization if we don't happen to
377      * use a given service context, but it's main advantage is
378      * that it allows us to change the order in which we
379      * unmarshal them. We need to do the UnknownExceptionInfo service
380      * context after the SendingContextRunTime service context so that we can
381      * get the CodeBase if necessary.
382      */

383     private Map scMap;
384
385     /**
386      * If true, write out a special alignment service context to force the
387      * correct alignment on re-marshalling.
388      */

389     private boolean addAlignmentOnWrite ;
390
391     private CodeBase codeBase;
392     private GIOPVersion giopVersion;
393     private ORBUtilSystemException wrapper ;
394 }
395
Popular Tags