/* * 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.bytecodemod; import java.awt.event.ActionEvent; import javax.swing.Icon; import javax.swing.JOptionPane; import javax.swing.JViewport; import analyser.gui.ClassTree; import analyser.gui.LineBuilderFormatter; import analyser.gui.MainFrame; import analyser.gui.Selection; import analyser.gui.TextBuilder; import analyser.logic.BytecodeModificationMediator; import analyser.logic.Reference; import jerl.bcm.inj.Injection; import jerl.bcm.inj.impl.MethodOffsetCurThreadOut; import mereflect.MEMethod; import mereflect.bytecode.Bytecode; public class MethodOffsetCurThreadAction extends AbstractTreeBytecodeModAction { private static final long serialVersionUID = 6979052875995839965L; protected static MethodOffsetCurThreadAction m_inst = null; public static MethodOffsetCurThreadAction getInstance(MainFrame mainFrame) { if (m_inst == null) { m_inst = new MethodOffsetCurThreadAction("Add current thread printout to offset", null); m_inst.setMainFrame(mainFrame); } return m_inst; } protected MethodOffsetCurThreadAction(String arg0, Icon arg1) { super(arg0, arg1); } @Override public void run(ActionEvent e) throws Throwable { MainFrame mainFrame = (MainFrame) getMainFrame(); ClassTree tree = mainFrame.getSelectedTree(); if (!(Selection.getSelectedView() instanceof TextBuilder)) { return; } TextBuilder text = (TextBuilder) Selection.getSelectedView(); if (text == null) { return; } Object ref = Selection.getSelectedObject(); MEMethod method = (MEMethod) text.getOwnerData(); int bytecodeOffset = ((LineBuilderFormatter.BytecodeOffset) ref).pc; if (ref == null || !LineBuilderFormatter.BytecodeOffset.class.isAssignableFrom(ref.getClass())) { return; } String output = (String) JOptionPane.showInputDialog( mainFrame, "", "Prefix string", JOptionPane.QUESTION_MESSAGE, null, null, method.getMEClass().getName() + ":" + method.getName() + "@" + Integer.toHexString(bytecodeOffset)); if (output != null && output.trim().length() > 0) { output += " "; } else { output = ""; } int bcIx = Bytecode.getBytecodeIndexForOffset(method, bytecodeOffset); MethodOffsetCurThreadOut injection = new MethodOffsetCurThreadOut(method.getName() + method.getDescriptor(), bcIx <= 0 ? bcIx : bcIx - 1, output + "currentThread="); BytecodeModificationMediator.getInstance().registerModification( method.getMEClass().getResource().getContext(), method.getMEClass(), injection, method); if (isRunning()) { mainFrame.actionFinished(this); } tree.findAndMarkNode(method, Reference.MODIFIED); tree.repaint(); int pos = text.getCaretPosition(); JViewport view = text.getScrollPane().getViewport(); text.getLineBuilder().insertLineBefore(text.getCurrentLine()); text.getLineBuilder().append(" >>> ", 0xbb0000); text.getLineBuilder().append("PRINT(", 0x000000); text.getLineBuilder().append("\"" + output + "currentThread=\"", 0x0000bb); text.getLineBuilder().append(" + Thread.currentThread())", 0x000000); text.getLineBuilder().setReferenceToCurrent(injection); text.updateDocument(); text.setCaretPosition(pos); text.getScrollPane().setViewport(view); } @Override protected Injection getInjection(String className, String methodSignature) { // not used return null; } }