KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > soot > jimple > toolkits > invoke > AccessManager


1 /* Soot - a J*va Optimization Framework
2  * Copyright (C) 1999 Patrick Lam
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */

19
20 /*
21  * Modified by the Sable Research Group and others 1997-1999.
22  * See the 'credits' file distributed with Soot for the complete list of
23  * contributors. (Soot is distributed at http://www.sable.mcgill.ca/soot)
24  */

25
26 package soot.jimple.toolkits.invoke;
27
28 import java.util.ArrayList JavaDoc;
29 import java.util.Iterator JavaDoc;
30 import java.util.LinkedList JavaDoc;
31
32 import soot.*;
33 import soot.javaToJimple.LocalGenerator;
34 import soot.jimple.*;
35 import soot.util.Chain;
36
37 /** Methods for checking Java scope and visibiliity requirements. */
38 public class AccessManager
39 {
40     /** Returns true iff target is legally accessible from container.
41      * Illegal access occurs when any of the following cases holds:
42      * 1. target is private, but container.declaringClass() !=
43      * target.declaringClass(); or,
44      * 2. target is package-visible, and its package differs from
45      * that of container; or,
46      * 3. target is protected, and either:
47      * a. container doesn't belong to target.declaringClass,
48      * or any subclass of ;
49      */

50     public static boolean isAccessLegal(SootMethod container, ClassMember target)
51     {
52         SootClass targetClass = target.getDeclaringClass();
53         SootClass containerClass = container.getDeclaringClass();
54
55         if (!isAccessLegal(container, targetClass))
56             return false;
57
58         // Condition 1 above.
59
if (target.isPrivate() &&
60                 !targetClass.getName().equals(containerClass.getName()))
61             return false;
62
63         // Condition 2. Check the package names.
64
if (!target.isPrivate() && !target.isProtected()
65             && !target.isPublic())
66         {
67             if (!targetClass.getPackageName().equals
68                      (containerClass.getPackageName()))
69                 return false;
70         }
71
72         // Condition 3.
73
if (target.isProtected())
74         {
75             Hierarchy h = Scene.v().getActiveHierarchy();
76
77             // protected means that you can be accessed by your children.
78
// i.e. container must be in a child of target.
79
if (h.isClassSuperclassOfIncluding(targetClass, containerClass))
80                 return true;
81
82             return false;
83         }
84
85         return true;
86     }
87
88     /** Returns true if an access to <code>target</code> is legal from code in <code>container</code>. */
89     public static boolean isAccessLegal(SootMethod container, SootClass target)
90     {
91         return target.isPublic() ||
92             container.getDeclaringClass().getPackageName().equals(target.getPackageName());
93     }
94     
95     /**
96      * Returns true if the statement <code>stmt</code> contains an illegal access to a field or method,
97      * assuming the statement is in method <code>container</code>
98      * @param container
99      * @param stmt
100      * @return
101      */

102     public static boolean isAccessLegal(SootMethod container, Stmt stmt) {
103         if (stmt.containsInvokeExpr()) {
104             return AccessManager.isAccessLegal(container, stmt.getInvokeExpr().getMethod());
105         } else if (stmt instanceof AssignStmt) {
106             AssignStmt as=(AssignStmt)stmt;
107             if (as.getRightOp() instanceof FieldRef) {
108                 FieldRef r=(FieldRef)as.getRightOp();
109                 return AccessManager.isAccessLegal(container, r.getField());
110             }
111             if (as.getLeftOp() instanceof FieldRef) {
112                 FieldRef r=(FieldRef)as.getLeftOp();
113                 return AccessManager.isAccessLegal(container, r.getField());
114             }
115         }
116         return true;
117     }
118
119     /**
120      * Resolves illegal accesses in the interval ]before,after[
121      * by creating accessor methods.
122      * <code>before</code> and <code>after</code> can be null to indicate beginning/end respectively.
123      * @param body
124      * @param before
125      * @param after
126      */

127     public static void createAccessorMethods(Body body, Stmt before, Stmt after) {
128         soot.util.Chain units=body.getUnits();
129         
130         if (before!=null && !units.contains(before))
131             throw new RuntimeException JavaDoc();
132         if (after!=null && !units.contains(after))
133             throw new RuntimeException JavaDoc();
134         
135         ArrayList JavaDoc unitList = new ArrayList JavaDoc(); unitList.addAll(units);
136         
137         boolean bInside=before==null;
138         for (java.util.Iterator JavaDoc it=unitList.iterator(); it.hasNext();) {
139             Stmt s=(Stmt)it.next();
140             
141             if (bInside) {
142                 if (s==after)
143                     return;
144                 
145                 if (!isAccessLegal(body.getMethod(), s))
146                     createAccessorMethod(body.getMethod(), s);
147                 
148             } else {
149                 if (s==before)
150                     bInside=true;
151             }
152         }
153         
154     }
155     
156     
157     /**
158      * Creates a name for an accessor method.
159      * @param member
160      * @param setter
161      * @return
162      */

163     public static String JavaDoc createAccessorName(ClassMember member, boolean setter) {
164         SootClass target=member.getDeclaringClass();
165         
166         String JavaDoc name="access$";
167         if (member instanceof SootField) {
168             SootField f=(SootField)member;
169             if (setter) {
170                 name +="set$";
171             } else {
172                 name +="get$";
173             }
174             name +=f.getName();
175         } else {
176             SootMethod m=(SootMethod)member;
177             name += m.getName() + "$";
178             
179             for (Iterator JavaDoc it=m.getParameterTypes().iterator(); it.hasNext();) {
180                 Type type=(Type)it.next();
181                 name += type.toString().replaceAll("\\.", "\\$\\$") + "$";
182             }
183         }
184         return name;
185     }
186
187     /**
188      * Turns a field access or method call into a call to an accessor method.
189      * Reuses existing accessors based on name mangling (see createAccessorName)
190      * @param container
191      * @param stmt
192      */

193     public static void createAccessorMethod(SootMethod container, Stmt stmt)
194     {
195         //System.out.println("Creating accessor method: \n" +
196
// " method: " + container + " \n" +
197
// " stmt: " + stmt);
198

199         Body containerBody=container.getActiveBody();
200         soot.util.Chain containerStmts=containerBody.getUnits();
201         if (!containerStmts.contains(stmt))
202             throw new RuntimeException JavaDoc();
203         
204         if (stmt.containsInvokeExpr()) {
205             createInvokeAccessor(container, stmt);
206         } else if (stmt instanceof AssignStmt) {
207             AssignStmt as=(AssignStmt)stmt;
208             FieldRef ref;
209             if (as.getLeftOp() instanceof FieldRef) {
210 // set
211
ref=(FieldRef)as.getLeftOp();
212                 createSetAccessor(container, as, ref);
213                 
214             } else if (as.getRightOp() instanceof FieldRef) {
215                 // get
216
ref=(FieldRef)as.getRightOp();
217                  createGetAccessor(container, as, ref);
218             } else {
219                 throw new RuntimeException JavaDoc("Expected class member access");
220             }
221         } else
222             throw new RuntimeException JavaDoc("Expected class member access");
223     }
224     
225     private static void createGetAccessor(SootMethod container, AssignStmt as, FieldRef ref) {
226         java.util.List JavaDoc parameterTypes=new LinkedList JavaDoc();
227         java.util.List JavaDoc thrownExceptions=new LinkedList JavaDoc();
228         
229         
230         Body accessorBody = Jimple.v().newBody();
231         soot.util.Chain accStmts=accessorBody.getUnits();
232         LocalGenerator lg=new LocalGenerator(accessorBody);
233         
234         Body containerBody=container.getActiveBody();
235         soot.util.Chain containerStmts=containerBody.getUnits();
236         
237         SootClass target=ref.getField().getDeclaringClass();
238         
239         SootMethod accessor;
240         
241         String JavaDoc name=createAccessorName(ref.getField(), false);
242         if (target.declaresMethodByName(name)) {
243             accessor=target.getMethodByName(name);
244         } else {
245              Type returnType=ref.getField().getType();
246              Local thisLocal=lg.generateLocal(target.getType());
247              if (ref instanceof InstanceFieldRef) {
248                 parameterTypes.add(target.getType());
249                 accStmts.addFirst(
250                         Jimple.v().newIdentityStmt(thisLocal,
251                         Jimple.v().newParameterRef(target.getType(),0)));
252              }
253             Local l=lg.generateLocal(ref.getField().getType());
254             Value v;
255             if (ref instanceof InstanceFieldRef) {
256                 v=Jimple.v().newInstanceFieldRef(thisLocal,ref.getFieldRef());
257             } else {
258                 v=Jimple.v().newStaticFieldRef(ref.getFieldRef());
259             }
260             accStmts.add(Jimple.v().newAssignStmt(l, v));
261             accStmts.add(Jimple.v().newReturnStmt(l));
262             
263             accessor=new SootMethod(name, parameterTypes, returnType,
264                     Modifier.PUBLIC | Modifier.STATIC,
265                     thrownExceptions);
266             accessorBody.setMethod(accessor);
267             accessor.setActiveBody(accessorBody);
268             target.addMethod(accessor);
269         }
270         java.util.List JavaDoc args=new LinkedList JavaDoc();
271         if (ref instanceof InstanceFieldRef) {
272             args.add(((InstanceFieldRef)ref).getBase());
273         }
274         InvokeExpr newExpr=
275             Jimple.v().newStaticInvokeExpr(accessor.makeRef(), args);
276         
277         as.setRightOp(newExpr);
278     }
279
280     private static void createSetAccessor(SootMethod container, AssignStmt as, FieldRef ref) {
281         java.util.List JavaDoc parameterTypes=new LinkedList JavaDoc();
282         java.util.List JavaDoc thrownExceptions=new LinkedList JavaDoc();
283         
284         Body accessorBody = Jimple.v().newBody();
285         soot.util.Chain accStmts=accessorBody.getUnits();
286         LocalGenerator lg=new LocalGenerator(accessorBody);
287         
288         Body containerBody=container.getActiveBody();
289         soot.util.Chain containerStmts=containerBody.getUnits();
290         
291         SootClass target=ref.getField().getDeclaringClass();
292         SootMethod accessor;
293         
294         String JavaDoc name=createAccessorName(ref.getField(), true);
295         if (target.declaresMethodByName(name)) {
296             accessor=target.getMethodByName(name);
297         } else {
298             Local thisLocal=lg.generateLocal(target.getType());
299             int paramID=0;
300             if (ref instanceof InstanceFieldRef) {
301                 accStmts.add(
302                         Jimple.v().newIdentityStmt(thisLocal,
303                                 Jimple.v().newParameterRef(target.getType(),paramID)));
304                 parameterTypes.add(target.getType());
305                 paramID++;
306             }
307             parameterTypes.add(ref.getField().getType());
308             Local l=lg.generateLocal(ref.getField().getType());
309             accStmts.add(
310                     Jimple.v().newIdentityStmt(l,
311                     Jimple.v().newParameterRef(ref.getField().getType(),paramID)));
312             paramID++;
313             if (ref instanceof InstanceFieldRef) {
314                 accStmts.add(Jimple.v().newAssignStmt(
315                     Jimple.v().newInstanceFieldRef(thisLocal,ref.getFieldRef()), l));
316             } else {
317                 accStmts.add(Jimple.v().newAssignStmt(
318                         Jimple.v().newStaticFieldRef(ref.getFieldRef()), l));
319             }
320             accStmts.addLast(Jimple.v().newReturnVoidStmt());
321             Type returnType=VoidType.v();
322             
323             accessor=new SootMethod(name, parameterTypes, returnType,
324                     Modifier.PUBLIC | Modifier.STATIC,
325                     thrownExceptions);
326             accessorBody.setMethod(accessor);
327             accessor.setActiveBody(accessorBody);
328             target.addMethod(accessor);
329         }
330         
331         java.util.List JavaDoc args=new LinkedList JavaDoc();
332         if (ref instanceof InstanceFieldRef) {
333             args.add(((InstanceFieldRef)ref).getBase());
334         }
335         args.add(as.getRightOp());
336         InvokeExpr newExpr=
337             Jimple.v().newStaticInvokeExpr(accessor.makeRef(), args);
338         
339         Stmt newStmt=Jimple.v().newInvokeStmt(newExpr);
340         
341         containerStmts.insertAfter(newStmt, as);
342         containerStmts.remove(as);
343     }
344
345     private static void createInvokeAccessor(SootMethod container, Stmt stmt) {
346         java.util.List JavaDoc parameterTypes=new LinkedList JavaDoc();
347         java.util.List JavaDoc thrownExceptions=new LinkedList JavaDoc();
348         Type returnType;
349         
350         Body accessorBody = Jimple.v().newBody();
351         soot.util.Chain accStmts=accessorBody.getUnits();
352         LocalGenerator lg=new LocalGenerator(accessorBody);
353         
354         Body containerBody=container.getActiveBody();
355         soot.util.Chain containerStmts=containerBody.getUnits();
356         
357         InvokeExpr expr=stmt.getInvokeExpr();
358         SootMethod method=expr.getMethod();
359         //System.out.println("method: " + method);
360

361         SootClass target=method.getDeclaringClass();
362         //System.out.println("target: " + target);
363

364         //System.out.println("method ref: " + expr.getMethodRef());
365

366         SootMethod accessor;
367         
368         String JavaDoc name=createAccessorName(method, true);
369         if (target.declaresMethodByName(name)) {
370             accessor=target.getMethodByName(name);
371         } else {
372             java.util.List JavaDoc arguments=new LinkedList JavaDoc();
373             
374             if (expr instanceof InstanceInvokeExpr) {
375                 parameterTypes.add(target.getType());
376             }
377             
378             parameterTypes.addAll(method.getParameterTypes());
379             returnType=method.getReturnType();
380             thrownExceptions.addAll(method.getExceptions());
381             
382             int paramID=0;
383             for (java.util.Iterator JavaDoc it=parameterTypes.iterator(); it.hasNext();) {
384                 Type type=(Type)it.next();
385                 Local l=lg.generateLocal(type);
386                 //System.out.println("local type: " + type);
387
accStmts.add(
388                         Jimple.v().newIdentityStmt(l,
389                         Jimple.v().newParameterRef(type, paramID)));
390                 arguments.add(l);
391                 paramID++;
392             }
393             
394             InvokeExpr accExpr;
395             
396             if (expr instanceof StaticInvokeExpr) {
397                 accExpr=Jimple.v().newStaticInvokeExpr(method.makeRef(), arguments);
398             } else if (expr instanceof VirtualInvokeExpr) {
399                 Local thisLocal=(Local)arguments.get(0);
400                 arguments.remove(0);
401                 accExpr=Jimple.v().newVirtualInvokeExpr(thisLocal, method.makeRef(), arguments);
402             } else if (expr instanceof SpecialInvokeExpr) {
403                 Local thisLocal=(Local)arguments.get(0);
404                 arguments.remove(0);
405                 accExpr=Jimple.v().newSpecialInvokeExpr(thisLocal, method.makeRef(), arguments);
406             } else
407                 throw new RuntimeException JavaDoc("");
408             
409             Stmt s;
410             if (returnType instanceof VoidType) {
411                 s=Jimple.v().newInvokeStmt(accExpr);
412                 accStmts.add(s);
413                 accStmts.add(Jimple.v().newReturnVoidStmt());
414             } else {
415                 Local resultLocal=lg.generateLocal(returnType);
416                 s=Jimple.v().newAssignStmt(resultLocal,accExpr);
417                 accStmts.add(s);
418                 accStmts.add(Jimple.v().newReturnStmt(resultLocal));
419             }
420             
421             accessor=new SootMethod(name, parameterTypes, returnType,
422                     Modifier.PUBLIC | Modifier.STATIC,
423                     thrownExceptions);
424             accessorBody.setMethod(accessor);
425             accessor.setActiveBody(accessorBody);
426             target.addMethod(accessor);
427         }
428         
429         java.util.List JavaDoc args=new LinkedList JavaDoc();
430         if (expr instanceof InstanceInvokeExpr) {
431             args.add(((InstanceInvokeExpr)expr).getBase());
432         }
433         args.addAll(expr.getArgs());
434         InvokeExpr newExpr=
435                 Jimple.v().newStaticInvokeExpr(accessor.makeRef(), args);
436                 
437         stmt.getInvokeExprBox().setValue(newExpr);
438     }
439
440     /** Modifies code so that an access to <code>target</code> is legal from
441      * code in <code>container</code>.
442      *
443      * The "accessors" option assumes suitable accessor methods will be created after checking.
444      *
445      * */

446     public static boolean ensureAccess(SootMethod container, ClassMember target, String JavaDoc options)
447     {
448         boolean accessors=options.equals("accessors");
449         boolean allowChanges = !(options.equals("none"));
450         boolean safeChangesOnly = !(options.equals("unsafe"));
451         
452         
453         SootClass targetClass = target.getDeclaringClass();
454         if (!ensureAccess(container, targetClass, options))
455             return false;
456
457         if (isAccessLegal(container, target))
458             return true;
459
460         if (!allowChanges && !accessors)
461             return false;
462
463         
464           //throw new RuntimeException("Not implemented yet!");
465

466         if (target.getDeclaringClass().isApplicationClass())
467         {
468             if (accessors)
469                 return true;
470             
471             if (safeChangesOnly)
472                 throw new RuntimeException JavaDoc("Not implemented yet!");
473             
474             target.setModifiers(target.getModifiers() | Modifier.PUBLIC);
475             return true;
476         }
477         else
478             return false;
479     }
480
481     /** Modifies code so that an access to <code>target</code> is legal from code in <code>container</code>. */
482     public static boolean ensureAccess(SootMethod container, SootClass target, String JavaDoc options)
483     {
484         boolean accessors=options.equals("accessors");
485         boolean allowChanges = !(options.equals("none"));
486         boolean safeChangesOnly = !(options.equals("unsafe"));
487
488         if (isAccessLegal(container, target))
489             return true;
490
491         if (!allowChanges && !accessors)
492             return false;
493
494         if (safeChangesOnly && !accessors)
495             throw new RuntimeException JavaDoc("Not implemented yet!");
496         
497         if (accessors)
498             return false;
499         
500         if (target.isApplicationClass())
501         {
502                 
503             target.setModifiers(target.getModifiers() | Modifier.PUBLIC);
504             return true;
505         }
506         else
507             return false;
508     }
509
510 }
511
Popular Tags