Home | History | Annotate | Download | only in javassist
      1 /*
      2  * Javassist, a Java-bytecode translator toolkit.
      3  * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved.
      4  *
      5  * The contents of this file are subject to the Mozilla Public License Version
      6  * 1.1 (the "License"); you may not use this file except in compliance with
      7  * the License.  Alternatively, the contents of this file may be used under
      8  * the terms of the GNU Lesser General Public License Version 2.1 or later.
      9  *
     10  * Software distributed under the License is distributed on an "AS IS" basis,
     11  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
     12  * for the specific language governing rights and limitations under the
     13  * License.
     14  */
     15 
     16 package javassist;
     17 
     18 import java.io.DataOutputStream;
     19 import java.io.IOException;
     20 import javassist.bytecode.ClassFile;
     21 
     22 class CtNewClass extends CtClassType {
     23     /* true if the class is an interface.
     24      */
     25     protected boolean hasConstructor;
     26 
     27     CtNewClass(String name, ClassPool cp,
     28                boolean isInterface, CtClass superclass) {
     29         super(name, cp);
     30         wasChanged = true;
     31         String superName;
     32         if (isInterface || superclass == null)
     33             superName = null;
     34         else
     35             superName = superclass.getName();
     36 
     37         classfile = new ClassFile(isInterface, name, superName);
     38         if (isInterface && superclass != null)
     39             classfile.setInterfaces(new String[] { superclass.getName() });
     40 
     41         setModifiers(Modifier.setPublic(getModifiers()));
     42         hasConstructor = isInterface;
     43     }
     44 
     45     protected void extendToString(StringBuffer buffer) {
     46         if (hasConstructor)
     47             buffer.append("hasConstructor ");
     48 
     49         super.extendToString(buffer);
     50     }
     51 
     52     public void addConstructor(CtConstructor c)
     53         throws CannotCompileException
     54     {
     55         hasConstructor = true;
     56         super.addConstructor(c);
     57     }
     58 
     59     public void toBytecode(DataOutputStream out)
     60         throws CannotCompileException, IOException
     61     {
     62         if (!hasConstructor)
     63             try {
     64                 inheritAllConstructors();
     65                 hasConstructor = true;
     66             }
     67             catch (NotFoundException e) {
     68                 throw new CannotCompileException(e);
     69             }
     70 
     71         super.toBytecode(out);
     72     }
     73 
     74     /**
     75      * Adds constructors inhrited from the super class.
     76      *
     77      * <p>After this method is called, the class inherits all the
     78      * constructors from the super class.  The added constructor
     79      * calls the super's constructor with the same signature.
     80      */
     81     public void inheritAllConstructors()
     82         throws CannotCompileException, NotFoundException
     83     {
     84         CtClass superclazz;
     85         CtConstructor[] cs;
     86 
     87         superclazz = getSuperclass();
     88         cs = superclazz.getDeclaredConstructors();
     89 
     90         int n = 0;
     91         for (int i = 0; i < cs.length; ++i) {
     92             CtConstructor c = cs[i];
     93             int mod = c.getModifiers();
     94             if (isInheritable(mod, superclazz)) {
     95                 CtConstructor cons
     96                     = CtNewConstructor.make(c.getParameterTypes(),
     97                                             c.getExceptionTypes(), this);
     98                 cons.setModifiers(mod & (Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE));
     99                 addConstructor(cons);
    100                 ++n;
    101             }
    102         }
    103 
    104         if (n < 1)
    105             throw new CannotCompileException(
    106                         "no inheritable constructor in " + superclazz.getName());
    107 
    108     }
    109 
    110     private boolean isInheritable(int mod, CtClass superclazz) {
    111         if (Modifier.isPrivate(mod))
    112             return false;
    113 
    114         if (Modifier.isPackage(mod)) {
    115             String pname = getPackageName();
    116             String pname2 = superclazz.getPackageName();
    117             if (pname == null)
    118                 return pname2 == null;
    119             else
    120                 return pname.equals(pname2);
    121         }
    122 
    123         return true;
    124     }
    125 }
    126