jaxws/src/share/classes/com/sun/codemodel/internal/JCodeModel.java
changeset 8 474761f14bca
child 2678 57cf2a1c1a05
equal deleted inserted replaced
0:fd16c54261b3 8:474761f14bca
       
     1 /*
       
     2  * Copyright 2006 Sun Microsystems, Inc.  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.  Sun designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    23  * have any questions.
       
    24  */
       
    25 
       
    26 package com.sun.codemodel.internal;
       
    27 
       
    28 import java.io.File;
       
    29 import java.io.IOException;
       
    30 import java.io.PrintStream;
       
    31 import java.lang.reflect.Modifier;
       
    32 import java.util.ArrayList;
       
    33 import java.util.Collections;
       
    34 import java.util.HashMap;
       
    35 import java.util.Iterator;
       
    36 import java.util.List;
       
    37 import java.util.Map;
       
    38 
       
    39 import com.sun.codemodel.internal.writer.FileCodeWriter;
       
    40 import com.sun.codemodel.internal.writer.ProgressCodeWriter;
       
    41 
       
    42 
       
    43 /**
       
    44  * Root of the code DOM.
       
    45  *
       
    46  * <p>
       
    47  * Here's your typical CodeModel application.
       
    48  *
       
    49  * <pre>
       
    50  * JCodeModel cm = new JCodeModel();
       
    51  *
       
    52  * // generate source code by populating the 'cm' tree.
       
    53  * cm._class(...);
       
    54  * ...
       
    55  *
       
    56  * // write them out
       
    57  * cm.build(new File("."));
       
    58  * </pre>
       
    59  *
       
    60  * <p>
       
    61  * Every CodeModel node is always owned by one {@link JCodeModel} object
       
    62  * at any given time (which can be often accesesd by the <tt>owner()</tt> method.)
       
    63  *
       
    64  * As such, when you generate Java code, most of the operation works
       
    65  * in a top-down fashion. For example, you create a class from {@link JCodeModel},
       
    66  * which gives you a {@link JDefinedClass}. Then you invoke a method on it
       
    67  * to generate a new method, which gives you {@link JMethod}, and so on.
       
    68  *
       
    69  * There are a few exceptions to this, most notably building {@link JExpression}s,
       
    70  * but generally you work with CodeModel in a top-down fashion.
       
    71  *
       
    72  * Because of this design, most of the CodeModel classes aren't directly instanciable.
       
    73  *
       
    74  *
       
    75  * <h2>Where to go from here?</h2>
       
    76  * <p>
       
    77  * Most of the time you'd want to populate new type definitions in a {@link JCodeModel}.
       
    78  * See {@link #_class(String, ClassType)}.
       
    79  */
       
    80 public final class JCodeModel {
       
    81 
       
    82     /** The packages that this JCodeWriter contains. */
       
    83     private HashMap<String,JPackage> packages = new HashMap<String,JPackage>();
       
    84 
       
    85     /** All JReferencedClasses are pooled here. */
       
    86     private final HashMap<Class,JReferencedClass> refClasses = new HashMap<Class,JReferencedClass>();
       
    87 
       
    88 
       
    89     /** Obtains a reference to the special "null" type. */
       
    90     public final JNullType NULL = new JNullType(this);
       
    91     // primitive types
       
    92     public final JPrimitiveType VOID    = new JPrimitiveType(this,"void",   Void.class);
       
    93     public final JPrimitiveType BOOLEAN = new JPrimitiveType(this,"boolean",Boolean.class);
       
    94     public final JPrimitiveType BYTE    = new JPrimitiveType(this,"byte",   Byte.class);
       
    95     public final JPrimitiveType SHORT   = new JPrimitiveType(this,"short",  Short.class);
       
    96     public final JPrimitiveType CHAR    = new JPrimitiveType(this,"char",   Character.class);
       
    97     public final JPrimitiveType INT     = new JPrimitiveType(this,"int",    Integer.class);
       
    98     public final JPrimitiveType FLOAT   = new JPrimitiveType(this,"float",  Float.class);
       
    99     public final JPrimitiveType LONG    = new JPrimitiveType(this,"long",   Long.class);
       
   100     public final JPrimitiveType DOUBLE  = new JPrimitiveType(this,"double", Double.class);
       
   101 
       
   102     /**
       
   103      * If the flag is true, we will consider two classes "Foo" and "foo"
       
   104      * as a collision.
       
   105      */
       
   106     protected static final boolean isCaseSensitiveFileSystem = getFileSystemCaseSensitivity();
       
   107 
       
   108     private static boolean getFileSystemCaseSensitivity() {
       
   109         try {
       
   110             // let the system property override, in case the user really
       
   111             // wants to override.
       
   112             if( System.getProperty("com.sun.codemodel.internal.FileSystemCaseSensitive")!=null )
       
   113                 return true;
       
   114         } catch( Exception e ) {}
       
   115 
       
   116         // on Unix, it's case sensitive.
       
   117         return (File.separatorChar == '/');
       
   118     }
       
   119 
       
   120 
       
   121     public JCodeModel() {}
       
   122 
       
   123     /**
       
   124      * Add a package to the list of packages to be generated
       
   125      *
       
   126      * @param name
       
   127      *        Name of the package. Use "" to indicate the root package.
       
   128      *
       
   129      * @return Newly generated package
       
   130      */
       
   131     public JPackage _package(String name) {
       
   132         JPackage p = packages.get(name);
       
   133         if (p == null) {
       
   134             p = new JPackage(name, this);
       
   135             packages.put(name, p);
       
   136         }
       
   137         return p;
       
   138     }
       
   139 
       
   140     public final JPackage rootPackage() {
       
   141         return _package("");
       
   142     }
       
   143 
       
   144     /**
       
   145      * Returns an iterator that walks the packages defined using this code
       
   146      * writer.
       
   147      */
       
   148     public Iterator<JPackage> packages() {
       
   149         return packages.values().iterator();
       
   150     }
       
   151 
       
   152     /**
       
   153      * Creates a new generated class.
       
   154      *
       
   155      * @exception JClassAlreadyExistsException
       
   156      *      When the specified class/interface was already created.
       
   157      */
       
   158     public JDefinedClass _class(String fullyqualifiedName) throws JClassAlreadyExistsException {
       
   159         return _class(fullyqualifiedName,ClassType.CLASS);
       
   160     }
       
   161 
       
   162     /**
       
   163      * Creates a dummy, unknown {@link JClass} that represents a given name.
       
   164      *
       
   165      * <p>
       
   166      * This method is useful when the code generation needs to include the user-specified
       
   167      * class that may or may not exist, and only thing known about it is a class name.
       
   168      */
       
   169     public JClass directClass(String name) {
       
   170         return new JDirectClass(this,name);
       
   171     }
       
   172 
       
   173     /**
       
   174      * Creates a new generated class.
       
   175      *
       
   176      * @exception JClassAlreadyExistsException
       
   177      *      When the specified class/interface was already created.
       
   178      */
       
   179     public JDefinedClass _class(String fullyqualifiedName,ClassType t) throws JClassAlreadyExistsException {
       
   180         int idx = fullyqualifiedName.lastIndexOf('.');
       
   181         if( idx<0 )     return rootPackage()._class(fullyqualifiedName);
       
   182         else
       
   183             return _package(fullyqualifiedName.substring(0,idx))
       
   184                 ._class( JMod.PUBLIC, fullyqualifiedName.substring(idx+1), t );
       
   185     }
       
   186 
       
   187     /**
       
   188      * Gets a reference to the already created generated class.
       
   189      *
       
   190      * @return null
       
   191      *      If the class is not yet created.
       
   192      * @see JPackage#_getClass(String)
       
   193      */
       
   194     public JDefinedClass _getClass(String fullyQualifiedName) {
       
   195         int idx = fullyQualifiedName.lastIndexOf('.');
       
   196         if( idx<0 )     return rootPackage()._getClass(fullyQualifiedName);
       
   197         else
       
   198             return _package(fullyQualifiedName.substring(0,idx))
       
   199                 ._getClass( fullyQualifiedName.substring(idx+1) );
       
   200     }
       
   201 
       
   202     /**
       
   203      * Creates a new anonymous class.
       
   204      *
       
   205      * @deprecated
       
   206      *      The naming convention doesn't match the rest of the CodeModel.
       
   207      *      Use {@link #anonymousClass(JClass)} instead.
       
   208      */
       
   209     public JDefinedClass newAnonymousClass(JClass baseType) {
       
   210         return new JAnonymousClass(baseType);
       
   211     }
       
   212 
       
   213     /**
       
   214      * Creates a new anonymous class.
       
   215      */
       
   216     public JDefinedClass anonymousClass(JClass baseType) {
       
   217         return new JAnonymousClass(baseType);
       
   218     }
       
   219 
       
   220     public JDefinedClass anonymousClass(Class baseType) {
       
   221         return anonymousClass(ref(baseType));
       
   222     }
       
   223 
       
   224     /**
       
   225      * Generates Java source code.
       
   226      * A convenience method for <code>build(destDir,destDir,System.out)</code>.
       
   227      *
       
   228      * @param   destDir
       
   229      *          source files are generated into this directory.
       
   230      * @param   status
       
   231      *      if non-null, progress indication will be sent to this stream.
       
   232      */
       
   233     public void build( File destDir, PrintStream status ) throws IOException {
       
   234         build(destDir,destDir,status);
       
   235     }
       
   236 
       
   237     /**
       
   238      * Generates Java source code.
       
   239      * A convenience method that calls {@link #build(CodeWriter,CodeWriter)}.
       
   240      *
       
   241      * @param   srcDir
       
   242      *          Java source files are generated into this directory.
       
   243      * @param   resourceDir
       
   244      *          Other resource files are generated into this directory.
       
   245      * @param   status
       
   246      *      if non-null, progress indication will be sent to this stream.
       
   247      */
       
   248     public void build( File srcDir, File resourceDir, PrintStream status ) throws IOException {
       
   249         CodeWriter src = new FileCodeWriter(srcDir);
       
   250         CodeWriter res = new FileCodeWriter(resourceDir);
       
   251         if(status!=null) {
       
   252             src = new ProgressCodeWriter(src, status );
       
   253             res = new ProgressCodeWriter(res, status );
       
   254         }
       
   255         build(src,res);
       
   256     }
       
   257 
       
   258     /**
       
   259      * A convenience method for <code>build(destDir,System.out)</code>.
       
   260      */
       
   261     public void build( File destDir ) throws IOException {
       
   262         build(destDir,System.out);
       
   263     }
       
   264 
       
   265     /**
       
   266      * A convenience method for <code>build(srcDir,resourceDir,System.out)</code>.
       
   267      */
       
   268     public void build( File srcDir, File resourceDir ) throws IOException {
       
   269         build(srcDir,resourceDir,System.out);
       
   270     }
       
   271 
       
   272     /**
       
   273      * A convenience method for <code>build(out,out)</code>.
       
   274      */
       
   275     public void build( CodeWriter out ) throws IOException {
       
   276         build(out,out);
       
   277     }
       
   278 
       
   279     /**
       
   280      * Generates Java source code.
       
   281      */
       
   282     public void build( CodeWriter source, CodeWriter resource ) throws IOException {
       
   283         JPackage[] pkgs = packages.values().toArray(new JPackage[packages.size()]);
       
   284         // avoid concurrent modification exception
       
   285         for( JPackage pkg : pkgs )
       
   286             pkg.build(source,resource);
       
   287         source.close();
       
   288         resource.close();
       
   289     }
       
   290 
       
   291     /**
       
   292      * Returns the number of files to be generated if
       
   293      * {@link #build} is invoked now.
       
   294      */
       
   295     public int countArtifacts() {
       
   296         int r = 0;
       
   297         JPackage[] pkgs = packages.values().toArray(new JPackage[packages.size()]);
       
   298         // avoid concurrent modification exception
       
   299         for( JPackage pkg : pkgs )
       
   300             r += pkg.countArtifacts();
       
   301         return r;
       
   302     }
       
   303 
       
   304 
       
   305     /**
       
   306      * Obtains a reference to an existing class from its Class object.
       
   307      *
       
   308      * <p>
       
   309      * The parameter may not be primitive.
       
   310      *
       
   311      * @see #_ref(Class) for the version that handles more cases.
       
   312      */
       
   313     public JClass ref(Class clazz) {
       
   314         JReferencedClass jrc = (JReferencedClass)refClasses.get(clazz);
       
   315         if (jrc == null) {
       
   316             if (clazz.isPrimitive())
       
   317                 throw new IllegalArgumentException(clazz+" is a primitive");
       
   318             if (clazz.isArray()) {
       
   319                 return new JArrayClass(this, _ref(clazz.getComponentType()));
       
   320             } else {
       
   321                 jrc = new JReferencedClass(clazz);
       
   322                 refClasses.put(clazz, jrc);
       
   323             }
       
   324         }
       
   325         return jrc;
       
   326     }
       
   327 
       
   328     public JType _ref(Class c) {
       
   329         if(c.isPrimitive())
       
   330             return JType.parse(this,c.getName());
       
   331         else
       
   332             return ref(c);
       
   333     }
       
   334 
       
   335     /**
       
   336      * Obtains a reference to an existing class from its fully-qualified
       
   337      * class name.
       
   338      *
       
   339      * <p>
       
   340      * First, this method attempts to load the class of the given name.
       
   341      * If that fails, we assume that the class is derived straight from
       
   342      * {@link Object}, and return a {@link JClass}.
       
   343      */
       
   344     public JClass ref(String fullyQualifiedClassName) {
       
   345         try {
       
   346             // try the context class loader first
       
   347             return ref(Thread.currentThread().getContextClassLoader().loadClass(fullyQualifiedClassName));
       
   348         } catch (ClassNotFoundException e) {
       
   349             // fall through
       
   350         }
       
   351         // then the default mechanism.
       
   352         try {
       
   353             return ref(Class.forName(fullyQualifiedClassName));
       
   354         } catch (ClassNotFoundException e1) {
       
   355             // fall through
       
   356         }
       
   357 
       
   358         // assume it's not visible to us.
       
   359         return new JDirectClass(this,fullyQualifiedClassName);
       
   360     }
       
   361 
       
   362     /**
       
   363      * Cached for {@link #wildcard()}.
       
   364      */
       
   365     private JClass wildcard;
       
   366 
       
   367     /**
       
   368      * Gets a {@link JClass} representation for "?",
       
   369      * which is equivalent to "? extends Object".
       
   370      */
       
   371     public JClass wildcard() {
       
   372         if(wildcard==null)
       
   373             wildcard = ref(Object.class).wildcard();
       
   374         return wildcard;
       
   375     }
       
   376 
       
   377     /**
       
   378      * Obtains a type object from a type name.
       
   379      *
       
   380      * <p>
       
   381      * This method handles primitive types, arrays, and existing {@link Class}es.
       
   382      *
       
   383      * @exception ClassNotFoundException
       
   384      *      If the specified type is not found.
       
   385      */
       
   386     public JType parseType(String name) throws ClassNotFoundException {
       
   387         // array
       
   388         if(name.endsWith("[]"))
       
   389             return parseType(name.substring(0,name.length()-2)).array();
       
   390 
       
   391         // try primitive type
       
   392         try {
       
   393             return JType.parse(this,name);
       
   394         } catch (IllegalArgumentException e) {
       
   395             ;
       
   396         }
       
   397 
       
   398         // existing class
       
   399         return new TypeNameParser(name).parseTypeName();
       
   400     }
       
   401 
       
   402     private final class TypeNameParser {
       
   403         private final String s;
       
   404         private int idx;
       
   405 
       
   406         public TypeNameParser(String s) {
       
   407             this.s = s;
       
   408         }
       
   409 
       
   410         /**
       
   411          * Parses a type name token T (which can be potentially of the form Tr&ly;T1,T2,...>,
       
   412          * or "? extends/super T".)
       
   413          *
       
   414          * @return the index of the character next to T.
       
   415          */
       
   416         JClass parseTypeName() throws ClassNotFoundException {
       
   417             int start = idx;
       
   418 
       
   419             if(s.charAt(idx)=='?') {
       
   420                 // wildcard
       
   421                 idx++;
       
   422                 ws();
       
   423                 String head = s.substring(idx);
       
   424                 if(head.startsWith("extends")) {
       
   425                     idx+=7;
       
   426                     ws();
       
   427                     return parseTypeName().wildcard();
       
   428                 } else
       
   429                 if(head.startsWith("super")) {
       
   430                     throw new UnsupportedOperationException("? super T not implemented");
       
   431                 } else {
       
   432                     // not supported
       
   433                     throw new IllegalArgumentException("only extends/super can follow ?, but found "+s.substring(idx));
       
   434                 }
       
   435             }
       
   436 
       
   437             while(idx<s.length()) {
       
   438                 char ch = s.charAt(idx);
       
   439                 if(Character.isJavaIdentifierStart(ch)
       
   440                 || Character.isJavaIdentifierPart(ch)
       
   441                 || ch=='.')
       
   442                     idx++;
       
   443                 else
       
   444                     break;
       
   445             }
       
   446 
       
   447             JClass clazz = ref(s.substring(start,idx));
       
   448 
       
   449             if(idx==s.length())
       
   450                 return clazz; // hit EOL
       
   451 
       
   452             char ch = s.charAt(idx);
       
   453 
       
   454             if(ch=='<')
       
   455                 return parseArguments(clazz);
       
   456 
       
   457             return clazz;
       
   458         }
       
   459 
       
   460         /**
       
   461          * Skips whitespaces
       
   462          */
       
   463         private void ws() {
       
   464             while(Character.isWhitespace(s.charAt(idx)) && idx<s.length())
       
   465                 idx++;
       
   466         }
       
   467 
       
   468         /**
       
   469          * Parses '&lt;T1,T2,...,Tn>'
       
   470          *
       
   471          * @return the index of the character next to '>'
       
   472          */
       
   473         private JClass parseArguments(JClass rawType) throws ClassNotFoundException {
       
   474             if(s.charAt(idx)!='<')
       
   475                 throw new IllegalArgumentException();
       
   476             idx++;
       
   477 
       
   478             List<JClass> args = new ArrayList<JClass>();
       
   479 
       
   480             while(true) {
       
   481                 args.add(parseTypeName());
       
   482                 if(idx==s.length())
       
   483                     throw new IllegalArgumentException("Missing '>' in "+s);
       
   484                 char ch = s.charAt(idx);
       
   485                 if(ch=='>')
       
   486                     return rawType.narrow(args.toArray(new JClass[args.size()]));
       
   487 
       
   488                 if(ch!=',')
       
   489                     throw new IllegalArgumentException(s);
       
   490                 idx++;
       
   491             }
       
   492 
       
   493         }
       
   494     }
       
   495 
       
   496     /**
       
   497      * References to existing classes.
       
   498      *
       
   499      * <p>
       
   500      * JReferencedClass is kept in a pool so that they are shared.
       
   501      * There is one pool for each JCodeModel object.
       
   502      *
       
   503      * <p>
       
   504      * It is impossible to cache JReferencedClass globally only because
       
   505      * there is the _package() method, which obtains the owner JPackage
       
   506      * object, which is scoped to JCodeModel.
       
   507      */
       
   508     private class JReferencedClass extends JClass implements JDeclaration {
       
   509         private final Class _class;
       
   510 
       
   511         JReferencedClass(Class _clazz) {
       
   512             super(JCodeModel.this);
       
   513             this._class = _clazz;
       
   514             assert !_class.isArray();
       
   515         }
       
   516 
       
   517         public String name() {
       
   518             return _class.getSimpleName().replace('$','.');
       
   519         }
       
   520 
       
   521         public String fullName() {
       
   522             return _class.getName().replace('$','.');
       
   523         }
       
   524 
       
   525         public String binaryName() {
       
   526             return _class.getName();
       
   527         }
       
   528 
       
   529         public JClass outer() {
       
   530             Class p = _class.getDeclaringClass();
       
   531             if(p==null)     return null;
       
   532             return ref(p);
       
   533         }
       
   534 
       
   535         public JPackage _package() {
       
   536             String name = fullName();
       
   537 
       
   538             // this type is array
       
   539             if (name.indexOf('[') != -1)
       
   540                 return JCodeModel.this._package("");
       
   541 
       
   542             // other normal case
       
   543             int idx = name.lastIndexOf('.');
       
   544             if (idx < 0)
       
   545                 return JCodeModel.this._package("");
       
   546             else
       
   547                 return JCodeModel.this._package(name.substring(0, idx));
       
   548         }
       
   549 
       
   550         public JClass _extends() {
       
   551             Class sp = _class.getSuperclass();
       
   552             if (sp == null) {
       
   553                 if(isInterface())
       
   554                     return owner().ref(Object.class);
       
   555                 return null;
       
   556             } else
       
   557                 return ref(sp);
       
   558         }
       
   559 
       
   560         public Iterator<JClass> _implements() {
       
   561             final Class[] interfaces = _class.getInterfaces();
       
   562             return new Iterator<JClass>() {
       
   563                 private int idx = 0;
       
   564                 public boolean hasNext() {
       
   565                     return idx < interfaces.length;
       
   566                 }
       
   567                 public JClass next() {
       
   568                     return JCodeModel.this.ref(interfaces[idx++]);
       
   569                 }
       
   570                 public void remove() {
       
   571                     throw new UnsupportedOperationException();
       
   572                 }
       
   573             };
       
   574         }
       
   575 
       
   576         public boolean isInterface() {
       
   577             return _class.isInterface();
       
   578         }
       
   579 
       
   580         public boolean isAbstract() {
       
   581             return Modifier.isAbstract(_class.getModifiers());
       
   582         }
       
   583 
       
   584         public JPrimitiveType getPrimitiveType() {
       
   585             Class v = boxToPrimitive.get(_class);
       
   586             if(v!=null)
       
   587                 return JType.parse(JCodeModel.this,v.getName());
       
   588             else
       
   589                 return null;
       
   590         }
       
   591 
       
   592         public boolean isArray() {
       
   593             return false;
       
   594         }
       
   595 
       
   596         public void declare(JFormatter f) {
       
   597         }
       
   598 
       
   599         public JTypeVar[] typeParams() {
       
   600             // TODO: does JDK 1.5 reflection provides these information?
       
   601             return super.typeParams();
       
   602         }
       
   603 
       
   604         protected JClass substituteParams(JTypeVar[] variables, List<JClass> bindings) {
       
   605             // TODO: does JDK 1.5 reflection provides these information?
       
   606             return this;
       
   607         }
       
   608     }
       
   609 
       
   610     /**
       
   611      * Conversion from primitive type {@link Class} (such as {@link Integer#TYPE}
       
   612      * to its boxed type (such as <tt>Integer.class</tt>)
       
   613      */
       
   614     public static final Map<Class,Class> primitiveToBox;
       
   615     /**
       
   616      * The reverse look up for {@link #primitiveToBox}
       
   617      */
       
   618     public static final Map<Class,Class> boxToPrimitive;
       
   619 
       
   620     static {
       
   621         Map<Class,Class> m1 = new HashMap<Class,Class>();
       
   622         Map<Class,Class> m2 = new HashMap<Class,Class>();
       
   623 
       
   624         m1.put(Boolean.class,Boolean.TYPE);
       
   625         m1.put(Byte.class,Byte.TYPE);
       
   626         m1.put(Character.class,Character.TYPE);
       
   627         m1.put(Double.class,Double.TYPE);
       
   628         m1.put(Float.class,Float.TYPE);
       
   629         m1.put(Integer.class,Integer.TYPE);
       
   630         m1.put(Long.class,Long.TYPE);
       
   631         m1.put(Short.class,Short.TYPE);
       
   632         m1.put(Void.class,Void.TYPE);
       
   633 
       
   634         for (Map.Entry<Class, Class> e : m1.entrySet())
       
   635             m2.put(e.getValue(),e.getKey());
       
   636 
       
   637         boxToPrimitive = Collections.unmodifiableMap(m1);
       
   638         primitiveToBox = Collections.unmodifiableMap(m2);
       
   639 
       
   640     }
       
   641 }