11package com .github .mustachejava .reflect ;
22
3- import com .google .common .base .Predicate ;
3+ import org .objectweb .asm .ClassWriter ;
4+ import org .objectweb .asm .Label ;
5+ import org .objectweb .asm .Type ;
6+ import org .objectweb .asm .commons .GeneratorAdapter ;
7+ import org .objectweb .asm .commons .Method ;
8+
9+ import static org .objectweb .asm .commons .GeneratorAdapter .*;
410
511/**
612 * Ensure that the class of the current scope is that same as when this wrapper was generated.
915 * Time: 9:23 AM
1016 * To change this template use File | Settings | File Templates.
1117 */
12- public class ClassGuard implements Predicate < Object []> {
18+ public class ClassGuard implements Guard {
1319 private final Class classGuard ;
1420 private final int scopeIndex ;
1521
@@ -33,6 +39,56 @@ public boolean equals(Object o) {
3339 public boolean apply (Object [] scopes ) {
3440 if (scopes == null || scopes .length <= scopeIndex ) return false ;
3541 Object scope = scopes [scopeIndex ];
36- return (scope == null && classGuard == null ) || (scope != null && classGuard == scope .getClass ());
42+ if (scope != null && classGuard != scope .getClass ()) return false ;
43+ if (scope == null && classGuard != null ) return false ;
44+ return true ;
3745 }
46+
47+ @ Override
48+ public void addGuard (Label returnFalse , GeneratorAdapter gm , GeneratorAdapter sm , ClassWriter cw , int id , String className ) {
49+ // Add the field for the class guard
50+ cw .visitField (ACC_PUBLIC | ACC_STATIC , "classGuard" + id , "Ljava/lang/Class;" , null , null );
51+
52+ // Initialize the field
53+ sm .push (classGuard .getName ());
54+ sm .invokeStatic (Type .getType (Class .class ), Method .getMethod ("Class forName(String)" ));
55+ sm .putStatic (Type .getType (className ), "classGuard" + id , Type .getType (Class .class ));
56+
57+ Label next = new Label ();
58+ Label scopeIsNull = new Label ();
59+
60+ gm .loadArg (0 ); // scopes
61+ gm .ifNull (returnFalse ); // if scopes == null return false
62+
63+ gm .loadArg (0 ); // scopes
64+ gm .arrayLength (); // scopes.length
65+ gm .push (scopeIndex );
66+ gm .ifICmp (LE , returnFalse ); // scopes.length <= scopeIndex return false
67+
68+ gm .loadArg (0 ); // scopes
69+ gm .push (scopeIndex );
70+ gm .arrayLoad (Type .getType (Object .class )); // Object[]
71+ int scopeLocal = gm .newLocal (Type .getType (Object .class ));
72+ gm .storeLocal (scopeLocal );
73+ int classGuardLocal = gm .newLocal (Type .getType (Class .class ));
74+ gm .getStatic (Type .getType (className ), "classGuard" + id , Type .getType (Class .class ));
75+ gm .storeLocal (classGuardLocal );
76+
77+ gm .loadLocal (scopeLocal );
78+ gm .ifNull (scopeIsNull ); // after here scope is not null
79+
80+ gm .loadLocal (scopeLocal );
81+ gm .invokeVirtual (Type .getType (Object .class ), Method .getMethod ("Class getClass()" )); // scope.getClass()
82+ gm .loadLocal (classGuardLocal );
83+ gm .ifCmp (Type .getType (Class .class ), NE , returnFalse ); // if they are not equal return false
84+
85+ gm .goTo (next ); // next guard
86+
87+ gm .visitLabel (scopeIsNull ); // after here scope is null
88+ gm .loadLocal (classGuardLocal );
89+ gm .ifNonNull (returnFalse ); // if there is a class guard, return false
90+
91+ gm .visitLabel (next ); // end of method
92+ }
93+
3894}
0 commit comments