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

Wed, 28 Mar 2012 02:50:50 -0700

author
mbankal
date
Wed, 28 Mar 2012 02:50:50 -0700
changeset 371
e324dfb90c9e
parent 158
91006f157c46
child 748
6845b95cba6b
permissions
-rw-r--r--

7079902: Refine CORBA data models
Reviewed-by: coffeys

     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  */
    32 package sun.rmi.rmic.iiop;
    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;
    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 {
    55     private boolean isCustom;
    57     //_____________________________________________________________________
    58     // Public Interfaces
    59     //_____________________________________________________________________
    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) {
    72         if (stack.anyErrors()) return null;
    74         // Do we already have it?
    76         sun.tools.java.Type theType = classDef.getType();
    77         String typeKey = theType.toString();
    78         Type existing = getType(typeKey,stack);
    80         if (existing != null) {
    82             if (!(existing instanceof ValueType)) return null; // False hit.
    84             // Yep, so return it...
    86             return (ValueType) existing;
    87         }
    89         // Is this java.lang.Class?
    91         boolean javaLangClass = false;
    93         if (classDef.getClassDeclaration().getName() == idJavaLangClass) {
    95             // Yes, so replace classDef with one for
    96             // javax.rmi.CORBA.ClassDesc...
    98             javaLangClass = true;
    99             BatchEnvironment env = stack.getEnv();
   100             ClassDeclaration decl = env.getClassDeclaration(idClassDesc);
   101             ClassDefinition def = null;
   103             try {
   104                 def = decl.getClassDefinition(env);
   105             } catch (ClassNotFound ex) {
   106                 classNotFound(stack,ex);
   107                 return null;
   108             }
   110             classDef = def;
   111         }
   113         // Could this be a value?
   115         if (couldBeValue(stack,classDef)) {
   117             // Yes, so check it...
   119             ValueType it = new ValueType(classDef,stack,javaLangClass);
   120             putType(typeKey,it,stack);
   121             stack.push(it);
   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     }
   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     }
   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     }
   164     //_____________________________________________________________________
   165     // Subclass/Internal Interfaces
   166     //_____________________________________________________________________
   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;
   178         // If this is the mapped version of java.lang.Class,
   179         // set the non-IDL names back to java.lang.Class...
   181         if (isMappedJavaLangClass) {
   182             setNames(idJavaLangClass,IDL_CLASS_MODULE,IDL_CLASS);
   183         }
   184     }
   186     //_____________________________________________________________________
   187     // Internal Interfaces
   188     //_____________________________________________________________________
   190     /**
   191      * Initialize this instance.
   192      */
   194     private static boolean couldBeValue(ContextStack stack, ClassDefinition classDef) {
   196         boolean result = false;
   197         ClassDeclaration classDecl = classDef.getClassDeclaration();
   198         BatchEnvironment env = stack.getEnv();
   200         try {
   201             // Make sure it's not remote...
   203             if (env.defRemote.implementedBy(env, classDecl)) {
   204                 failedConstraint(10,false,stack,classDef.getName());
   205             } else {
   207                 // Make sure it's Serializable...
   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         }
   219         return result;
   220     }
   222     /**
   223      * Initialize this instance.
   224      */
   225     private boolean initialize (ContextStack stack, boolean quiet) {
   227         ClassDefinition ourDef = getClassDefinition();
   228         ClassDeclaration ourDecl = getClassDeclaration();
   230         try {
   232             // Make sure our parentage is ok...
   234             if (!initParents(stack)) {
   235                 failedConstraint(12,quiet,stack,getQualifiedName());
   236                 return false;
   237             }
   240             // We're ok, so make up our collections...
   242             Vector directInterfaces = new Vector();
   243             Vector directMethods = new Vector();
   244             Vector directMembers = new Vector();
   246             // Get interfaces...
   248             if (addNonRemoteInterfaces(directInterfaces,stack) != null) {
   250                 // Get methods...
   252                 if (addAllMethods(ourDef,directMethods,false,false,stack) != null) {
   254                     // Update parent class methods
   255                     if (updateParentClassMethods(ourDef,directMethods,false,stack) != null) {
   257                     // Get constants and members...
   259                     if (addAllMembers(directMembers,false,false,stack)) {
   261                         // We're ok, so pass 'em up...
   263                         if (!initialize(directInterfaces,directMethods,directMembers,stack,quiet)) {
   264                             return false;
   265                         }
   267                         // Is this class Externalizable?
   269                         boolean externalizable = false;
   270                         if (!env.defExternalizable.implementedBy(env, ourDecl)) {
   272                             // No, so check to see if we have a serialPersistentField
   273                             // that will modify the members.
   275                             if (!checkPersistentFields(getClassInstance(),quiet)) {
   276                                 return false;
   277                             }
   278                         } else {
   280                             // Yes.
   282                             externalizable = true;
   283                         }
   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                         //
   292                         if (externalizable) {
   293                             isCustom = true;
   294                         } else {
   295                             for (MemberDefinition member = ourDef.getFirstMember();
   296                                  member != null;
   297                                  member = member.getNextMember()) {
   299                                 if (member.isMethod() &&
   300                                     !member.isInitializer() &&
   301                                     member.isPrivate() &&
   302                                     member.getName().toString().equals("writeObject")) {
   304                                     // Check return type, arguments and exceptions...
   306                                     sun.tools.java.Type methodType = member.getType();
   307                                     sun.tools.java.Type rtnType = methodType.getReturnType();
   309                                     if (rtnType == sun.tools.java.Type.tVoid) {
   311                                         // Return type is correct. How about arguments?
   313                                         sun.tools.java.Type[] args = methodType.getArgumentTypes();
   314                                         if (args.length == 1 &&
   315                                             args[0].getTypeSignature().equals("Ljava/io/ObjectOutputStream;")) {
   317                                             // Arguments are correct, so it is a custom
   318                                             // value type...
   320                                             isCustom = true;
   321                                         }
   322                                     }
   323                                 }
   324                             }
   325                         }
   326                         }
   328                         return true;
   329                     }
   330                 }
   331             }
   332         } catch (ClassNotFound e) {
   333             classNotFound(stack,e);
   334         }
   336         return false;
   337     }
   340     private boolean checkPersistentFields (Class clz, boolean quiet) {
   342         // Do we have a writeObject method?
   344         for (int i = 0; i < methods.length; i++) {
   345             if (methods[i].getName().equals("writeObject") &&
   346                 methods[i].getArguments().length == 1) {
   348                 Type returnType = methods[i].getReturnType();
   349                 Type arg = methods[i].getArguments()[0];
   350                 String id = arg.getQualifiedName();
   352                 if (returnType.isType(TYPE_VOID) &&
   353                     id.equals("java.io.ObjectOutputStream")) {
   355                     // Got one, so there's nothing to do...
   357                     return true;
   358                 }
   359             }
   360         }
   362         // Do we have a valid serialPersistentField array?
   364         MemberDefinition spfDef = null;
   366         for (int i = 0; i < members.length; i++) {
   367             if (members[i].getName().equals("serialPersistentFields")) {
   369                 Member member = members[i];
   370                 Type type = member.getType();
   371                 Type elementType = type.getElementType();
   373                 // We have a member with the correct name. Make sure
   374                 // we have the correct signature...
   376                 if (elementType != null &&
   377                     elementType.getQualifiedName().equals(
   378                                                           "java.io.ObjectStreamField")
   379                     ) {
   381                     if (member.isStatic() &&
   382                         member.isFinal() &&
   383                         member.isPrivate()) {
   385                         // We have the correct signature
   387                         spfDef = member.getMemberDefinition();
   389                     } else {
   391                         // Bad signature...
   393                         failedConstraint(4,quiet,stack,getQualifiedName());
   394                         return false;
   395                     }
   396                 }
   397             }
   398         }
   400         // If we do not have a serialPersistentField,
   401         // there's nothing to do, so return with no error...
   403         if (spfDef == null) {
   404             return true;
   405         }
   407         // Ok, now we must examine the contents of the array -
   408         // then validate them...
   410         Hashtable fields = getPersistentFields(clz);
   411         boolean result = true;
   413         for (int i = 0; i < members.length; i++) {
   414             String fieldName = members[i].getName();
   415             String fieldType = members[i].getType().getSignature();
   417             // Is this field present in the array?
   419             String type = (String) fields.get(fieldName);
   421             if (type == null) {
   423                 // No, so mark it transient...
   425                 members[i].setTransient();
   427             } else {
   429                 // Yes, does the type match?
   431                 if (type.equals(fieldType)) {
   433                     // Yes, so remove it from the fields table...
   435                     fields.remove(fieldName);
   437                 } else {
   439                     // No, so error...
   441                     result = false;
   442                     failedConstraint(2,quiet,stack,fieldName,getQualifiedName());
   443                 }
   444             }
   445         }
   447         // Ok, we've checked all of our fields. Are there any left in the "array"?
   448         // If so, it's an error...
   450         if (result && fields.size() > 0) {
   452             result = false;
   453             failedConstraint(9,quiet,stack,getQualifiedName());
   454         }
   456         // Return result...
   458         return result;
   459     }
   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