1 19 20 package soot.jimple.toolkits.callgraph; 21 import soot.*; 22 import soot.util.queue.*; 23 import java.util.*; 24 25 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 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 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 104 public Iterator sourceMethods() { 105 return srcMethodToEdge.keySet().iterator(); 106 } 107 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 (); 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 next() { 126 Edge ret = position; 127 position = position.nextByUnit(); 128 return ret; 129 } 130 public void remove() { 131 throw new UnsupportedOperationException (); 132 } 133 } 134 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 (); 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 next() { 153 Edge ret = position; 154 position = position.nextBySrc(); 155 return ret; 156 } 157 public void remove() { 158 throw new UnsupportedOperationException (); 159 } 160 } 161 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 (); 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 next() { 180 Edge ret = position; 181 position = position.nextByTgt(); 182 return ret; 183 } 184 public void remove() { 185 throw new UnsupportedOperationException (); 186 } 187 } 188 191 public QueueReader listener() { 192 return (QueueReader) reader.clone(); 193 } 194 197 public QueueReader newListener() { 198 return stream.reader(); 199 } 200 public String toString() { 201 QueueReader reader = listener(); 202 StringBuffer out = new StringBuffer (); 203 while(reader.hasNext()) { 204 Edge e = (Edge) reader.next(); 205 out.append( e.toString() + "\n" ); 206 } 207 return out.toString(); 208 } 209 210 public int size() { 211 return edges.size(); 212 } 213 } 214 215 | Popular Tags |