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