/* * Copyright, Aspect Security, Inc. * * This file is part of JavaSnoop. * * JavaSnoop is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * JavaSnoop 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with JavaSnoop. If not, see <http://www.gnu.org/licenses/>. */ package com.aspect.snoop.agent.manager; import com.aspect.snoop.FunctionHook; import com.aspect.snoop.SnoopSession; import com.aspect.snoop.agent.AgentLogger; import com.aspect.snoop.agent.SnoopAgent; import com.aspect.snoop.util.ReflectionUtil; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.HashMap; import java.util.List; public class SessionManager { public static void recycleHooks(SnoopSession session) throws InstrumentationException { uninstallHooks(session); installHooks(session); } /** * This function is the entry point into the instrumentation of the * running program. It turns on the rules we instrument. */ public static void uninstallHooks(SnoopSession snoopSession) throws InstrumentationException { if ( snoopSession == null ) { return; } InstrumentationManager manager = SnoopAgent.getAgentManager(); for (FunctionHook hook : snoopSession.getFunctionHooks()) { Class clazz = hook.getClazz(); /*if ( ! manager.hasClassBeenModified(clazz) ) { continue; }*/ if ( ReflectionUtil.isInterfaceOrAbstract(clazz) || hook.isAppliedToSubtypes() ) { Class[] subtypes = getAllSubtypes(clazz); for (Class c : subtypes ) { if ( manager.hasClassBeenModified(c) ) { manager.deinstrument(c); } } } try { if ( manager.hasClassBeenModified(clazz) ) { manager.deinstrument(clazz); } else { AgentLogger.debug("Not de-instrumenting " + clazz.getName() + " because it has no history"); } } catch(InstrumentationException e) { AgentLogger.error("Problem de-instrumenting class", e); } } } public static void installHooks(SnoopSession snoopSession) throws InstrumentationException { HashMap<Class, ClassChanges> classChanges = new HashMap<Class,ClassChanges>(); InstrumentationManager manager = SnoopAgent.getAgentManager(); for(FunctionHook hook : snoopSession.getFunctionHooks() ) { if ( ! hook.isEnabled() ) { continue; } String methodName = hook.getMethodName(); Class[] parameterTypes = hook.getParameterTypes(); Class clazz = hook.getClazz(); // if it applies to all subtypes, only do it to the subtypes if ( ReflectionUtil.isInterfaceOrAbstract(clazz) || hook.isAppliedToSubtypes() ) { Class[] subtypes = getAllSubtypes(clazz); for (Class c : subtypes ) { if ( hasMethod(c, methodName, parameterTypes) ) { ClassChanges change = classChanges.get(c); if (change == null) { change = new ClassChanges(c); classChanges.put(c, change); } change.registerHook(hook, manager); } } } if ( ! clazz.isInterface() ) { if ( ! Modifier.isAbstract(clazz.getModifiers()) || hasMethod(clazz,methodName,parameterTypes)) { ClassChanges change = classChanges.get(clazz); if (change == null) { change = new ClassChanges(clazz); classChanges.put(clazz, change); } change.registerHook(hook, manager); } } } for ( Class clazz : classChanges.keySet() ) { try { ClassChanges change = classChanges.get(clazz); manager.instrument( clazz, change.getAllMethodChanges()); } catch (InstrumentationException ex) { throw ex; } } } private static Class[] getAllSubtypes(Class clazz) { List<Class> subtypes = new ArrayList<Class>(); for(Class c : SnoopAgent.getAgentManager().getLoadedClasses() ) { if ( clazz.isAssignableFrom(c) && ! c.isInterface() && ! c.equals(clazz)) { subtypes.add(c); } } return subtypes.toArray( new Class[]{} ); } private static boolean hasMethod(Class c, String name, Class[] params) { try { Method m = c.getDeclaredMethod(name, params); return !Modifier.isAbstract(m.getModifiers()); } catch(Exception e) { } return false; } }