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 16package javassist; 17 18import java.io.DataOutputStream; 19import java.io.IOException; 20import javassist.bytecode.ClassFile; 21 22class 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