Permalink
Browse files

[reactivemongo] Disable Akka reverse engineering, only use Acolyte ac…

…tor system
  • Loading branch information...
cchantep
cchantep committed Sep 18, 2014
1 parent 1183221 commit 14b59bc5a92637d97e60c2f2a884f4aa7037a2ef
@@ -80,10 +80,7 @@ trait ReactiveMongo { deps: Dependencies ⇒
generated.foldLeft(Seq[(File, String)]()) { (s, f) =>
val path = f.getAbsolutePath
s :+ (f -> path.
drop(outdir.getAbsolutePath.length+1))
s :+ (f -> path.drop(outdir.getAbsolutePath.length+1))
}
} dependsOn(compile in (reactiveMongoGen, Compile)),
managedClasspath in Compile := {
@@ -2,18 +2,28 @@
import akka.actor.ActorSystem;
import akka.actor.ActorRef;
import akka.actor.Props;
/**
* Reference factory for Acolyte actors.
* Reference factory with underlying actor system provided.
*/
public interface ActorRefFactory {
/**
* Creates an ActorRef 'before' another.
* Returns actor reference according given properties.
*
* @param system Actor system
* @param then Actor to which message should be normally forwarded
* @param props Actor properties
*/
public ActorRef before(ActorSystem system, ActorRef then);
public ActorRef actorOf(ActorSystem system, Props props);
/**
* Returns actor reference according given properties and name.
*
* @param system Actor system
* @param props Actor properties
* @param name Actor name
*/
public ActorRef actorOf(ActorSystem system, Props props, String name);
} // end of class ActorRefFactory
@@ -40,6 +40,85 @@
final CtMethod[] ms = pc.getMethods();
for (int i = 0; i < ms.length; i++) {
if (!ms[i].getDeclaringClass().
getPackageName().startsWith("akka.")) {
continue;
} // end of if
// ---
final int mod = Modifier.
clear(ms[i].getModifiers(), Modifier.ABSTRACT);
if (Modifier.isStatic(mod) || Modifier.isPrivate(mod) ||
Modifier.isNative(mod) || Modifier.isFinal(mod)) {
continue;
} // end of if
// ---
final CtClass returnType = ms[i].getReturnType();
final CtClass[] paramTypes = ms[i].getParameterTypes();
final String name = ms[i].getName();
final String body = (returnType == CtClass.voidType)
? "{ underlying." + name + "($$); }"
: ("actorOf".equals(name) &&
(paramTypes.length == 1 || paramTypes.length == 2))
? "{ return this.refFactory.actorOf(underlying, $$); }"
: "{ return underlying." + name + "($$); }";
pc.addMethod(CtNewMethod.make(mod,
ms[i].getReturnType(),
ms[i].getName(),
paramTypes,
ms[i].getExceptionTypes(),
body,
pc));
} // end of for
final File packageDir =
new File(new File(outdir, "acolyte"), "reactivemongo");
packageDir.mkdirs();
final String outpath = outdir.getAbsolutePath();
fc.writeFile(outpath);
pc.writeFile(outpath);
return new File[] {
new File(packageDir, fc.getSimpleName() + ".class"),
new File(packageDir, pc.getSimpleName() + ".class")
};
} // end of writeTo
// Used to proxy ReactiveMongo actor system and do some reverse engineering
public static File[] writeReverseEngineering(File outdir) throws Exception {
final ClassPool pool = ClassPool.getDefault();
final LoaderClassPath lcp =
new LoaderClassPath(ActorSystem.class.getClassLoader());
pool.appendClassPath(lcp);
final CtClass asc = pool.get(ActorSystem.class.getName());
final CtClass fc = pool.get(ReverseEngineeringRefFactory.class.getName());
final CtClass pc =
pool.makeClass("acolyte.reactivemongo.ActorSystem");
pc.setSuperclass(asc);
// New fields
pc.addField(CtField.make("private final " + ActorSystem.class.getName() + " underlying;", pc));
pc.addField(CtField.make("private final " + ReverseEngineeringRefFactory.class.getName() + " refFactory;", pc));
// New constructor
pc.addConstructor(CtNewConstructor.make(new CtClass[] { asc, fc }, new CtClass[0], "{ if ($1 == null) { throw new IllegalArgumentException(\"Missing underlying system\"); } if ($2 == null) { throw new IllegalArgumentException(\"Missing reference factory\"); } this.underlying = $1; this.refFactory = $2; }", pc));
final CtMethod[] ms = pc.getMethods();
for (int i = 0; i < ms.length; i++) {
if (!ms[i].getDeclaringClass().
getPackageName().startsWith("akka.")) {
@@ -92,5 +171,5 @@
new File(packageDir, fc.getSimpleName() + ".class"),
new File(packageDir, pc.getSimpleName() + ".class")
};
} // end of writeTo
} // end of writeReverseEngineering
} // end of class ActorSystemGenerator
@@ -0,0 +1,19 @@
package acolyte.reactivemongo;
import akka.actor.ActorSystem;
import akka.actor.ActorRef;
/**
* Reference factory for reverse engineering of Mongo actors.
*/
public interface ReverseEngineeringRefFactory {
/**
* Creates an ActorRef 'before' another.
*
* @param system Actor system
* @param then Actor to which message should be normally forwarded
*/
public ActorRef before(ActorSystem system, ActorRef then);
} // end of class ReverseEngineeringRefFactory
@@ -35,14 +35,31 @@ private[reactivemongo] object Akka {
* @param name Actor system name (default: "ReactiveMongoAcolyte")
*/
def actorSystem(handler: ConnectionHandler, name: String = "ReactiveMongoAcolyte"): AkkaSystem = new ActorSystem(AkkaSystem(name), new ActorRefFactory() {
/* For reverse engineering
def before(system: AkkaSystem, next: ActorRef): ActorRef = {
system actorOf Props(classOf[Actor], handler, next)
}
*/
val DbSystem = classOf[reactivemongo.core.actors.MongoDBSystem]
def actorOf(system: AkkaSystem, props: Props): ActorRef = {
if (props.actorClass == DbSystem) {
system actorOf Props(classOf[Actor], handler)
} else system.actorOf(props)
}
def actorOf(system: AkkaSystem, props: Props, n: String): ActorRef = {
if (props.actorClass == DbSystem) {
system.actorOf(Props(classOf[Actor], handler), n)
} else system.actorOf(props, n)
}
})
}
private[reactivemongo] class Actor(
handler: ConnectionHandler, next: ActorRef /* TODO: Remove */ ) extends akka.actor.Actor {
handler: ConnectionHandler) extends akka.actor.Actor {
def receive = {
case msg @ CheckedWriteRequestExResp(
r @ CheckedWriteRequest(op, doc, GetLastError(_, _, _, _)))

0 comments on commit 14b59bc

Please sign in to comment.