/Users/lyon/j4p/src/javassist/expr/Instanceof.java

1    /* 
2     * Javassist, a Java-bytecode translator toolkit. 
3     * Copyright (C) 1999-2003 Shigeru Chiba. All Rights Reserved. 
4     * 
5     * The contents of this file are subject to the Mozilla Public License Version 
6     * 1.1 (the "License"); you may not use this file except in compliance with 
7     * the License.  Alternatively, the contents of this file may be used under 
8     * the terms of the GNU Lesser General Public License Version 2.1 or later. 
9     * 
10    * Software distributed under the License is distributed on an "AS IS" basis, 
11    * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 
12    * for the specific language governing rights and limitations under the 
13    * License. 
14    */ 
15    
16   package javassist.expr; 
17    
18   import javassist.*; 
19   import javassist.bytecode.*; 
20   import javassist.compiler.*; 
21   import javassist.compiler.ast.ASTList; 
22    
23   /** 
24    * Instanceof operator. 
25    */ 
26   public class Instanceof extends Expr { 
27       /** 
28        * Undocumented constructor.  Do not use; internal-use only. 
29        */ 
30       Instanceof(int pos, CodeIterator i, CtClass declaring, MethodInfo m) { 
31           super(pos, i, declaring, m); 
32       } 
33    
34       /** 
35        * Returns the method or constructor containing the instanceof 
36        * expression represented by this object. 
37        */ 
38       public CtBehavior where() { 
39           return super.where(); 
40       } 
41    
42       /** 
43        * Returns the line number of the source line containing the 
44        * instanceof expression. 
45        * 
46        * @return -1       if this information is not available. 
47        */ 
48       public int getLineNumber() { 
49           return super.getLineNumber(); 
50       } 
51    
52       /** 
53        * Returns the source file containing the 
54        * instanceof expression. 
55        * 
56        * @return null     if this information is not available. 
57        */ 
58       public String getFileName() { 
59           return super.getFileName(); 
60       } 
61    
62       /** 
63        * Returns the <code>CtClass</code> object representing 
64        * the type name on the right hand side 
65        * of the instanceof operator. 
66        */ 
67       public CtClass getType() throws NotFoundException { 
68           ConstPool cp = getConstPool(); 
69           int pos = currentPos; 
70           int index = iterator.u16bitAt(pos + 1); 
71           String name = cp.getClassInfo(index); 
72           return Descriptor.toCtClass(name, thisClass.getClassPool()); 
73       } 
74    
75       /** 
76        * Returns the list of exceptions that the expression may throw. 
77        * This list includes both the exceptions that the try-catch statements 
78        * including the expression can catch and the exceptions that 
79        * the throws declaration allows the method to throw. 
80        */ 
81       public CtClass[] mayThrow() { 
82           return super.mayThrow(); 
83       } 
84    
85       /** 
86        * Replaces the instanceof operator with the bytecode derived from 
87        * the given source text. 
88        * 
89        * <p>$0 is available but the value is <code>null</code>. 
90        * 
91        * @param statement         a Java statement. 
92        */ 
93       public void replace(String statement) throws CannotCompileException { 
94           ConstPool constPool = getConstPool(); 
95           int pos = currentPos; 
96           int index = iterator.u16bitAt(pos + 1); 
97    
98           Javac jc = new Javac(thisClass); 
99           ClassPool cp = thisClass.getClassPool(); 
100          CodeAttribute ca = iterator.get(); 
101   
102          try { 
103              CtClass[] params 
104                      = new CtClass[]{cp.get(javaLangObject)}; 
105              CtClass retType = CtClass.booleanType; 
106   
107              int paramVar = ca.getMaxLocals(); 
108              jc.recordParams(javaLangObject, params, true, paramVar, 
109                      withinStatic()); 
110              int retVar = jc.recordReturnType(retType, true); 
111              jc.recordProceed(new ProceedForInstanceof(index)); 
112   
113              // because $type is not the return type... 
114              jc.recordType(getType()); 
115   
116              /* Is $_ included in the source code? 
117               */ 
118              checkResultValue(retType, statement); 
119   
120              Bytecode bytecode = jc.getBytecode(); 
121              storeStack(params, true, paramVar, bytecode); 
122              jc.compileStmnt(statement); 
123              bytecode.addLoad(retVar, retType); 
124   
125              replace0(pos, bytecode, 3); 
126          } catch (CompileError e) { 
127              throw new CannotCompileException(e); 
128          } catch (NotFoundException e) { 
129              throw new CannotCompileException(e); 
130          } catch (BadBytecode e) { 
131              throw new CannotCompileException("broken method"); 
132          } 
133      } 
134   
135      /* boolean $proceed(Object obj) 
136       */ 
137      static class ProceedForInstanceof implements ProceedHandler { 
138          int index; 
139   
140          ProceedForInstanceof(int i) { 
141              index = i; 
142          } 
143   
144          public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args) 
145                  throws CompileError { 
146              if (gen.atMethodArgsLength(args) != 1) 
147                  throw new CompileError(Javac.proceedName 
148                          + "() cannot take more than one parameter " 
149                          + "for instanceof"); 
150   
151              gen.atMethodArgs(args, new int[1], new int[1], new String[1]); 
152              bytecode.addOpcode(Opcode.INSTANCEOF); 
153              bytecode.addIndex(index); 
154              gen.setType(CtClass.booleanType); 
155          } 
156      } 
157  } 
158