169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/* 269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Javassist, a Java-bytecode translator toolkit. 369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved. 469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The contents of this file are subject to the Mozilla Public License Version 669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1.1 (the "License"); you may not use this file except in compliance with 769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the License. Alternatively, the contents of this file may be used under 869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the terms of the GNU Lesser General Public License Version 2.1 or later. 969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Software distributed under the License is distributed on an "AS IS" basis, 1169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 1269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * for the specific language governing rights and limitations under the 1369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * License. 1469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 1569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 1669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpackage javassist; 1769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 1869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.io.DataOutputStream; 1969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.io.IOException; 2069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.ClassFile; 2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalclass CtNewClass extends CtClassType { 2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* true if the class is an interface. 2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal protected boolean hasConstructor; 2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtNewClass(String name, ClassPool cp, 2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal boolean isInterface, CtClass superclass) { 2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal super(name, cp); 3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal wasChanged = true; 3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String superName; 3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (isInterface || superclass == null) 3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal superName = null; 3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal superName = superclass.getName(); 3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal classfile = new ClassFile(isInterface, name, superName); 3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (isInterface && superclass != null) 3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal classfile.setInterfaces(new String[] { superclass.getName() }); 4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal setModifiers(Modifier.setPublic(getModifiers())); 4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal hasConstructor = isInterface; 4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal protected void extendToString(StringBuffer buffer) { 4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (hasConstructor) 4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal buffer.append("hasConstructor "); 4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal super.extendToString(buffer); 5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void addConstructor(CtConstructor c) 5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CannotCompileException 5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal hasConstructor = true; 5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal super.addConstructor(c); 5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void toBytecode(DataOutputStream out) 6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CannotCompileException, IOException 6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (!hasConstructor) 6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal try { 6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal inheritAllConstructors(); 6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal hasConstructor = true; 6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (NotFoundException e) { 6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CannotCompileException(e); 6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal super.toBytecode(out); 7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Adds constructors inhrited from the super class. 7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>After this method is called, the class inherits all the 7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * constructors from the super class. The added constructor 7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * calls the super's constructor with the same signature. 8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void inheritAllConstructors() 8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CannotCompileException, NotFoundException 8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtClass superclazz; 8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtConstructor[] cs; 8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal superclazz = getSuperclass(); 8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal cs = superclazz.getDeclaredConstructors(); 8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int n = 0; 9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < cs.length; ++i) { 9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtConstructor c = cs[i]; 9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int mod = c.getModifiers(); 9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (isInheritable(mod, superclazz)) { 9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtConstructor cons 9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal = CtNewConstructor.make(c.getParameterTypes(), 9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal c.getExceptionTypes(), this); 9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal cons.setModifiers(mod & (Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE)); 9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal addConstructor(cons); 10069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ++n; 10169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 10269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 10369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 10469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (n < 1) 10569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CannotCompileException( 10669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal "no inheritable constructor in " + superclazz.getName()); 10769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 10869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 10969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 11069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private boolean isInheritable(int mod, CtClass superclazz) { 11169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (Modifier.isPrivate(mod)) 11269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return false; 11369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 11469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (Modifier.isPackage(mod)) { 11569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String pname = getPackageName(); 11669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String pname2 = superclazz.getPackageName(); 11769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (pname == null) 11869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return pname2 == null; 11969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 12069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return pname.equals(pname2); 12169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 12269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 12369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return true; 12469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 12569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal} 126