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