/*
* COMSAT
* Copyright (C) 2015, Parallel Universe Software Co. All rights reserved.
*
* This program and the accompanying materials are dual-licensed under
* either the terms of the Eclipse Public License v1.0 as published by
* the Eclipse Foundation
*
* or (per the licensee's choosing)
*
* under the terms of the GNU Lesser General Public License version 3.0
* as published by the Free Software Foundation.
*/
package co.paralleluniverse.fibers.jdbi;
import co.paralleluniverse.fibers.instrument.LogLevel;
import co.paralleluniverse.fibers.instrument.MethodDatabase;
import co.paralleluniverse.fibers.instrument.SimpleSuspendableClassifier;
import co.paralleluniverse.fibers.instrument.SuspendableClassifier;
import co.paralleluniverse.fibers.instrument.SuspendableHelper;
/**
* Given classes and methodRegexps, Instrumenting all the extending methods in
* the scope of given package prefix.
*/
public class JdbiClassifier implements SuspendableClassifier {
private static final String PKG_PREFIX = "org/skife/jdbi/v2";
String[][] methodsArray = {
{"org/skife/jdbi/v2/IDBI", "open"},
{"org/skife/jdbi/v2/Handle", "execute", "update", "close", "begin", "commit", "rollback", "execute", "checkpoint", "release"},
{"org/skife/jdbi/v2/ResultBearing", "first", "list"},
{"org/skife/jdbi/v2/QueryResultMunger", "munge"},
{"org/skife/jdbi/v2/Cleanable", "cleanup"},
{"org/skife/jdbi/v2/sqlobject/Handler", "invoke"},
{"org/skife/jdbi/v2/sqlobject/HandleDing", "getHandle", "release", "retain"},
{"org/skife/jdbi/v2/sqlobject/UpdateHandler$Returner", "value"},
{"org/skife/jdbi/v2/sqlobject/ResultReturnThing", "result"},
{"org/skife/jdbi/v2/sqlobject/mixins/Transactional", "begin", "commit", "rollback", "checkpoint", "release"},
{"org/skife/jdbi/v2/tweak/TransactionHandler", "begin", "commit", "rollback", "checkpoint", "release"},
{"org/skife/jdbi/v2/tweak/ConnectionFactory", "openConnection"},
{"org/skife/jdbi/v2/tweak/StatementCustomizer", "beforeExecution", "afterExecution", "cleanup"},
{"org/skife/jdbi/v2/tweak/RewrittenStatement", "bind"},
{"org/skife/jdbi/v2/tweak/ResultSetMapper", "map"},
{"org/skife/jdbi/v2/tweak/ResultColumnMapper", "mapColumn"},
{"org/skife/jdbi/v2/tweak/Argument", "apply"},
{"org/skife/jdbi/v2/tweak/StatementBuilder", "create", "beforeExecution", "close"},
{"org/skife/jdbi/v2/tweak/ConnectionFactory", "openConnection"},
{"org/skife/jdbi/v2/util/TypedMapper", "extractByName", "extractByIndex"},
};
@Override
public MethodDatabase.SuspendableType isSuspendable (
MethodDatabase db,
String sourceName, String sourceDebugInfo,
boolean isInterface, String className, String superClassName, String[] interfaces,
String methodName, String methodDesc, String methodSignature, String[] methodExceptions
) {
// Declares given methods as supers
for (String[] susExtendables : methodsArray) {
if (isJDBICGLibProxy(className, methodName)) {
return MethodDatabase.SuspendableType.SUSPENDABLE;
} else if (className.equals(susExtendables[0]))
for (int i = 1; i < susExtendables.length; i++) {
if (methodName.matches(susExtendables[i])) {
if (db.isVerbose())
db.getLog().log(LogLevel.INFO, JdbiClassifier.class.getName() + ": " + className + "." + methodName + " supersOrEqual " + susExtendables[0] + "." + susExtendables[i]);
return MethodDatabase.SuspendableType.SUSPENDABLE;
}
}
}
// Declares extending classes in jooq packages as suspendables
if (!className.startsWith(PKG_PREFIX))
return null;
for (String[] susExtendables : methodsArray) {
if (SimpleSuspendableClassifier.extendsOrImplements(susExtendables[0], db, className, superClassName, interfaces))
for (int i = 1; i < susExtendables.length; i++) {
if (methodName.matches(susExtendables[i])) {
if (db.isVerbose())
db.getLog().log(LogLevel.INFO, JdbiClassifier.class.getName() + ": " + className + "." + methodName + " extends " + susExtendables[0] + "." + susExtendables[i]);
return MethodDatabase.SuspendableType.SUSPENDABLE;
}
}
}
return null;
}
private boolean isJDBICGLibProxy(String className, String methodName) {
boolean ret = className.startsWith("org/skife/jdbi/v2/sqlobject/CloseInternalDoNotUseThisClass$$EnhancerByCGLIB$$") && !methodName.startsWith("<");
if (ret)
SuspendableHelper.addWaiver(className.replace("/", "."), methodName); // @Instrumented added during instrumentation seems not to stick to CGLIB proxies, let verification know
return ret;
}
}