/* Soot - a J*va Optimization Framework * Copyright (C) 2003 Jerome Miecznikowski * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package soot.dava.toolkits.base.finders; import soot.*; import java.util.*; import soot.util.*; import soot.dava.internal.asg.*; public class ExceptionNode { private final IterableSet body; private IterableSet tryBody, catchBody; private boolean dirty; private LinkedList exitList, catchList; private SootClass exception; private HashMap<IterableSet,SootClass> catch2except; private AugmentedStmt handlerAugmentedStmt; public ExceptionNode( IterableSet tryBody, SootClass exception, AugmentedStmt handlerAugmentedStmt) { this.tryBody = tryBody; this.catchBody = null; this.exception = exception; this.handlerAugmentedStmt = handlerAugmentedStmt; body = new IterableSet(); body.addAll( tryBody); dirty = true; exitList = null; catchList = null; catch2except = null; } public boolean add_TryStmts( Collection c) { Iterator it = c.iterator(); while (it.hasNext()) if (add_TryStmt( (AugmentedStmt) it.next()) == false) return false; return true; } public boolean add_TryStmt( AugmentedStmt as) { if ((body.contains( as)) || (tryBody.contains( as))) return false; body.add( as); tryBody.add( as); return true; } public void refresh_CatchBody( ExceptionFinder ef) { if (catchBody != null) body.removeAll( catchBody); catchBody = ef.get_CatchBody( handlerAugmentedStmt); body.addAll( catchBody); } public IterableSet get_Body() { return body; } public IterableSet get_TryBody() { return tryBody; } public IterableSet get_CatchBody() { return catchBody; } public boolean remove( AugmentedStmt as) { if (body.contains( as) == false) return false; if (tryBody.contains( as)) tryBody.remove( as); else if ((catchBody != null) && (catchBody.contains( as))) { catchBody.remove( as); dirty = true; } else return false; body.remove( as); return true; } public List get_CatchExits() { if (catchBody == null) return null; if (dirty) { exitList = new LinkedList(); dirty = false; Iterator it = catchBody.iterator(); while (it.hasNext()) { AugmentedStmt as = (AugmentedStmt) it.next(); Iterator sit = as.bsuccs.iterator(); while (sit.hasNext()) if (catchBody.contains( sit.next()) == false) { exitList.add( as); break; } } } return exitList; } public void splitOff_ExceptionNode( IterableSet newTryBody, AugmentedStmtGraph asg, IterableSet enlist) { IterableSet oldTryBody = new IterableSet(); oldTryBody.addAll( tryBody); IterableSet oldBody = new IterableSet(); oldBody.addAll( body); Iterator it = newTryBody.iterator(); while (it.hasNext()) { AugmentedStmt as = (AugmentedStmt) it.next(); if (remove( as) == false) { StringBuffer b = new StringBuffer(); it = newTryBody.iterator(); while (it.hasNext()) b.append( "\n" + ((AugmentedStmt) it.next()).toString()); b.append( "\n-"); it = oldTryBody.iterator(); while (it.hasNext()) b.append( "\n" + ((AugmentedStmt) it.next()).toString()); b.append( "\n-"); it = oldBody.iterator(); while (it.hasNext()) b.append( "\n" + ((AugmentedStmt) it.next()).toString()); b.append( "\n-"); throw new RuntimeException( "Tried to split off a new try body that isn't in the old one.\n"+ as +"\n - " + b.toString()); } } asg.clone_Body( catchBody); AugmentedStmt oldCatchTarget = handlerAugmentedStmt, newCatchTarget = asg.get_CloneOf( handlerAugmentedStmt); Iterator tbit = newTryBody.iterator(); while (tbit.hasNext()) { AugmentedStmt as = (AugmentedStmt) tbit.next(); as.remove_CSucc( oldCatchTarget); oldCatchTarget.remove_CPred( as); } tbit = tryBody.iterator(); while (tbit.hasNext()) { AugmentedStmt as = (AugmentedStmt) tbit.next(); as.remove_CSucc( newCatchTarget); newCatchTarget.remove_CPred( as); } Iterator enlit = enlist.snapshotIterator(); while (enlit.hasNext()) { ExceptionNode en = (ExceptionNode) enlit.next(); if (this == en) continue; if (catchBody.isSupersetOf( en.get_Body())) { IterableSet clonedTryBody = new IterableSet(); Iterator trit = en.get_TryBody().iterator(); while (trit.hasNext()) clonedTryBody.add( asg.get_CloneOf( (AugmentedStmt) trit.next())); enlist.addLast( new ExceptionNode( clonedTryBody, en.exception, asg.get_CloneOf( en.handlerAugmentedStmt))); } } enlist.addLast( new ExceptionNode( newTryBody, exception, asg.get_CloneOf( handlerAugmentedStmt))); enlit = enlist.iterator(); while (enlit.hasNext()) ((ExceptionNode) enlit.next()).refresh_CatchBody( ExceptionFinder.v()); asg.find_Dominators(); } public void add_CatchBody( ExceptionNode other) { if (other.get_CatchList() == null) { add_CatchBody( other.get_CatchBody(), other.get_Exception()); return; } Iterator it = other.get_CatchList().iterator(); while (it.hasNext()) { IterableSet c = (IterableSet) it.next(); add_CatchBody( c, other.get_Exception( c)); } } public void add_CatchBody( IterableSet newCatchBody, SootClass except) { if (catchList == null) { catchList = new LinkedList(); catchList.addLast( catchBody); catch2except = new HashMap<IterableSet,SootClass>(); catch2except.put( catchBody, exception); } body.addAll( newCatchBody); catchList.addLast( newCatchBody); catch2except.put( newCatchBody, except); } public List get_CatchList() { List l = catchList; if (l == null) { l = new LinkedList(); l.add( catchBody); } return l; } public Map get_ExceptionMap() { Map m = catch2except; if (m == null) { m = new HashMap(); m.put( catchBody, exception); } return m; } public SootClass get_Exception() { return exception; } public SootClass get_Exception( IterableSet catchBody) { if (catch2except == null) return exception; return catch2except.get( catchBody); } public void dump() { G.v().out.println("try {"); Iterator tit = get_TryBody().iterator(); while (tit.hasNext()) G.v().out.println( "\t" + tit.next()); G.v().out.println( "}"); Iterator cit = get_CatchList().iterator(); while (cit.hasNext()) { IterableSet catchBody = (IterableSet) cit.next(); G.v().out.println( "catch " + get_ExceptionMap().get( catchBody) + " {"); Iterator cbit = catchBody.iterator(); while (cbit.hasNext()) G.v().out.println( "\t" + cbit.next()); G.v().out.println("}"); } } }