src/share/classes/sun/rmi/rmic/iiop/ValueType.java

changeset 0
7ef37b2cdcad
child 748
6845b95cba6b
equal deleted inserted replaced
-1:000000000000 0:7ef37b2cdcad
1 /*
2 * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
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
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
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 *
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.
24 */
25 /*
26 * Licensed Materials - Property of IBM
27 * RMI-IIOP v1.0
28 * Copyright IBM Corp. 1998 1999 All Rights Reserved
29 *
30 */
31
32 package sun.rmi.rmic.iiop;
33
34 import java.util.Vector;
35 import sun.tools.java.ClassNotFound;
36 import sun.tools.java.ClassDeclaration;
37 import sun.tools.java.ClassDefinition;
38 import sun.tools.java.MemberDefinition;
39 import java.util.Hashtable;
40 import java.io.ObjectStreamClass;
41 import java.io.ObjectStreamField;
42
43
44 /**
45 * ValueType represents any non-special class which does inherit from
46 * java.io.Serializable and does not inherit from java.rmi.Remote.
47 * <p>
48 * The static forValue(...) method must be used to obtain an instance, and
49 * will return null if the ClassDefinition is non-conforming.
50 *
51 * @author Bryan Atsatt
52 */
53 public class ValueType extends ClassType {
54
55 private boolean isCustom;
56
57 //_____________________________________________________________________
58 // Public Interfaces
59 //_____________________________________________________________________
60
61 /**
62 * Create an ValueType object for the given class.
63 *
64 * If the class is not a properly formed or if some other error occurs, the
65 * return value will be null, and errors will have been reported to the
66 * supplied BatchEnvironment.
67 */
68 public static ValueType forValue(ClassDefinition classDef,
69 ContextStack stack,
70 boolean quiet) {
71
72 if (stack.anyErrors()) return null;
73
74 // Do we already have it?
75
76 sun.tools.java.Type theType = classDef.getType();
77 String typeKey = theType.toString();
78 Type existing = getType(typeKey,stack);
79
80 if (existing != null) {
81
82 if (!(existing instanceof ValueType)) return null; // False hit.
83
84 // Yep, so return it...
85
86 return (ValueType) existing;
87 }
88
89 // Is this java.lang.Class?
90
91 boolean javaLangClass = false;
92
93 if (classDef.getClassDeclaration().getName() == idJavaLangClass) {
94
95 // Yes, so replace classDef with one for
96 // javax.rmi.CORBA.ClassDesc...
97
98 javaLangClass = true;
99 BatchEnvironment env = stack.getEnv();
100 ClassDeclaration decl = env.getClassDeclaration(idClassDesc);
101 ClassDefinition def = null;
102
103 try {
104 def = decl.getClassDefinition(env);
105 } catch (ClassNotFound ex) {
106 classNotFound(stack,ex);
107 return null;
108 }
109
110 classDef = def;
111 }
112
113 // Could this be a value?
114
115 if (couldBeValue(stack,classDef)) {
116
117 // Yes, so check it...
118
119 ValueType it = new ValueType(classDef,stack,javaLangClass);
120 putType(typeKey,it,stack);
121 stack.push(it);
122
123 if (it.initialize(stack,quiet)) {
124 stack.pop(true);
125 return it;
126 } else {
127 removeType(typeKey,stack);
128 stack.pop(false);
129 return null;
130 }
131 } else {
132 return null;
133 }
134 }
135
136
137 /**
138 * Return a string describing this type.
139 */
140 public String getTypeDescription () {
141 String result = addExceptionDescription("Value");
142 if (isCustom) {
143 result = "Custom " + result;
144 }
145 if (isIDLEntity) {
146 result = result + " [IDLEntity]";
147 }
148 return result;
149 }
150
151 /**
152 * Return true if this type is a "custom" type (i.e.
153 * it implements java.io.Externalizable or has a
154 * method with the following signature:
155 *
156 * private void writeObject(java.io.ObjectOutputStream out);
157 *
158 */
159 public boolean isCustom () {
160 return isCustom;
161 }
162
163
164 //_____________________________________________________________________
165 // Subclass/Internal Interfaces
166 //_____________________________________________________________________
167
168 /**
169 * Create a ValueType instance for the given class. The resulting
170 * object is not yet completely initialized.
171 */
172 private ValueType(ClassDefinition classDef,
173 ContextStack stack,
174 boolean isMappedJavaLangClass) {
175 super(stack,classDef,TYPE_VALUE | TM_CLASS | TM_COMPOUND);
176 isCustom = false;
177
178 // If this is the mapped version of java.lang.Class,
179 // set the non-IDL names back to java.lang.Class...
180
181 if (isMappedJavaLangClass) {
182 setNames(idJavaLangClass,IDL_CLASS_MODULE,IDL_CLASS);
183 }
184 }
185
186 //_____________________________________________________________________
187 // Internal Interfaces
188 //_____________________________________________________________________
189
190 /**
191 * Initialize this instance.
192 */
193
194 private static boolean couldBeValue(ContextStack stack, ClassDefinition classDef) {
195
196 boolean result = false;
197 ClassDeclaration classDecl = classDef.getClassDeclaration();
198 BatchEnvironment env = stack.getEnv();
199
200 try {
201 // Make sure it's not remote...
202
203 if (env.defRemote.implementedBy(env, classDecl)) {
204 failedConstraint(10,false,stack,classDef.getName());
205 } else {
206
207 // Make sure it's Serializable...
208
209 if (!env.defSerializable.implementedBy(env, classDecl)) {
210 failedConstraint(11,false,stack,classDef.getName());
211 } else {
212 result = true;
213 }
214 }
215 } catch (ClassNotFound e) {
216 classNotFound(stack,e);
217 }
218
219 return result;
220 }
221
222 /**
223 * Initialize this instance.
224 */
225 private boolean initialize (ContextStack stack, boolean quiet) {
226
227 ClassDefinition ourDef = getClassDefinition();
228 ClassDeclaration ourDecl = getClassDeclaration();
229
230 try {
231
232 // Make sure our parentage is ok...
233
234 if (!initParents(stack)) {
235 failedConstraint(12,quiet,stack,getQualifiedName());
236 return false;
237 }
238
239
240 // We're ok, so make up our collections...
241
242 Vector directInterfaces = new Vector();
243 Vector directMethods = new Vector();
244 Vector directMembers = new Vector();
245
246 // Get interfaces...
247
248 if (addNonRemoteInterfaces(directInterfaces,stack) != null) {
249
250 // Get methods...
251
252 if (addAllMethods(ourDef,directMethods,false,false,stack) != null) {
253
254 // Update parent class methods
255 if (updateParentClassMethods(ourDef,directMethods,false,stack) != null) {
256
257 // Get constants and members...
258
259 if (addAllMembers(directMembers,false,false,stack)) {
260
261 // We're ok, so pass 'em up...
262
263 if (!initialize(directInterfaces,directMethods,directMembers,stack,quiet)) {
264 return false;
265 }
266
267 // Is this class Externalizable?
268
269 boolean externalizable = false;
270 if (!env.defExternalizable.implementedBy(env, ourDecl)) {
271
272 // No, so check to see if we have a serialPersistentField
273 // that will modify the members.
274
275 if (!checkPersistentFields(getClassInstance(),quiet)) {
276 return false;
277 }
278 } else {
279
280 // Yes.
281
282 externalizable = true;
283 }
284
285 // Should this class be considered "custom"? It is if
286 // it is Externalizable OR if it has a method with the
287 // following signature:
288 //
289 // private void writeObject(java.io.ObjectOutputStream out);
290 //
291
292 if (externalizable) {
293 isCustom = true;
294 } else {
295 for (MemberDefinition member = ourDef.getFirstMember();
296 member != null;
297 member = member.getNextMember()) {
298
299 if (member.isMethod() &&
300 !member.isInitializer() &&
301 member.isPrivate() &&
302 member.getName().toString().equals("writeObject")) {
303
304 // Check return type, arguments and exceptions...
305
306 sun.tools.java.Type methodType = member.getType();
307 sun.tools.java.Type rtnType = methodType.getReturnType();
308
309 if (rtnType == sun.tools.java.Type.tVoid) {
310
311 // Return type is correct. How about arguments?
312
313 sun.tools.java.Type[] args = methodType.getArgumentTypes();
314 if (args.length == 1 &&
315 args[0].getTypeSignature().equals("Ljava/io/ObjectOutputStream;")) {
316
317 // Arguments are correct, so it is a custom
318 // value type...
319
320 isCustom = true;
321 }
322 }
323 }
324 }
325 }
326 }
327
328 return true;
329 }
330 }
331 }
332 } catch (ClassNotFound e) {
333 classNotFound(stack,e);
334 }
335
336 return false;
337 }
338
339
340 private boolean checkPersistentFields (Class clz, boolean quiet) {
341
342 // Do we have a writeObject method?
343
344 for (int i = 0; i < methods.length; i++) {
345 if (methods[i].getName().equals("writeObject") &&
346 methods[i].getArguments().length == 1) {
347
348 Type returnType = methods[i].getReturnType();
349 Type arg = methods[i].getArguments()[0];
350 String id = arg.getQualifiedName();
351
352 if (returnType.isType(TYPE_VOID) &&
353 id.equals("java.io.ObjectOutputStream")) {
354
355 // Got one, so there's nothing to do...
356
357 return true;
358 }
359 }
360 }
361
362 // Do we have a valid serialPersistentField array?
363
364 MemberDefinition spfDef = null;
365
366 for (int i = 0; i < members.length; i++) {
367 if (members[i].getName().equals("serialPersistentFields")) {
368
369 Member member = members[i];
370 Type type = member.getType();
371 Type elementType = type.getElementType();
372
373 // We have a member with the correct name. Make sure
374 // we have the correct signature...
375
376 if (elementType != null &&
377 elementType.getQualifiedName().equals(
378 "java.io.ObjectStreamField")
379 ) {
380
381 if (member.isStatic() &&
382 member.isFinal() &&
383 member.isPrivate()) {
384
385 // We have the correct signature
386
387 spfDef = member.getMemberDefinition();
388
389 } else {
390
391 // Bad signature...
392
393 failedConstraint(4,quiet,stack,getQualifiedName());
394 return false;
395 }
396 }
397 }
398 }
399
400 // If we do not have a serialPersistentField,
401 // there's nothing to do, so return with no error...
402
403 if (spfDef == null) {
404 return true;
405 }
406
407 // Ok, now we must examine the contents of the array -
408 // then validate them...
409
410 Hashtable fields = getPersistentFields(clz);
411 boolean result = true;
412
413 for (int i = 0; i < members.length; i++) {
414 String fieldName = members[i].getName();
415 String fieldType = members[i].getType().getSignature();
416
417 // Is this field present in the array?
418
419 String type = (String) fields.get(fieldName);
420
421 if (type == null) {
422
423 // No, so mark it transient...
424
425 members[i].setTransient();
426
427 } else {
428
429 // Yes, does the type match?
430
431 if (type.equals(fieldType)) {
432
433 // Yes, so remove it from the fields table...
434
435 fields.remove(fieldName);
436
437 } else {
438
439 // No, so error...
440
441 result = false;
442 failedConstraint(2,quiet,stack,fieldName,getQualifiedName());
443 }
444 }
445 }
446
447 // Ok, we've checked all of our fields. Are there any left in the "array"?
448 // If so, it's an error...
449
450 if (result && fields.size() > 0) {
451
452 result = false;
453 failedConstraint(9,quiet,stack,getQualifiedName());
454 }
455
456 // Return result...
457
458 return result;
459 }
460
461 /**
462 * Get the names and types of all the persistent fields of a Class.
463 */
464 private Hashtable getPersistentFields (Class clz) {
465 Hashtable result = new Hashtable();
466 ObjectStreamClass osc = ObjectStreamClass.lookup(clz);
467 if (osc != null) {
468 ObjectStreamField[] fields = osc.getFields();
469 for (int i = 0; i < fields.length; i++) {
470 String typeSig;
471 String typePrefix = String.valueOf(fields[i].getTypeCode());
472 if (fields[i].isPrimitive()) {
473 typeSig = typePrefix;
474 } else {
475 if (fields[i].getTypeCode() == '[') {
476 typePrefix = "";
477 }
478 typeSig = typePrefix + fields[i].getType().getName().replace('.','/');
479 if (typeSig.endsWith(";")) {
480 typeSig = typeSig.substring(0,typeSig.length()-1);
481 }
482 }
483 result.put(fields[i].getName(),typeSig);
484 }
485 }
486 return result;
487 }
488 }

mercurial