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 javassist.bytecode.*;
1969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.compiler.Javac;
2069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.compiler.CompileError;
2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.expr.ExprEditor;
2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/**
2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>CtBehavior</code> represents a method, a constructor,
2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * or a static constructor (class initializer).
2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * It is the abstract super class of
2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>CtMethod</code> and <code>CtConstructor</code>.
2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */
2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpublic abstract class CtBehavior extends CtMember {
3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    protected MethodInfo methodInfo;
3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    protected CtBehavior(CtClass clazz, MethodInfo minfo) {
3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        super(clazz);
3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        methodInfo = minfo;
3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param isCons        true if this is a constructor.
3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    void copy(CtBehavior src, boolean isCons, ClassMap map)
4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws CannotCompileException
4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        CtClass declaring = declaringClass;
4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        MethodInfo srcInfo = src.methodInfo;
4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        CtClass srcClass = src.getDeclaringClass();
4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ConstPool cp = declaring.getClassFile2().getConstPool();
4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        map = new ClassMap(map);
4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        map.put(srcClass.getName(), declaring.getName());
5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        try {
5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            boolean patch = false;
5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            CtClass srcSuper = srcClass.getSuperclass();
5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            CtClass destSuper = declaring.getSuperclass();
5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            String destSuperName = null;
5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (srcSuper != null && destSuper != null) {
5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                String srcSuperName = srcSuper.getName();
5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                destSuperName = destSuper.getName();
5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                if (!srcSuperName.equals(destSuperName))
5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    if (srcSuperName.equals(CtClass.javaLangObject))
6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        patch = true;
6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    else
6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        map.putIfNone(srcSuperName, destSuperName);
6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            // a stack map table is copied from srcInfo.
6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            methodInfo = new MethodInfo(cp, srcInfo.getName(), srcInfo, map);
6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (isCons && patch)
6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                methodInfo.setSuperclass(destSuperName);
6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        catch (NotFoundException e) {
7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new CannotCompileException(e);
7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        catch (BadBytecode e) {
7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new CannotCompileException(e);
7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    protected void extendToString(StringBuffer buffer) {
7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        buffer.append(' ');
8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        buffer.append(getName());
8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        buffer.append(' ');
8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        buffer.append(methodInfo.getDescriptor());
8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the method or constructor name followed by parameter types
8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * such as <code>javassist.CtBehavior.stBody(String)</code>.
8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @since 3.5
9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public abstract String getLongName();
9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the MethodInfo representing this method/constructor in the
9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * class file.
9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public MethodInfo getMethodInfo() {
9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        declaringClass.checkModify();
9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return methodInfo;
10069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
10169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
10269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
10369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the MethodInfo representing the method/constructor in the
10469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * class file (read only).
10569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Normal applications do not need calling this method.  Use
10669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <code>getMethodInfo()</code>.
10769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
10869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <p>The <code>MethodInfo</code> object obtained by this method
10969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * is read only.  Changes to this object might not be reflected
11069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * on a class file generated by <code>toBytecode()</code>,
11169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <code>toClass()</code>, etc in <code>CtClass</code>.
11269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
11369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <p>This method is available even if the <code>CtClass</code>
11469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * containing this method is frozen.  However, if the class is
11569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * frozen, the <code>MethodInfo</code> might be also pruned.
11669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
11769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see #getMethodInfo()
11869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see CtClass#isFrozen()
11969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see CtClass#prune()
12069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
12169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public MethodInfo getMethodInfo2() { return methodInfo; }
12269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
12369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
12469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Obtains the modifiers of the method/constructor.
12569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
12669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @return          modifiers encoded with
12769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  <code>javassist.Modifier</code>.
12869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see Modifier
12969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
13069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public int getModifiers() {
13169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return AccessFlag.toModifier(methodInfo.getAccessFlags());
13269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
13369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
13469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
13569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Sets the encoded modifiers of the method/constructor.
13669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
13769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <p>Changing the modifiers may cause a problem.
13869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * For example, if a non-static method is changed to static,
13969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * the method will be rejected by the bytecode verifier.
14069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
14169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see Modifier
14269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
14369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void setModifiers(int mod) {
14469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        declaringClass.checkModify();
14569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        methodInfo.setAccessFlags(AccessFlag.of(mod));
14669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
14769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
14869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
14969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns true if the class has the specified annotation class.
15069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
15169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param clz the annotation class.
15269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @return <code>true</code> if the annotation is found,
15369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *         otherwise <code>false</code>.
15469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @since 3.11
15569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
15669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public boolean hasAnnotation(Class clz) {
15769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal       MethodInfo mi = getMethodInfo2();
15869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal       AnnotationsAttribute ainfo = (AnnotationsAttribute)
15969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                   mi.getAttribute(AnnotationsAttribute.invisibleTag);
16069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal       AnnotationsAttribute ainfo2 = (AnnotationsAttribute)
16169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                   mi.getAttribute(AnnotationsAttribute.visibleTag);
16269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal       return CtClassType.hasAnnotationType(clz,
16369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                            getDeclaringClass().getClassPool(),
16469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                            ainfo, ainfo2);
16569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
16669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
16769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
16869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the annotation if the class has the specified annotation class.
16969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * For example, if an annotation <code>@Author</code> is associated
17069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * with this method/constructor, an <code>Author</code> object is returned.
17169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * The member values can be obtained by calling methods on
17269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * the <code>Author</code> object.
17369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
17469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param clz the annotation class.
17569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @return the annotation if found, otherwise <code>null</code>.
17669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @since 3.11
17769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
17869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public Object getAnnotation(Class clz) throws ClassNotFoundException {
17969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal       MethodInfo mi = getMethodInfo2();
18069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal       AnnotationsAttribute ainfo = (AnnotationsAttribute)
18169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                   mi.getAttribute(AnnotationsAttribute.invisibleTag);
18269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal       AnnotationsAttribute ainfo2 = (AnnotationsAttribute)
18369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                   mi.getAttribute(AnnotationsAttribute.visibleTag);
18469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal       return CtClassType.getAnnotationType(clz,
18569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                            getDeclaringClass().getClassPool(),
18669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                            ainfo, ainfo2);
18769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
18869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
18969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
19069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the annotations associated with this method or constructor.
19169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
19269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @return an array of annotation-type objects.
19369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see #getAvailableAnnotations()
19469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @since 3.1
19569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
19669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public Object[] getAnnotations() throws ClassNotFoundException {
19769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal       return getAnnotations(false);
19869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal   }
19969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
20069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
20169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the annotations associated with this method or constructor.
20269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * If any annotations are not on the classpath, they are not included
20369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * in the returned array.
20469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
20569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @return an array of annotation-type objects.
20669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see #getAnnotations()
20769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @since 3.3
20869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
20969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public Object[] getAvailableAnnotations(){
21069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal       try{
21169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal           return getAnnotations(true);
21269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal       }
21369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal       catch (ClassNotFoundException e){
21469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal           throw new RuntimeException("Unexpected exception", e);
21569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal       }
21669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
21769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
21869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private Object[] getAnnotations(boolean ignoreNotFound)
21969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal       throws ClassNotFoundException
22069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
22169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal       MethodInfo mi = getMethodInfo2();
22269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal       AnnotationsAttribute ainfo = (AnnotationsAttribute)
22369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                   mi.getAttribute(AnnotationsAttribute.invisibleTag);
22469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal       AnnotationsAttribute ainfo2 = (AnnotationsAttribute)
22569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                   mi.getAttribute(AnnotationsAttribute.visibleTag);
22669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal       return CtClassType.toAnnotationType(ignoreNotFound,
22769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                           getDeclaringClass().getClassPool(),
22869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                           ainfo, ainfo2);
22969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
23069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
23169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
23269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the parameter annotations associated with this method or constructor.
23369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
23469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @return an array of annotation-type objects.  The length of the returned array is
23569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * equal to the number of the formal parameters.  If each parameter has no
23669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * annotation, the elements of the returned array are empty arrays.
23769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
23869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see #getAvailableParameterAnnotations()
23969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see #getAnnotations()
24069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @since 3.1
24169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
24269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public Object[][] getParameterAnnotations() throws ClassNotFoundException {
24369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return getParameterAnnotations(false);
24469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
24569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
24669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
24769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the parameter annotations associated with this method or constructor.
24869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * If any annotations are not on the classpath, they are not included in the
24969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * returned array.
25069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
25169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @return an array of annotation-type objects.  The length of the returned array is
25269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * equal to the number of the formal parameters.  If each parameter has no
25369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * annotation, the elements of the returned array are empty arrays.
25469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
25569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see #getParameterAnnotations()
25669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see #getAvailableAnnotations()
25769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @since 3.3
25869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
25969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public Object[][] getAvailableParameterAnnotations(){
26069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        try {
26169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return getParameterAnnotations(true);
26269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
26369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        catch(ClassNotFoundException e) {
26469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new RuntimeException("Unexpected exception", e);
26569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
26669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
26769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
26869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    Object[][] getParameterAnnotations(boolean ignoreNotFound)
26969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws ClassNotFoundException
27069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
27169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        MethodInfo mi = getMethodInfo2();
27269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ParameterAnnotationsAttribute ainfo = (ParameterAnnotationsAttribute)
27369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    mi.getAttribute(ParameterAnnotationsAttribute.invisibleTag);
27469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ParameterAnnotationsAttribute ainfo2 = (ParameterAnnotationsAttribute)
27569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    mi.getAttribute(ParameterAnnotationsAttribute.visibleTag);
27669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return CtClassType.toAnnotationType(ignoreNotFound,
27769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                            getDeclaringClass().getClassPool(),
27869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                            ainfo, ainfo2, mi);
27969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
28069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
28169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
28269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Obtains parameter types of this method/constructor.
28369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
28469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public CtClass[] getParameterTypes() throws NotFoundException {
28569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return Descriptor.getParameterTypes(methodInfo.getDescriptor(),
28669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                            declaringClass.getClassPool());
28769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
28869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
28969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
29069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Obtains the type of the returned value.
29169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
29269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    CtClass getReturnType0() throws NotFoundException {
29369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return Descriptor.getReturnType(methodInfo.getDescriptor(),
29469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                        declaringClass.getClassPool());
29569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
29669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
29769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
29869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the method signature (the parameter types
29969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * and the return type).
30069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * The method signature is represented by a character string
30169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * called method descriptor, which is defined in the JVM specification.
30269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * If two methods/constructors have
30369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * the same parameter types
30469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * and the return type, <code>getSignature()</code> returns the
30569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * same string (the return type of constructors is <code>void</code>).
30669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
30769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <p>Note that the returned string is not the type signature
30869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * contained in the <code>SignatureAttirbute</code>.  It is
30969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * a descriptor.  To obtain a type signature, call the following
31069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * methods:
31169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
31269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <ul><pre>getMethodInfo().getAttribute(SignatureAttribute.tag)
31369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * </pre></ul>
31469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
31569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see javassist.bytecode.Descriptor
31669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see javassist.bytecode.SignatureAttribute
31769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
31869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public String getSignature() {
31969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return methodInfo.getDescriptor();
32069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
32169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
32269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
32369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Obtains exceptions that this method/constructor may throw.
32469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
32569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @return a zero-length array if there is no throws clause.
32669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
32769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public CtClass[] getExceptionTypes() throws NotFoundException {
32869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        String[] exceptions;
32969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ExceptionsAttribute ea = methodInfo.getExceptionsAttribute();
33069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (ea == null)
33169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            exceptions = null;
33269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else
33369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            exceptions = ea.getExceptions();
33469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
33569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return declaringClass.getClassPool().get(exceptions);
33669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
33769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
33869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
33969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Sets exceptions that this method/constructor may throw.
34069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
34169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void setExceptionTypes(CtClass[] types) throws NotFoundException {
34269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        declaringClass.checkModify();
34369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (types == null || types.length == 0) {
34469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            methodInfo.removeExceptionsAttribute();
34569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return;
34669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
34769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
34869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        String[] names = new String[types.length];
34969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 0; i < types.length; ++i)
35069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            names[i] = types[i].getName();
35169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
35269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ExceptionsAttribute ea = methodInfo.getExceptionsAttribute();
35369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (ea == null) {
35469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            ea = new ExceptionsAttribute(methodInfo.getConstPool());
35569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            methodInfo.setExceptionsAttribute(ea);
35669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
35769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
35869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ea.setExceptions(names);
35969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
36069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
36169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
36269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns true if the body is empty.
36369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
36469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public abstract boolean isEmpty();
36569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
36669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
36769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Sets a method/constructor body.
36869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
36969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param src       the source code representing the body.
37069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  It must be a single statement or block.
37169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  If it is <code>null</code>, the substituted
37269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  body does nothing except returning zero or null.
37369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
37469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void setBody(String src) throws CannotCompileException {
37569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        setBody(src, null, null);
37669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
37769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
37869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
37969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Sets a method/constructor body.
38069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
38169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param src       the source code representing the body.
38269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  It must be a single statement or block.
38369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  If it is <code>null</code>, the substituted
38469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  body does nothing except returning zero or null.
38569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param delegateObj       the source text specifying the object
38669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                          that is called on by <code>$proceed()</code>.
38769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param delegateMethod    the name of the method
38869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                          that is called by <code>$proceed()</code>.
38969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
39069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void setBody(String src,
39169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        String delegateObj, String delegateMethod)
39269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws CannotCompileException
39369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
39469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        CtClass cc = declaringClass;
39569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        cc.checkModify();
39669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        try {
39769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            Javac jv = new Javac(cc);
39869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (delegateMethod != null)
39969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                jv.recordProceed(delegateObj, delegateMethod);
40069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
40169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            Bytecode b = jv.compileBody(this, src);
40269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            methodInfo.setCodeAttribute(b.toCodeAttribute());
40369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            methodInfo.setAccessFlags(methodInfo.getAccessFlags()
40469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                      & ~AccessFlag.ABSTRACT);
40569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            methodInfo.rebuildStackMapIf6(cc.getClassPool(), cc.getClassFile2());
40669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            declaringClass.rebuildClassFile();
40769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
40869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        catch (CompileError e) {
40969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new CannotCompileException(e);
41069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        } catch (BadBytecode e) {
41169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new CannotCompileException(e);
41269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
41369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
41469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
41569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    static void setBody0(CtClass srcClass, MethodInfo srcInfo,
41669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                         CtClass destClass, MethodInfo destInfo,
41769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                         ClassMap map)
41869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws CannotCompileException
41969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
42069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        destClass.checkModify();
42169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
42269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        map = new ClassMap(map);
42369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        map.put(srcClass.getName(), destClass.getName());
42469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        try {
42569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            CodeAttribute cattr = srcInfo.getCodeAttribute();
42669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (cattr != null) {
42769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                ConstPool cp = destInfo.getConstPool();
42869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                CodeAttribute ca = (CodeAttribute)cattr.copy(cp, map);
42969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                destInfo.setCodeAttribute(ca);
43069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                // a stack map table is copied to destInfo.
43169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
43269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
43369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        catch (CodeAttribute.RuntimeCopyException e) {
43469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            /* the exception may be thrown by copy() in CodeAttribute.
43569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal             */
43669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new CannotCompileException(e);
43769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
43869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
43969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        destInfo.setAccessFlags(destInfo.getAccessFlags()
44069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                & ~AccessFlag.ABSTRACT);
44169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        destClass.rebuildClassFile();
44269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
44369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
44469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
44569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Obtains an attribute with the given name.
44669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * If that attribute is not found in the class file, this
44769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * method returns null.
44869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
44969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <p>Note that an attribute is a data block specified by
45069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * the class file format.  It is not an annotation.
45169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * See {@link javassist.bytecode.AttributeInfo}.
45269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
45369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param name              attribute name
45469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
45569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public byte[] getAttribute(String name) {
45669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        AttributeInfo ai = methodInfo.getAttribute(name);
45769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (ai == null)
45869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return null;
45969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else
46069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return ai.get();
46169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
46269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
46369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
46469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Adds an attribute. The attribute is saved in the class file.
46569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
46669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <p>Note that an attribute is a data block specified by
46769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * the class file format.  It is not an annotation.
46869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * See {@link javassist.bytecode.AttributeInfo}.
46969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
47069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param name      attribute name
47169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param data      attribute value
47269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
47369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void setAttribute(String name, byte[] data) {
47469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        declaringClass.checkModify();
47569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        methodInfo.addAttribute(new AttributeInfo(methodInfo.getConstPool(),
47669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                                  name, data));
47769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
47869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
47969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
48069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Declares to use <code>$cflow</code> for this method/constructor.
48169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * If <code>$cflow</code> is used, the class files modified
48269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * with Javassist requires a support class
48369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <code>javassist.runtime.Cflow</code> at runtime
48469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * (other Javassist classes are not required at runtime).
48569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
48669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <p>Every <code>$cflow</code> variable is given a unique name.
48769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * For example, if the given name is <code>"Point.paint"</code>,
48869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * then the variable is indicated by <code>$cflow(Point.paint)</code>.
48969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
49069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param name      <code>$cflow</code> name.  It can include
49169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  alphabets, numbers, <code>_</code>,
49269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  <code>$</code>, and <code>.</code> (dot).
49369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
49469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see javassist.runtime.Cflow
49569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
49669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void useCflow(String name) throws CannotCompileException {
49769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        CtClass cc = declaringClass;
49869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        cc.checkModify();
49969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ClassPool pool = cc.getClassPool();
50069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        String fname;
50169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int i = 0;
50269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        while (true) {
50369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            fname = "_cflow$" + i++;
50469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            try {
50569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                cc.getDeclaredField(fname);
50669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
50769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            catch(NotFoundException e) {
50869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                break;
50969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
51069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
51169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
51269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        pool.recordCflow(name, declaringClass.getName(), fname);
51369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        try {
51469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            CtClass type = pool.get("javassist.runtime.Cflow");
51569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            CtField field = new CtField(type, fname, cc);
51669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            field.setModifiers(Modifier.PUBLIC | Modifier.STATIC);
51769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            cc.addField(field, CtField.Initializer.byNew(type));
51869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            insertBefore(fname + ".enter();", false);
51969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            String src = fname + ".exit();";
52069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            insertAfter(src, true);
52169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
52269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        catch (NotFoundException e) {
52369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new CannotCompileException(e);
52469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
52569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
52669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
52769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
52869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Declares a new local variable.  The scope of this variable is the
52969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * whole method body.  The initial value of that variable is not set.
53069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * The declared variable can be accessed in the code snippet inserted
53169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * by <code>insertBefore()</code>, <code>insertAfter()</code>, etc.
53269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
53369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <p>If the second parameter <code>asFinally</code> to
53469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <code>insertAfter()</code> is true, the declared local variable
53569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * is not visible from the code inserted by <code>insertAfter()</code>.
53669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
53769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param name      the name of the variable
53869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param type      the type of the variable
53969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see #insertBefore(String)
54069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see #insertAfter(String)
54169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
54269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void addLocalVariable(String name, CtClass type)
54369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws CannotCompileException
54469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
54569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        declaringClass.checkModify();
54669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ConstPool cp = methodInfo.getConstPool();
54769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        CodeAttribute ca = methodInfo.getCodeAttribute();
54869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (ca == null)
54969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new CannotCompileException("no method body");
55069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
55169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        LocalVariableAttribute va = (LocalVariableAttribute)ca.getAttribute(
55269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                                LocalVariableAttribute.tag);
55369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (va == null) {
55469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            va = new LocalVariableAttribute(cp);
55569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            ca.getAttributes().add(va);
55669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
55769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
55869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int maxLocals = ca.getMaxLocals();
55969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        String desc = Descriptor.of(type);
56069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        va.addEntry(0, ca.getCodeLength(),
56169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    cp.addUtf8Info(name), cp.addUtf8Info(desc), maxLocals);
56269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ca.setMaxLocals(maxLocals + Descriptor.dataSize(desc));
56369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
56469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
56569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
56669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Inserts a new parameter, which becomes the first parameter.
56769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
56869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void insertParameter(CtClass type)
56969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws CannotCompileException
57069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
57169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        declaringClass.checkModify();
57269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        String desc = methodInfo.getDescriptor();
57369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        String desc2 = Descriptor.insertParameter(type, desc);
57469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        try {
57569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            addParameter2(Modifier.isStatic(getModifiers()) ? 0 : 1, type, desc);
57669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
57769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        catch (BadBytecode e) {
57869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new CannotCompileException(e);
57969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
58069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
58169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        methodInfo.setDescriptor(desc2);
58269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
58369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
58469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
58569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Appends a new parameter, which becomes the last parameter.
58669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
58769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void addParameter(CtClass type)
58869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws CannotCompileException
58969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
59069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        declaringClass.checkModify();
59169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        String desc = methodInfo.getDescriptor();
59269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        String desc2 = Descriptor.appendParameter(type, desc);
59369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int offset = Modifier.isStatic(getModifiers()) ? 0 : 1;
59469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        try {
59569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            addParameter2(offset + Descriptor.paramSize(desc), type, desc);
59669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
59769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        catch (BadBytecode e) {
59869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new CannotCompileException(e);
59969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
60069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
60169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        methodInfo.setDescriptor(desc2);
60269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
60369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
60469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private void addParameter2(int where, CtClass type, String desc)
60569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws BadBytecode
60669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
60769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        CodeAttribute ca = methodInfo.getCodeAttribute();
60869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (ca != null) {
60969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int size = 1;
61069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            char typeDesc = 'L';
61169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int classInfo = 0;
61269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (type.isPrimitive()) {
61369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                CtPrimitiveType cpt = (CtPrimitiveType)type;
61469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                size = cpt.getDataSize();
61569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                typeDesc = cpt.getDescriptor();
61669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
61769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else
61869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                classInfo = methodInfo.getConstPool().addClassInfo(type);
61969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
62069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            ca.insertLocalVar(where, size);
62169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            LocalVariableAttribute va
62269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                            = (LocalVariableAttribute)
62369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                              ca.getAttribute(LocalVariableAttribute.tag);
62469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (va != null)
62569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                va.shiftIndex(where, size);
62669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
62769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            StackMapTable smt = (StackMapTable)ca.getAttribute(StackMapTable.tag);
62869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (smt != null)
62969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                smt.insertLocal(where, StackMapTable.typeTagOf(typeDesc), classInfo);
63069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
63169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            StackMap sm = (StackMap)ca.getAttribute(StackMap.tag);
63269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (sm != null)
63369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                sm.insertLocal(where, StackMapTable.typeTagOf(typeDesc), classInfo);
63469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
63569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
63669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
63769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
63869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Modifies the method/constructor body.
63969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
64069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param converter         specifies how to modify.
64169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
64269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void instrument(CodeConverter converter)
64369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws CannotCompileException
64469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
64569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        declaringClass.checkModify();
64669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ConstPool cp = methodInfo.getConstPool();
64769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        converter.doit(getDeclaringClass(), methodInfo, cp);
64869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
64969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
65069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
65169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Modifies the method/constructor body.
65269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
65369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param editor            specifies how to modify.
65469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
65569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void instrument(ExprEditor editor)
65669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws CannotCompileException
65769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
65869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        // if the class is not frozen,
65969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        // does not turn the modified flag on.
66069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (declaringClass.isFrozen())
66169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            declaringClass.checkModify();
66269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
66369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (editor.doit(declaringClass, methodInfo))
66469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            declaringClass.checkModify();
66569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
66669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
66769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
66869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Inserts bytecode at the beginning of the body.
66969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
67069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <p>If this object represents a constructor,
67169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * the bytecode is inserted before
67269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * a constructor in the super class or this class is called.
67369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Therefore, the inserted bytecode is subject to constraints described
67469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * in Section 4.8.2 of The Java Virtual Machine Specification (2nd ed).
67569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * For example, it cannot access instance fields or methods although
67669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * it may assign a value to an instance field directly declared in this
67769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * class.  Accessing static fields and methods is allowed.
67869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Use <code>insertBeforeBody()</code> in <code>CtConstructor</code>.
67969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
68069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param src       the source code representing the inserted bytecode.
68169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  It must be a single statement or block.
68269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see CtConstructor#insertBeforeBody(String)
68369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
68469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void insertBefore(String src) throws CannotCompileException {
68569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        insertBefore(src, true);
68669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
68769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
68869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private void insertBefore(String src, boolean rebuild)
68969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws CannotCompileException
69069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
69169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        CtClass cc = declaringClass;
69269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        cc.checkModify();
69369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        CodeAttribute ca = methodInfo.getCodeAttribute();
69469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (ca == null)
69569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new CannotCompileException("no method body");
69669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
69769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        CodeIterator iterator = ca.iterator();
69869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Javac jv = new Javac(cc);
69969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        try {
70069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int nvars = jv.recordParams(getParameterTypes(),
70169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                        Modifier.isStatic(getModifiers()));
70269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            jv.recordParamNames(ca, nvars);
70369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            jv.recordLocalVariables(ca, 0);
70469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            jv.recordType(getReturnType0());
70569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            jv.compileStmnt(src);
70669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            Bytecode b = jv.getBytecode();
70769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int stack = b.getMaxStack();
70869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int locals = b.getMaxLocals();
70969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
71069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (stack > ca.getMaxStack())
71169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                ca.setMaxStack(stack);
71269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
71369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (locals > ca.getMaxLocals())
71469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                ca.setMaxLocals(locals);
71569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
71669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int pos = iterator.insertEx(b.get());
71769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            iterator.insert(b.getExceptionTable(), pos);
71869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (rebuild)
71969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                methodInfo.rebuildStackMapIf6(cc.getClassPool(), cc.getClassFile2());
72069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
72169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        catch (NotFoundException e) {
72269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new CannotCompileException(e);
72369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
72469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        catch (CompileError e) {
72569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new CannotCompileException(e);
72669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
72769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        catch (BadBytecode e) {
72869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new CannotCompileException(e);
72969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
73069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
73169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
73269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
73369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Inserts bytecode at the end of the body.
73469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * The bytecode is inserted just before every return insturction.
73569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * It is not executed when an exception is thrown.
73669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
73769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param src       the source code representing the inserted bytecode.
73869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  It must be a single statement or block.
73969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
74069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void insertAfter(String src)
74169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws CannotCompileException
74269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
74369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        insertAfter(src, false);
74469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
74569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
74669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
74769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Inserts bytecode at the end of the body.
74869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * The bytecode is inserted just before every return insturction.
74969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
75069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param src       the source code representing the inserted bytecode.
75169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  It must be a single statement or block.
75269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param asFinally         true if the inserted bytecode is executed
75369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  not only when the control normally returns
75469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  but also when an exception is thrown.
75569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  If this parameter is true, the inserted code cannot
75669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  access local variables.
75769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
75869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void insertAfter(String src, boolean asFinally)
75969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws CannotCompileException
76069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
76169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        CtClass cc = declaringClass;
76269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        cc.checkModify();
76369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ConstPool pool = methodInfo.getConstPool();
76469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        CodeAttribute ca = methodInfo.getCodeAttribute();
76569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (ca == null)
76669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new CannotCompileException("no method body");
76769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
76869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        CodeIterator iterator = ca.iterator();
76969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int retAddr = ca.getMaxLocals();
77069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Bytecode b = new Bytecode(pool, 0, retAddr + 1);
77169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        b.setStackDepth(ca.getMaxStack() + 1);
77269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Javac jv = new Javac(b, cc);
77369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        try {
77469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int nvars = jv.recordParams(getParameterTypes(),
77569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                        Modifier.isStatic(getModifiers()));
77669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            jv.recordParamNames(ca, nvars);
77769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            CtClass rtype = getReturnType0();
77869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int varNo = jv.recordReturnType(rtype, true);
77969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            jv.recordLocalVariables(ca, 0);
78069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
78169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            // finally clause for exceptions
78269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int handlerLen = insertAfterHandler(asFinally, b, rtype, varNo,
78369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                                jv, src);
78469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            // finally clause for normal termination
78569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            insertAfterAdvice(b, jv, src, pool, rtype, varNo);
78669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
78769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            ca.setMaxStack(b.getMaxStack());
78869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            ca.setMaxLocals(b.getMaxLocals());
78969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
79069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int gapPos = iterator.append(b.get());
79169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            iterator.append(b.getExceptionTable(), gapPos);
79269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
79369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (asFinally)
79469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                ca.getExceptionTable().add(getStartPosOfBody(ca), gapPos, gapPos, 0);
79569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
79669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int gapLen = iterator.getCodeLength() - gapPos - handlerLen;
79769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int subr = iterator.getCodeLength() - gapLen;
79869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
79969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            while (iterator.hasNext()) {
80069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                int pos = iterator.next();
80169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                if (pos >= subr)
80269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    break;
80369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
80469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                int c = iterator.byteAt(pos);
80569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                if (c == Opcode.ARETURN || c == Opcode.IRETURN
80669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    || c == Opcode.FRETURN || c == Opcode.LRETURN
80769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    || c == Opcode.DRETURN || c == Opcode.RETURN) {
80869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    insertGoto(iterator, subr, pos);
80969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    subr = iterator.getCodeLength() - gapLen;
81069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                }
81169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
81269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
81369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            methodInfo.rebuildStackMapIf6(cc.getClassPool(), cc.getClassFile2());
81469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
81569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        catch (NotFoundException e) {
81669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new CannotCompileException(e);
81769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
81869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        catch (CompileError e) {
81969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new CannotCompileException(e);
82069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
82169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        catch (BadBytecode e) {
82269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new CannotCompileException(e);
82369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
82469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
82569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
82669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private void insertAfterAdvice(Bytecode code, Javac jv, String src,
82769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                   ConstPool cp, CtClass rtype, int varNo)
82869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws CompileError
82969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
83069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (rtype == CtClass.voidType) {
83169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            code.addOpcode(Opcode.ACONST_NULL);
83269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            code.addAstore(varNo);
83369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            jv.compileStmnt(src);
83469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            code.addOpcode(Opcode.RETURN);
83569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (code.getMaxLocals() < 1)
83669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                code.setMaxLocals(1);
83769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
83869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else {
83969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            code.addStore(varNo, rtype);
84069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            jv.compileStmnt(src);
84169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            code.addLoad(varNo, rtype);
84269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (rtype.isPrimitive())
84369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                code.addOpcode(((CtPrimitiveType)rtype).getReturnOp());
84469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else
84569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                code.addOpcode(Opcode.ARETURN);
84669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
84769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
84869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
84969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /*
85069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * assert subr > pos
85169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
85269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private void insertGoto(CodeIterator iterator, int subr, int pos)
85369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws BadBytecode
85469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
85569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        iterator.setMark(subr);
85669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        // the gap length might be a multiple of 4.
85769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        iterator.writeByte(Opcode.NOP, pos);
85869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        boolean wide = subr + 2 - pos > Short.MAX_VALUE;
85969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        pos = iterator.insertGapAt(pos, wide ? 4 : 2, false).position;
86069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int offset = iterator.getMark() - pos;
86169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (wide) {
86269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            iterator.writeByte(Opcode.GOTO_W, pos);
86369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            iterator.write32bit(offset, pos + 1);
86469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
86569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else if (offset <= Short.MAX_VALUE) {
86669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            iterator.writeByte(Opcode.GOTO, pos);
86769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            iterator.write16bit(offset, pos + 1);
86869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
86969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else {
87069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            pos = iterator.insertGapAt(pos, 2, false).position;
87169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            iterator.writeByte(Opcode.GOTO_W, pos);
87269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            iterator.write32bit(iterator.getMark() - pos, pos + 1);
87369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
87469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
87569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
87669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /* insert a finally clause
87769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
87869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private int insertAfterHandler(boolean asFinally, Bytecode b,
87969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                   CtClass rtype, int returnVarNo,
88069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                   Javac javac, String src)
88169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws CompileError
88269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
88369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (!asFinally)
88469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return 0;
88569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
88669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int var = b.getMaxLocals();
88769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        b.incMaxLocals(1);
88869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int pc = b.currentPc();
88969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        b.addAstore(var);   // store an exception
89069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (rtype.isPrimitive()) {
89169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            char c = ((CtPrimitiveType)rtype).getDescriptor();
89269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (c == 'D') {
89369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                b.addDconst(0.0);
89469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                b.addDstore(returnVarNo);
89569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
89669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else if (c == 'F') {
89769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                b.addFconst(0);
89869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                b.addFstore(returnVarNo);
89969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
90069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else if (c == 'J') {
90169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                b.addLconst(0);
90269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                b.addLstore(returnVarNo);
90369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
90469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else if (c == 'V') {
90569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                b.addOpcode(Opcode.ACONST_NULL);
90669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                b.addAstore(returnVarNo);
90769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
90869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else { // int, boolean, char, short, ...
90969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                b.addIconst(0);
91069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                b.addIstore(returnVarNo);
91169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
91269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
91369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else {
91469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            b.addOpcode(Opcode.ACONST_NULL);
91569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            b.addAstore(returnVarNo);
91669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
91769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
91869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        javac.compileStmnt(src);
91969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        b.addAload(var);
92069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        b.addOpcode(Opcode.ATHROW);
92169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return b.currentPc() - pc;
92269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
92369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
92469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /* -- OLD version --
92569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
92669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void insertAfter(String src) throws CannotCompileException {
92769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        declaringClass.checkModify();
92869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        CodeAttribute ca = methodInfo.getCodeAttribute();
92969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        CodeIterator iterator = ca.iterator();
93069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Bytecode b = new Bytecode(methodInfo.getConstPool(),
93169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                  ca.getMaxStack(), ca.getMaxLocals());
93269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        b.setStackDepth(ca.getMaxStack());
93369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Javac jv = new Javac(b, declaringClass);
93469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        try {
93569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            jv.recordParams(getParameterTypes(),
93669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                            Modifier.isStatic(getModifiers()));
93769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            CtClass rtype = getReturnType0();
93869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int varNo = jv.recordReturnType(rtype, true);
93969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            boolean isVoid = rtype == CtClass.voidType;
94069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (isVoid) {
94169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                b.addOpcode(Opcode.ACONST_NULL);
94269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                b.addAstore(varNo);
94369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                jv.compileStmnt(src);
94469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
94569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else {
94669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                b.addStore(varNo, rtype);
94769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                jv.compileStmnt(src);
94869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                b.addLoad(varNo, rtype);
94969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
95069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
95169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            byte[] code = b.get();
95269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            ca.setMaxStack(b.getMaxStack());
95369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            ca.setMaxLocals(b.getMaxLocals());
95469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            while (iterator.hasNext()) {
95569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                int pos = iterator.next();
95669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                int c = iterator.byteAt(pos);
95769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                if (c == Opcode.ARETURN || c == Opcode.IRETURN
95869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    || c == Opcode.FRETURN || c == Opcode.LRETURN
95969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    || c == Opcode.DRETURN || c == Opcode.RETURN)
96069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    iterator.insert(pos, code);
96169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
96269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
96369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        catch (NotFoundException e) {
96469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new CannotCompileException(e);
96569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
96669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        catch (CompileError e) {
96769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new CannotCompileException(e);
96869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
96969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        catch (BadBytecode e) {
97069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new CannotCompileException(e);
97169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
97269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
97369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    */
97469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
97569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
97669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Adds a catch clause that handles an exception thrown in the
97769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * body.  The catch clause must end with a return or throw statement.
97869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
97969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param src       the source code representing the catch clause.
98069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  It must be a single statement or block.
98169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param exceptionType     the type of the exception handled by the
98269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                          catch clause.
98369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
98469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void addCatch(String src, CtClass exceptionType)
98569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws CannotCompileException
98669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
98769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        addCatch(src, exceptionType, "$e");
98869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
98969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
99069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
99169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Adds a catch clause that handles an exception thrown in the
99269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * body.  The catch clause must end with a return or throw statement.
99369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
99469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param src       the source code representing the catch clause.
99569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  It must be a single statement or block.
99669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param exceptionType     the type of the exception handled by the
99769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                          catch clause.
99869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param exceptionName     the name of the variable containing the
99969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                          caught exception, for example,
100069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                          <code>$e</code>.
100169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
100269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void addCatch(String src, CtClass exceptionType,
100369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                         String exceptionName)
100469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws CannotCompileException
100569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
100669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        CtClass cc = declaringClass;
100769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        cc.checkModify();
100869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ConstPool cp = methodInfo.getConstPool();
100969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        CodeAttribute ca = methodInfo.getCodeAttribute();
101069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        CodeIterator iterator = ca.iterator();
101169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Bytecode b = new Bytecode(cp, ca.getMaxStack(), ca.getMaxLocals());
101269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        b.setStackDepth(1);
101369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Javac jv = new Javac(b, cc);
101469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        try {
101569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            jv.recordParams(getParameterTypes(),
101669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                            Modifier.isStatic(getModifiers()));
101769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int var = jv.recordVariable(exceptionType, exceptionName);
101869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            b.addAstore(var);
101969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            jv.compileStmnt(src);
102069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
102169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int stack = b.getMaxStack();
102269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int locals = b.getMaxLocals();
102369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
102469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (stack > ca.getMaxStack())
102569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                ca.setMaxStack(stack);
102669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
102769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (locals > ca.getMaxLocals())
102869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                ca.setMaxLocals(locals);
102969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
103069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int len = iterator.getCodeLength();
103169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int pos = iterator.append(b.get());
103269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            ca.getExceptionTable().add(getStartPosOfBody(ca), len, len,
103369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                       cp.addClassInfo(exceptionType));
103469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            iterator.append(b.getExceptionTable(), pos);
103569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            methodInfo.rebuildStackMapIf6(cc.getClassPool(), cc.getClassFile2());
103669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
103769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        catch (NotFoundException e) {
103869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new CannotCompileException(e);
103969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
104069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        catch (CompileError e) {
104169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new CannotCompileException(e);
104269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        } catch (BadBytecode e) {
104369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new CannotCompileException(e);
104469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
104569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
104669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
104769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /* CtConstructor overrides this method.
104869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
104969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    int getStartPosOfBody(CodeAttribute ca) throws CannotCompileException {
105069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return 0;
105169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
105269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
105369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
105469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Inserts bytecode at the specified line in the body.
105569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * It is equivalent to:
105669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
105769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <br><code>insertAt(lineNum, true, src)</code>
105869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
105969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <br>See this method as well.
106069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
106169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param lineNum   the line number.  The bytecode is inserted at the
106269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  beginning of the code at the line specified by this
106369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  line number.
106469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param src       the source code representing the inserted bytecode.
106569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  It must be a single statement or block.
106669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @return      the line number at which the bytecode has been inserted.
106769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
106869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see CtBehavior#insertAt(int,boolean,String)
106969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
107069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public int insertAt(int lineNum, String src)
107169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws CannotCompileException
107269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
107369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return insertAt(lineNum, true, src);
107469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
107569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
107669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
107769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Inserts bytecode at the specified line in the body.
107869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
107969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <p>If there is not
108069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * a statement at the specified line, the bytecode might be inserted
108169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * at the line including the first statement after that line specified.
108269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * For example, if there is only a closing brace at that line, the
108369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * bytecode would be inserted at another line below.
108469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * To know exactly where the bytecode will be inserted, call with
108569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <code>modify</code> set to <code>false</code>.
108669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
108769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param lineNum   the line number.  The bytecode is inserted at the
108869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  beginning of the code at the line specified by this
108969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  line number.
109069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param modify    if false, this method does not insert the bytecode.
109169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  It instead only returns the line number at which
109269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  the bytecode would be inserted.
109369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param src       the source code representing the inserted bytecode.
109469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  It must be a single statement or block.
109569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  If modify is false, the value of src can be null.
109669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @return      the line number at which the bytecode has been inserted.
109769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
109869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public int insertAt(int lineNum, boolean modify, String src)
109969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws CannotCompileException
110069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
110169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        CodeAttribute ca = methodInfo.getCodeAttribute();
110269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (ca == null)
110369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new CannotCompileException("no method body");
110469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
110569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        LineNumberAttribute ainfo
110669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            = (LineNumberAttribute)ca.getAttribute(LineNumberAttribute.tag);
110769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (ainfo == null)
110869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new CannotCompileException("no line number info");
110969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
111069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        LineNumberAttribute.Pc pc = ainfo.toNearPc(lineNum);
111169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        lineNum = pc.line;
111269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int index = pc.index;
111369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (!modify)
111469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return lineNum;
111569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
111669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        CtClass cc = declaringClass;
111769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        cc.checkModify();
111869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        CodeIterator iterator = ca.iterator();
111969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Javac jv = new Javac(cc);
112069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        try {
112169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            jv.recordLocalVariables(ca, index);
112269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            jv.recordParams(getParameterTypes(),
112369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                            Modifier.isStatic(getModifiers()));
112469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            jv.setMaxLocals(ca.getMaxLocals());
112569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            jv.compileStmnt(src);
112669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            Bytecode b = jv.getBytecode();
112769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int locals = b.getMaxLocals();
112869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int stack = b.getMaxStack();
112969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            ca.setMaxLocals(locals);
113069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
113169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            /* We assume that there is no values in the operand stack
113269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal             * at the position where the bytecode is inserted.
113369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal             */
113469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (stack > ca.getMaxStack())
113569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                ca.setMaxStack(stack);
113669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
113769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            index = iterator.insertAt(index, b.get());
113869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            iterator.insert(b.getExceptionTable(), index);
113969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            methodInfo.rebuildStackMapIf6(cc.getClassPool(), cc.getClassFile2());
114069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return lineNum;
114169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
114269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        catch (NotFoundException e) {
114369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new CannotCompileException(e);
114469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
114569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        catch (CompileError e) {
114669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new CannotCompileException(e);
114769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
114869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        catch (BadBytecode e) {
114969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new CannotCompileException(e);
115069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
115169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
115269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal}
1153