/* * Copyright (C) 2012 Sony Mobile Communications AB * * This file is part of ApkAnalyser. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package analyser.gui.actions; import gui.actions.AbstractCanceableAction; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; import javax.swing.Icon; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import mereflect.MEClass; import mereflect.MEClassContext; import mereflect.MEField; import mereflect.MEMethod; import analyser.Analyser; import analyser.gui.MainFrame; import analyser.logic.AbstractReference; import analyser.logic.Reference; import analyser.logic.Resolver; import analyser.logic.ResolverListener; import andreflect.ApkClassContext; import andreflect.DexReferenceCache; import brut.androlib.res.data.ResResSpec; public abstract class AbstractAnalyseAction extends AbstractCanceableAction implements ResolverListener { private static final long serialVersionUID = 7269117050588573039L; protected AbstractAnalyseAction(String arg0, Icon arg1) { super(arg0, arg1); } public void buildTrees(Resolver r) { MainFrame.getInstance().setBottomInfo("Building trees"); Collection<Reference> cRR = r.getReferenceResources(); DefaultMutableTreeNode refRoot = new DefaultMutableTreeNode("Reference"); populatex(cRR, refRoot); MainFrame.getInstance().getResourceTree().setModel( new DefaultTreeModel(refRoot)); Collection<Reference> cMR = r.getMidletResources(); DefaultMutableTreeNode midletRoot = new DefaultMutableTreeNode("MIDlets"); populatex(cMR, midletRoot); MainFrame.getInstance().getMidletTree().setModel( new DefaultTreeModel(midletRoot)); } protected void populatex(Collection<Reference> cR, DefaultMutableTreeNode root) { List<AbstractReference> list = Arrays.asList(cR.toArray(new AbstractReference[0])); Collections.sort(list); Iterator<AbstractReference> iR = list.iterator(); while (iR.hasNext() && isRunning()) { AbstractReference abRef = iR.next(); DefaultMutableTreeNode refNode = new DefaultMutableTreeNode(abRef); root.add(refNode); Iterator<Reference> i = abRef.getChildren().iterator(); if (i != null && i.hasNext()) { populatex(abRef.getChildren(), refNode); } } } @Override public void resolving(int midlets, int numMidlets, int classes, int numClasses, int methods, int numMethods, MEClassContext ctx, MEClass clazz, MEMethod method) { double midletP = 1.0 / numMidlets; double classP = 1.0 / numClasses; double methodP = 1.0 / numMethods; double p = midletP * (midlets + classP * (classes + methodP * methods)); if (ctx instanceof ApkClassContext) { p *= 15; } else { p *= 100; } getMainFrame().actionReportWork(this, (int) p); getMainFrame().setBottomInfo( "Resolving method " + Analyser.getContextName(ctx) + ": " + clazz.getName() + "." + method.getName()); } @Override public void resolvingField(int midlets, int numMidlets, int classes, int numClasses, int fields, int numFields, ApkClassContext ctx, MEClass clazz, MEField field) { double midletP = 1.0 / numMidlets; double classP = 1.0 / numClasses; double fieldP = 1.0 / numFields; double p = midletP * (midlets + classP * (classes + fieldP * fields)); p *= 25; getMainFrame().actionReportWork(this, ((int) p) + 15); getMainFrame().setBottomInfo( "Resolving field " + Analyser.getContextName(ctx) + ": " + clazz.getName() + "." + field.getName()); } @Override public void resolvingFieldAccess(int midlet, int midlets, int access, int accesses, ApkClassContext ctx, DexReferenceCache.FieldAccess fieldAccess) { double midletP = 1.0 / midlets; double accessP = 1.0 / accesses; double p = midletP * (midlet + accessP * access); p *= 20; getMainFrame().actionReportWork(this, ((int) p) + 40); getMainFrame().setBottomInfo( "Resolving field access " + Analyser.getContextName(ctx) + ": " + fieldAccess.fieldIdItem.getFieldName().getStringValue()); } @Override public void resolvingResource(int midlets, int numMidlets, int resources, int numResources, ApkClassContext ctx, ResResSpec spec) { double midletP = 1.0 / numMidlets; double resourceP = 1.0 / numResources; double p = midletP * (midlets + resourceP * resources); p *= 35; //left 5% for rendering getMainFrame().actionReportWork(this, ((int) p) + 60); if (resources < numResources / 2) { getMainFrame().setBottomInfo( "Resolving resource " + Analyser.getContextName(ctx) + ": " + spec.getName()); } else { getMainFrame().setBottomInfo( "Resolving resource reference" + Analyser.getContextName(ctx) + ": " + spec.getName()); } } @Override public void resolved() { } @Override public void handleThrowable(Throwable t) { t.printStackTrace(); getMainFrame().showError("Error during analyse", t); MainFrame.getInstance().initBottomInfo(); } }