KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > soot > jimple > toolkits > callgraph > CallGraph


1 /* Soot - a J*va Optimization Framework
2  * Copyright (C) 2003 Ondrej Lhotak
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 package soot.jimple.toolkits.callgraph;
21 import soot.*;
22 import soot.util.queue.*;
23 import java.util.*;
24
25 /** Represents the edges in a call graph. This class is meant to act as
26  * only a container of edges; code for various call graph builders should
27  * be kept out of it, as well as most code for accessing the edges.
28  * @author Ondrej Lhotak
29  */

30 public class CallGraph
31 {
32     private Set edges = new HashSet();
33     private ChunkedQueue stream = new ChunkedQueue();
34     private QueueReader reader = stream.reader();
35     private Map srcMethodToEdge = new HashMap();
36     private Map srcUnitToEdge = new HashMap();
37     private Map tgtToEdge = new HashMap();
38     private Edge dummy = new Edge( null, null, null, Kind.INVALID );
39
40     /** Used to add an edge to the call graph. Returns true iff the edge was
41      * not already present. */

42     public boolean addEdge( Edge e ) {
43         if( !edges.add( e ) ) return false;
44         stream.add( e );
45         Edge position = null;
46
47         position = (Edge) srcUnitToEdge.get( e.srcUnit() );
48         if( position == null ) {
49             srcUnitToEdge.put( e.srcUnit(), e );
50             position = dummy;
51         }
52         e.insertAfterByUnit( position );
53
54         position = (Edge) srcMethodToEdge.get( e.getSrc() );
55         if( position == null ) {
56             srcMethodToEdge.put( e.getSrc(), e );
57             position = dummy;
58         }
59         e.insertAfterBySrc( position );
60
61         position = (Edge) tgtToEdge.get( e.getTgt() );
62         if( position == null ) {
63             tgtToEdge.put( e.getTgt(), e );
64             position = dummy;
65         }
66         e.insertAfterByTgt( position );
67         return true;
68     }
69     /** Removes the edge e from the call graph. Returns true iff the edge
70      * was originally present in the call graph. */

71     public boolean removeEdge( Edge e ) {
72         if( !edges.remove( e ) ) return false;
73         e.remove();
74
75         if( srcUnitToEdge.get(e.srcUnit()) == e ) {
76             if( e.nextByUnit().srcUnit() == e.srcUnit() ) {
77                 srcUnitToEdge.put(e.srcUnit(), e.nextByUnit() );
78             } else {
79                 srcUnitToEdge.put(e.srcUnit(), null);
80             }
81         }
82
83         if( srcMethodToEdge.get(e.getSrc()) == e ) {
84             if( e.nextBySrc().getSrc() == e.getSrc() ) {
85                 srcMethodToEdge.put(e.getSrc(), e.nextBySrc() );
86             } else {
87                 srcMethodToEdge.put(e.getSrc(), null);
88             }
89         }
90
91         if( tgtToEdge.get(e.getTgt()) == e ) {
92             if( e.nextByTgt().getTgt() == e.getTgt() ) {
93                 tgtToEdge.put(e.getTgt(), e.nextByTgt() );
94             } else {
95                 tgtToEdge.put(e.getTgt(), null);
96             }
97         }
98
99         return true;
100     }
101
102     /** Returns an iterator over all methods that are the sources of at least
103      * one edge. */

104     public Iterator sourceMethods() {
105         return srcMethodToEdge.keySet().iterator();
106     }
107     /** Returns an iterator over all edges that have u as their source unit. */
108     public Iterator edgesOutOf( Unit u ) {
109         return new TargetsOfUnitIterator( u );
110     }
111     class TargetsOfUnitIterator implements Iterator {
112         private Edge position = null;
113         private Unit u;
114         TargetsOfUnitIterator( Unit u ) {
115             this.u = u;
116             if( u == null ) throw new RuntimeException JavaDoc();
117             position = (Edge) srcUnitToEdge.get( u );
118             if( position == null ) position = dummy;
119         }
120         public boolean hasNext() {
121             if( position.srcUnit() != u ) return false;
122             if( position.kind() == Kind.INVALID ) return false;
123             return true;
124         }
125         public Object JavaDoc next() {
126             Edge ret = position;
127             position = position.nextByUnit();
128             return ret;
129         }
130         public void remove() {
131             throw new UnsupportedOperationException JavaDoc();
132         }
133     }
134     /** Returns an iterator over all edges that have m as their source method. */
135     public Iterator edgesOutOf( MethodOrMethodContext m ) {
136         return new TargetsOfMethodIterator( m );
137     }
138     class TargetsOfMethodIterator implements Iterator {
139         private Edge position = null;
140         private MethodOrMethodContext m;
141         TargetsOfMethodIterator( MethodOrMethodContext m ) {
142             this.m = m;
143             if( m == null ) throw new RuntimeException JavaDoc();
144             position = (Edge) srcMethodToEdge.get( m );
145             if( position == null ) position = dummy;
146         }
147         public boolean hasNext() {
148             if( position.getSrc() != m ) return false;
149             if( position.kind() == Kind.INVALID ) return false;
150             return true;
151         }
152         public Object JavaDoc next() {
153             Edge ret = position;
154             position = position.nextBySrc();
155             return ret;
156         }
157         public void remove() {
158             throw new UnsupportedOperationException JavaDoc();
159         }
160     }
161     /** Returns an iterator over all edges that have m as their target method. */
162     public Iterator edgesInto( MethodOrMethodContext m ) {
163         return new CallersOfMethodIterator( m );
164     }
165     class CallersOfMethodIterator implements Iterator {
166         private Edge position = null;
167         private MethodOrMethodContext m;
168         CallersOfMethodIterator( MethodOrMethodContext m ) {
169             this.m = m;
170             if( m == null ) throw new RuntimeException JavaDoc();
171             position = (Edge) tgtToEdge.get( m );
172             if( position == null ) position = dummy;
173         }
174         public boolean hasNext() {
175             if( position.getTgt() != m ) return false;
176             if( position.kind() == Kind.INVALID ) return false;
177             return true;
178         }
179         public Object JavaDoc next() {
180             Edge ret = position;
181             position = position.nextByTgt();
182             return ret;
183         }
184         public void remove() {
185             throw new UnsupportedOperationException JavaDoc();
186         }
187     }
188     /** Returns a QueueReader object containing all edges added so far, and
189      * which will be informed of any new edges that are later added to
190      * the graph. */

191     public QueueReader listener() {
192         return (QueueReader) reader.clone();
193     }
194     /** Returns a QueueReader object which will contain ONLY NEW edges
195      * which will be added to the graph.
196      */

197     public QueueReader newListener() {
198         return stream.reader();
199     }
200     public String JavaDoc toString() {
201         QueueReader reader = listener();
202         StringBuffer JavaDoc out = new StringBuffer JavaDoc();
203         while(reader.hasNext()) {
204             Edge e = (Edge) reader.next();
205             out.append( e.toString() + "\n" );
206         }
207         return out.toString();
208     }
209     /** Returns the number of edges in the call graph. */
210     public int size() {
211         return edges.size();
212     }
213 }
214
215
Popular Tags