-
Notifications
You must be signed in to change notification settings - Fork 1
/
jcasbin.drawio
120 lines (120 loc) · 53.2 KB
/
jcasbin.drawio
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
<mxfile host="Electron" modified="2024-10-16T07:20:48.930Z" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/21.6.5 Chrome/114.0.5735.243 Electron/25.3.1 Safari/537.36" etag="Z_mFZaldhdmYtSrsw8-3" version="21.6.5" type="device">
<diagram name="第 1 页" id="0amOAZ1KYqz4wGv-mDgI">
<mxGraphModel dx="3088" dy="879" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="QtVUoe-s8aGA1qfG5qBj-1" value="<h1 style="font-size: 16px;"><font style="font-size: 16px;">JCasbin (v1.40)</font></h1><p style="">使用JCasbin时碰到一些疑问,文档中又找不到解决方法,这里看下源码,源码量只有1W行。<br>主要梳理<b>Enforcer权限校验流程</b>,以及发掘<b>拓展点</b>。</p><p style="">JCasbin 用到 Aviator 这个表达式引擎,Aviator可以直接将表达式编译成Java字节码交给JVM执行。<br>用户指南:https://code.google.com/archive/p/aviator/wikis/User_Guide_zh.wiki</p><p style="">测试代码: SpringBoot-Labs/jcasbin</p>" style="text;html=1;strokeColor=none;fillColor=none;spacing=5;spacingTop=-20;whiteSpace=wrap;overflow=hidden;rounded=0;" vertex="1" parent="1">
<mxGeometry x="40" y="10" width="600" height="130" as="geometry" />
</mxCell>
<mxCell id="QtVUoe-s8aGA1qfG5qBj-4" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="QtVUoe-s8aGA1qfG5qBj-2" target="QtVUoe-s8aGA1qfG5qBj-3">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="QtVUoe-s8aGA1qfG5qBj-2" value="EnforcerTest" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
<mxGeometry x="40" y="160" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="QtVUoe-s8aGA1qfG5qBj-6" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="QtVUoe-s8aGA1qfG5qBj-3" target="QtVUoe-s8aGA1qfG5qBj-5">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="QtVUoe-s8aGA1qfG5qBj-23" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="QtVUoe-s8aGA1qfG5qBj-28" target="QtVUoe-s8aGA1qfG5qBj-22">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="QtVUoe-s8aGA1qfG5qBj-3" value="Enforcer enforcer = new Enforcer(modelFile, policyFile);" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="280" y="160" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="QtVUoe-s8aGA1qfG5qBj-41" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="QtVUoe-s8aGA1qfG5qBj-5" target="QtVUoe-s8aGA1qfG5qBj-40">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="QtVUoe-s8aGA1qfG5qBj-5" value="EnforceContext context = new EnforceContext("2");<br style="font-size: 10px;">boolean ret2 = enforcer.<b style="font-size: 10px;">enforce</b>("10006", "/sysA/config/bz1", "POST");" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontSize=10;" vertex="1" parent="1">
<mxGeometry x="280" y="480" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="QtVUoe-s8aGA1qfG5qBj-20" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;endArrow=block;endFill=1;" edge="1" parent="1" source="QtVUoe-s8aGA1qfG5qBj-8" target="QtVUoe-s8aGA1qfG5qBj-10">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="QtVUoe-s8aGA1qfG5qBj-8" value="<p style="margin: 4px 0px 0px; text-align: center; font-size: 12px;"><b style="font-size: 12px;">Enforcer</b></p><hr style="font-size: 12px;">" style="verticalAlign=top;align=left;overflow=fill;fontSize=12;fontFamily=Helvetica;html=1;rounded=0;shadow=0;comic=0;labelBackgroundColor=none;strokeWidth=1;fillColor=#fff2cc;strokeColor=#d6b656;" vertex="1" parent="1">
<mxGeometry x="-320" y="840" width="160" height="40" as="geometry" />
</mxCell>
<mxCell id="QtVUoe-s8aGA1qfG5qBj-18" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;endArrow=block;endFill=1;" edge="1" parent="1" source="QtVUoe-s8aGA1qfG5qBj-9" target="QtVUoe-s8aGA1qfG5qBj-17">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="QtVUoe-s8aGA1qfG5qBj-9" value="<p style="margin: 4px 0px 0px; text-align: center; font-size: 12px;"><b style="font-size: 12px;">InternalEnforcer</b></p><hr style="font-size: 12px;">" style="verticalAlign=top;align=left;overflow=fill;fontSize=12;fontFamily=Helvetica;html=1;rounded=0;shadow=0;comic=0;labelBackgroundColor=none;strokeWidth=1;" vertex="1" parent="1">
<mxGeometry x="-320" y="560" width="160" height="40" as="geometry" />
</mxCell>
<mxCell id="QtVUoe-s8aGA1qfG5qBj-19" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;endArrow=block;endFill=1;" edge="1" parent="1" source="QtVUoe-s8aGA1qfG5qBj-10" target="QtVUoe-s8aGA1qfG5qBj-9">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="QtVUoe-s8aGA1qfG5qBj-10" value="<p style="margin: 4px 0px 0px; text-align: center; font-size: 12px;"><b style="font-size: 12px;">ManagementEnforcer</b></p><hr style="font-size: 12px;"><p style="margin: 0px 0px 0px 4px; line-height: 1.6; font-size: 12px;"> allSubjects: List&lt;String&gt;<br style="font-size: 12px;"> allActions: List&lt;String&gt;<br style="font-size: 12px;"> allRoles: List&lt;String&gt;<br style="font-size: 12px;"> allObjects: List&lt;String&gt;<br style="font-size: 12px;"> policy: List&lt;List&lt;String&gt;&gt;<br style="font-size: 12px;"> groupingPolicy: List&lt;List&lt;String&gt;&gt;</p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=12;fontFamily=Helvetica;html=1;rounded=0;shadow=0;comic=0;labelBackgroundColor=none;strokeWidth=1;" vertex="1" parent="1">
<mxGeometry x="-440.5" y="645" width="400" height="160" as="geometry" />
</mxCell>
<mxCell id="QtVUoe-s8aGA1qfG5qBj-27" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.25;exitDx=0;exitDy=0;endArrow=open;endFill=0;" edge="1" parent="1" source="QtVUoe-s8aGA1qfG5qBj-14" target="QtVUoe-s8aGA1qfG5qBj-26">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="QtVUoe-s8aGA1qfG5qBj-14" value="<p style="margin:0px;margin-top:4px;text-align:center;"><b>Policy</b><br></p><hr size="1"><p style="margin:0px;margin-left:4px;"><font color="#007fff">// 这是真正的模型加载后的模型对象</font></p><p style="margin:0px;margin-left:4px;"><font color="#007fff">// 模型段名 -&gt; 这段中每一行的Key Value, Value 被转成 Assertion</font></p><p style="margin:0px;margin-left:4px;">public Map&lt;String, Map&lt;String, Assertion&gt;&gt; <b>model</b>;</p><hr size="1"><p style="margin:0px;margin-left:4px;"><br></p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=12;fontFamily=Helvetica;html=1;whiteSpace=wrap;fillColor=#fff2cc;strokeColor=#d6b656;" vertex="1" parent="1">
<mxGeometry x="-880" y="160" width="400" height="120" as="geometry" />
</mxCell>
<mxCell id="QtVUoe-s8aGA1qfG5qBj-16" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;endArrow=block;endFill=1;" edge="1" parent="1" source="QtVUoe-s8aGA1qfG5qBj-15" target="QtVUoe-s8aGA1qfG5qBj-14">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="QtVUoe-s8aGA1qfG5qBj-15" value="<p style="margin:0px;margin-top:4px;text-align:center;"><b>Model</b></p><hr size="1"><p style="margin:0px;margin-left:4px;"><font color="#007fff"><b>权限模型</b></font></p><p style="margin:0px;margin-left:4px;"><font color="#007fff"><br></font></p><p style="margin:0px;margin-left:4px;"><font color="#007fff">// 仅仅保存模型文件中各个部分的缩略名,比如 “r” -&gt; "request_definition"</font></p><p style="margin:0px;margin-left:4px;">private static final Map&lt;String, String&gt; <b>sectionNameMap</b>;</p><p style="margin:0px;margin-left:4px;"><font color="#007fff">// 记录修改次数</font></p><p style="margin:0px;margin-left:4px;">protected int modCount;</p><p style="margin:0px;margin-left:4px;">private int domainIndex = -1;</p><p style="margin:0px;margin-left:4px;">private String defaultDomain = "";</p><p style="margin:0px;margin-left:4px;">private String defaultSeparator = "::";</p><hr size="1"><p style="margin:0px;margin-left:4px;"><font color="#007fff">提供了一些加载模型文件,添加模型数据等方法</font></p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=12;fontFamily=Helvetica;html=1;whiteSpace=wrap;" vertex="1" parent="1">
<mxGeometry x="-880" y="320" width="400" height="200" as="geometry" />
</mxCell>
<mxCell id="QtVUoe-s8aGA1qfG5qBj-21" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.004;exitY=0.233;exitDx=0;exitDy=0;endArrow=open;endFill=0;exitPerimeter=0;" edge="1" parent="1" source="QtVUoe-s8aGA1qfG5qBj-17" target="QtVUoe-s8aGA1qfG5qBj-15">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="QtVUoe-s8aGA1qfG5qBj-39" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.004;exitY=0.956;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;endArrow=open;endFill=0;exitPerimeter=0;" edge="1" parent="1" source="QtVUoe-s8aGA1qfG5qBj-17" target="QtVUoe-s8aGA1qfG5qBj-38">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="QtVUoe-s8aGA1qfG5qBj-17" value="<p style="margin: 4px 0px 0px; text-align: center;"><b>CoreEnforcer</b></p><hr size="1"><p style="margin:0px;margin-left:4px;"><font color="#007fff"><span style="background-color: initial;">// 模型文件的路径,ini 文件</span><br></font></p><p style="margin:0px;margin-left:4px;">String modelPath;</p><p style="margin:0px;margin-left:4px;"><font color="#007fff">// 权限模型</font></p><p style="margin:0px;margin-left:4px;">Model <b>model</b>;</p><p style="margin:0px;margin-left:4px;"><font color="#007fff">// 函数Map, 存储内置以及外部添加的函数,这些函数最终是要加入到&nbsp;</font></p><font color="#007fff"><b>aviatorEval</b> 中使用<br></font><p style="margin:0px;margin-left:4px;">FunctionMap <b>fm</b>;</p><p style="margin:0px;margin-left:4px;">private Effector <b>eft</b>;</p><p style="margin:0px;margin-left:4px;"><font color="#007fff">// 策略数据源的适配器,比如 FileAdapter、JDBCAdapter</font></p><p style="margin:0px;margin-left:4px;">Adapter <b>adapter</b>;</p><p style="margin:0px;margin-left:4px;">Watcher watcher;</p><p style="margin:0px;margin-left:4px;">Dispatcher dispatcher;</p><p style="margin:0px;margin-left:4px;">Map&lt;String, RoleManager&gt; rmMap;</p><p style="margin:0px;margin-left:4px;"><br></p><p style="margin:0px;margin-left:4px;"><font color="#007fff">// 初始化时设置为true</font></p><p style="margin:0px;margin-left:4px;">private boolean <b>enabled</b>;</p><p style="margin:0px;margin-left:4px;">boolean autoSave;</p><p style="margin:0px;margin-left:4px;">boolean autoBuildRoleLinks;</p><p style="margin:0px;margin-left:4px;">boolean autoNotifyWatcher = true;</p><p style="margin:0px;margin-left:4px;">boolean autoNotifyDispatcher = true;</p><p style="margin:0px;margin-left:4px;"><br></p><p style="margin:0px;margin-left:4px;">private AviatorEvaluatorInstance <b>aviatorEval</b>;</p><hr size="1"><p style="margin:0px;margin-left:4px;"><br></p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=12;fontFamily=Helvetica;html=1;whiteSpace=wrap;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
<mxGeometry x="-440.5" y="160" width="400" height="360" as="geometry" />
</mxCell>
<mxCell id="QtVUoe-s8aGA1qfG5qBj-22" value="Model m = new Model();<br>m.<b>loadModel</b>(modelPath);" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="760" y="160" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="QtVUoe-s8aGA1qfG5qBj-25" value="<font color="#007fff">解析INI类型权限模型文件内容到 Config 对象(本质是两层的HashMap),<br>然后依次加载每一段,到 Model 对应的定义中</font>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
<mxGeometry x="970" y="170" width="420" height="40" as="geometry" />
</mxCell>
<mxCell id="QtVUoe-s8aGA1qfG5qBj-26" value="<p style="margin:0px;margin-top:4px;text-align:center;"><b>Assertion</b><br></p><hr size="1"><p style="margin:0px;margin-left:4px;"><font color="#007fff">比如 policy_definition 中定义了两行&nbsp;</font></p><p style="margin:0px;margin-left:4px;"><font color="#007fff">p = sub, obj, act</font></p><p style="margin:0px;margin-left:4px;"><font color="#007fff">p2 = sub, sub2, obj, act</font></p><p style="margin:0px;margin-left:4px;"><span style="background-color: initial;"><br></span></p><p style="margin:0px;margin-left:4px;"><span style="background-color: initial;"><font color="#007fff">// 对应 p p2</font></span></p><p style="margin:0px;margin-left:4px;"><span style="background-color: initial;">public String key;&nbsp;</span></p><p style="margin:0px;margin-left:4px;"><span style="background-color: initial;"><font color="#007fff">// 对应 sub, obj, act</font></span></p><p style="margin:0px;margin-left:4px;"><span style="background-color: initial;">public String value;</span></p><p style="margin:0px;margin-left:4px;">public String[] <b>tokens</b>;</p><p style="margin:0px;margin-left:4px;"><font color="#007fff">// 从策略数据源加载的key对应的策略数据行</font></p><p style="margin:0px;margin-left:4px;">public List&lt;List&lt;String&gt;&gt; <b>policy</b>;</p><p style="margin:0px;margin-left:4px;">public Map&lt;String, Integer&gt; <b>policyIndex</b>;</p><p style="margin:0px;margin-left:4px;"><font color="#007fff">// RoleManager 中保存角色继承关系</font></p><p style="margin:0px;margin-left:4px;">public RoleManager <b>rm</b>;</p><p style="margin:0px;margin-left:4px;">public int priorityIndex;</p><hr size="1"><p style="margin:0px;margin-left:4px;"><br></p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=12;fontFamily=Helvetica;html=1;whiteSpace=wrap;" vertex="1" parent="1">
<mxGeometry x="-1320" y="160" width="400" height="280" as="geometry" />
</mxCell>
<mxCell id="QtVUoe-s8aGA1qfG5qBj-29" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="QtVUoe-s8aGA1qfG5qBj-3" target="QtVUoe-s8aGA1qfG5qBj-28">
<mxGeometry relative="1" as="geometry">
<mxPoint x="480" y="190" as="sourcePoint" />
<mxPoint x="760" y="190" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="QtVUoe-s8aGA1qfG5qBj-30" value="..." style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="QtVUoe-s8aGA1qfG5qBj-29">
<mxGeometry relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="QtVUoe-s8aGA1qfG5qBj-33" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="QtVUoe-s8aGA1qfG5qBj-28" target="QtVUoe-s8aGA1qfG5qBj-31">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="QtVUoe-s8aGA1qfG5qBj-28" value="this(newModel(modelPath, ""), adapter);" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="520" y="160" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="QtVUoe-s8aGA1qfG5qBj-31" value="<div>public Enforcer(Model m, Adapter adapter, boolean enableLog) {</div><div>&nbsp; &nbsp; this.adapter = adapter;</div><div>&nbsp; &nbsp; this.watcher = null;</div><div>&nbsp; &nbsp; model = m;</div><div>&nbsp; &nbsp; ...</div><div><font color="#007fff"><b>&nbsp; &nbsp; // 加载内置的函数,比如&nbsp;keyMatch、keyGet、regexMatch</b></font></div><div>&nbsp; &nbsp; fm = FunctionMap.<b>loadFunctionMap</b>();</div><div><font color="#007fff"><b>&nbsp; &nbsp; // 初始化 CoreEnforcer 中成员</b></font></div><div>&nbsp; &nbsp; <b>initialize</b>();</div><div><font color="#007fff"><b>&nbsp; &nbsp; // 加载策略数据,即 csv 文件中的数据</b></font></div><div>&nbsp; &nbsp; if (this.adapter != null &amp;&amp; !isFiltered()) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; <b>loadPolicy</b>();</div><div>&nbsp; &nbsp; }</div><div>}</div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;arcSize=3;" vertex="1" parent="1">
<mxGeometry x="760" y="240" width="440" height="200" as="geometry" />
</mxCell>
<mxCell id="QtVUoe-s8aGA1qfG5qBj-34" value="<div style="font-size: 11px;">private EnforceResult enforce(String matcher, Object... rvals) {</div><div style="font-size: 11px;">&nbsp; &nbsp; ...</div><div style="font-size: 11px;">&nbsp; &nbsp; boolean compileCached = true;</div><div style="font-size: 11px;">&nbsp; &nbsp; if (fm.isModify) { <font color="#007fff">//是否有添加函数</font></div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; compileCached = false;</div><div style="font-size: 11px;"><font color="#007fff"><b>&nbsp; &nbsp; &nbsp; &nbsp; // 将内置函数加入&nbsp;aviatorEval</b></font></div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; <b>initBuiltInFunction</b>();</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; fm.isModify = false;</div><div style="font-size: 11px;">&nbsp; &nbsp; }</div><div style="font-size: 11px;"><font color="#007fff"><b>&nbsp; &nbsp; // 读取模型中 role_definition, 生成 AviatorFunction 并添加到 aviatorEval</b></font></div><div style="font-size: 11px;">&nbsp; &nbsp; Map&lt;String, AviatorFunction&gt; <b>gFunctions</b> = new HashMap&lt;&gt;();</div><div style="font-size: 11px;"><span style="background-color: initial;">&nbsp; &nbsp; if (model.model.containsKey("g")) {</span><br></div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; for (Map.Entry&lt;String, Assertion&gt; entry : model.model.get("g").entrySet()) {</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; String key = entry.getKey();</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Assertion ast = entry.getValue();</div><div style="font-size: 11px;"><font style="" color="#007fff"><span style="">&nbsp;&nbsp;&nbsp;&nbsp;</span>&nbsp; &nbsp; &nbsp; &nbsp; // 权限模型 g 段中 RoleManager 实例保存从策略数据源解析到的所有角色及其继承关系</font><br style="font-size: 11px;"></div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; RoleManager rm = ast.rm;</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AviatorFunction aviatorFunction = BuiltInFunctions.GenerateGFunctionClass.<b>generateGFunction</b>(key, rm);</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gFunctions.put(key, aviatorFunction);</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="font-size: 11px;">&nbsp; &nbsp; }</div><div style="font-size: 11px;">&nbsp; &nbsp; <font color="#007fff">//&nbsp;</font></div><div style="font-size: 11px;">&nbsp; &nbsp; for (AviatorFunction f : gFunctions.values()) {</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; if (!aviatorEval.containsFunction(f.getName())) {</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; aviatorEval.<b>addFunction</b>(f);</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; compileCached = false;</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="font-size: 11px;">&nbsp; &nbsp; }</div><div style="font-size: 11px;"><font color="#007fff"><b>&nbsp; &nbsp; // 更新 FunctionMap 中所有函数的&nbsp;aviatorEval, 即 FunctionMap 中的函数执行也是依赖 Aviator 引擎执行的</b></font></div><div style="font-size: 11px;">&nbsp; &nbsp; fm.setAviatorEval(aviatorEval);</div><div style="font-size: 11px;"><br style="font-size: 11px;"></div><div style="font-size: 11px;">&nbsp; &nbsp; String rType = "r", pType = "p", eType = "e", mType = "m";</div><div style="font-size: 11px;">&nbsp; &nbsp; if (rvals.length != 0) {</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; if (rvals[0] instanceof EnforceContext) {</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; EnforceContext enforceContext = (EnforceContext) rvals[0];</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rType = enforceContext.getrType();</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pType = enforceContext.getpType();</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; eType = enforceContext.geteType();</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mType = enforceContext.getmType();</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rvals = Arrays.copyOfRange(rvals, 1, rvals.length);</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="font-size: 11px;">&nbsp; &nbsp; }</div><div style="font-size: 11px;"><br style="font-size: 11px;"></div><div style="font-size: 11px;">&nbsp; &nbsp; String expString;</div><div style="font-size: 11px;">&nbsp; &nbsp; if (matcher == null || "".equals(matcher)) {</div><div style="font-size: 11px;"><font color="#007fff">&nbsp; &nbsp; &nbsp; &nbsp; // 获取模型中定义的<b>matcher表达式</b>, 比如&nbsp;g(r_sub, p_sub) &amp;&amp; r_obj == p_obj &amp;&amp; r_act == p_act</font></div><div style="font-size: 11px;"><font color="#007fff"><b>&nbsp; &nbsp; &nbsp; &nbsp; // 如果定义了多组 matcher 表达式,根本不会同时被使用</b></font></div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; expString = model.model.<b>get</b>("m").get(mType).value;</div><div style="font-size: 11px;">&nbsp; &nbsp; } else {</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; expString = Util.removeComments(Util.escapeAssertion(matcher));</div><div style="font-size: 11px;">&nbsp; &nbsp; }</div><div style="font-size: 11px;"><font color="#007fff">&nbsp; &nbsp; // 只是为了支持 in 语法添加的转换逻辑</font></div><div style="font-size: 11px;">&nbsp; &nbsp; expString = Util.convertInSyntax(expString);</div><div style="font-size: 11px;"><font color="#007fff">&nbsp; &nbsp; // <b>将 matcher 表达式编译成 Aviator 表达式</b>,估计是 Java 字节码</font></div><div style="font-size: 11px;">&nbsp; &nbsp; // Use md5 encryption as cacheKey to prevent expString from being too long</div><div style="font-size: 11px;">&nbsp; &nbsp; Expression <b>expression</b> = aviatorEval.<b>compile</b>(Util.md5(expString), expString, compileCached);</div><div style="font-size: 11px;"><br style="font-size: 11px;"></div><div style="font-size: 11px;">&nbsp; &nbsp; StreamEffector streamEffector = null;</div><div style="font-size: 11px;">&nbsp; &nbsp; try {</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; streamEffector = this.eft.newStreamEffector(model.model.get("e").get(eType).value);</div><div style="font-size: 11px;">&nbsp; &nbsp; } catch (Exception e) {</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; if (!(e instanceof UnsupportedOperationException)) {</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw new CasbinEffectorException(e);</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="font-size: 11px;">&nbsp; &nbsp; }</div><div style="font-size: 11px;"><br style="font-size: 11px;"></div><div style="font-size: 11px;">&nbsp; &nbsp; Effect[] policyEffects;</div><div style="font-size: 11px;">&nbsp; &nbsp; float[] matcherResults;</div><div style="font-size: 11px;">&nbsp; &nbsp; <font color="#007fff">// 没有 EnforcerContext 传参的话,</font><font color="#007fff">pType 就是写死的 p, 且 policy 只会加载一种,对于下面后两种策略<b>根本不会同时被使用</b></font></div><div style="font-size: 11px;"><font color="#007fff">&nbsp; &nbsp; //&nbsp;p, ROLE_BIZA_PM, /sysA/config/bz1, POST</font></div><div><font color="#007fff">&nbsp; &nbsp; // p2, ROLE_BIZA_BACKEND, ROLE_T3, /sysA/config/bz1, POST</font></div><div><font color="#007fff">&nbsp; &nbsp; // p2, ROLE_BIZA_BACKEND, ROLE_T2, /sysA/config/bz1, POST</font></div><div style="font-size: 11px;">&nbsp; &nbsp; final List&lt;List&lt;String&gt;&gt; <b>policy</b> = model.model.<b>get("p")</b>.<b>get</b>(<b>pType</b>).policy;</div><div style="font-size: 11px;">&nbsp; &nbsp; final String[] pTokens = model.model.get("p").get(pType).tokens;</div><div style="font-size: 11px;">&nbsp; &nbsp; final int policyLen = policy.size();</div><div style="font-size: 11px;">&nbsp; &nbsp; int explainIndex = -1;</div><div style="font-size: 11px;"><br style="font-size: 11px;"></div><div style="font-size: 11px;">&nbsp; &nbsp; if (policyLen != 0) {</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; policyEffects = new Effect[policyLen];</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; matcherResults = new float[policyLen];</div><div style="font-size: 11px;"><font color="#007fff">&nbsp; &nbsp; &nbsp; &nbsp; // 遍历 pType 类型的策略,使用</font></div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; for (int i = 0; i &lt; policy.size(); i++) {</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; List&lt;String&gt; pvals = policy.get(i);</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Map&lt;String, Object&gt; parameters = new HashMap&lt;&gt;(rvals.length + pTokens.length);</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; getPTokens(parameters, pType, pvals, pTokens);</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; getRTokens(parameters, rType, rvals);</div><div style="font-size: 11px;"><font color="#007fff">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // 表达式的 Java 字节码交给 JVM 执行, 即<b>执行 request 到 policy 的匹配逻辑(matcher)</b></font></div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Object result = expression.<b>execute</b>(parameters);</div><div style="font-size: 11px;"><br style="font-size: 11px;"></div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (result instanceof <b>Boolean</b>) {</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!((boolean) result)) {</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; policyEffects[i] = Effect.Indeterminate;</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else {</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; policyEffects[i] = Effect.Allow;</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (streamEffector == null) {</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; continue;</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else if (result instanceof <b>Double</b> || result instanceof <b>Long</b>) {</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (((Number) result).floatValue() == 0) {</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; policyEffects[i] = Effect.Indeterminate;</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else {</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; matcherResults[i] = ((Number) result).floatValue();</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; policyEffects[i] = Effect.Allow;</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (streamEffector == null) {</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; continue;</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else {</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw new CasbinMatcherException("matcher result should be Boolean, Double or Long");</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (policyEffects[i] == Effect.Allow &amp;&amp; parameters.containsKey(pType + "_eft")) {</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; String eft = (String) parameters.get(pType + "_eft");</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ("allow".equals(eft)) {</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; policyEffects[i] = Effect.Allow;</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else if ("deny".equals(eft)) {</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; policyEffects[i] = Effect.Deny;</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else {</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; policyEffects[i] = Effect.Indeterminate;</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="font-size: 11px;"><br style="font-size: 11px;"></div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (streamEffector != null) {</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; boolean done = streamEffector.push(policyEffects[i], i, policyLen);</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (done) {</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else {</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ("priority(p_eft) || deny".equals(model.model.get("e").get(eType).value)) {</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; explainIndex = streamEffector.current().getExplainIndex();</div><div style="font-size: 11px;">&nbsp; &nbsp; } else {&nbsp; <b><font color="#007fff">// policy 条数为0</font></b></div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; policyEffects = new Effect[1];</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; matcherResults = new float[1];</div><div style="font-size: 11px;"><br style="font-size: 11px;"></div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; String[] rTokens = model.model.get("r").get(rType).tokens;</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; Map&lt;String, Object&gt; parameters = new HashMap&lt;&gt;(rTokens.length + pTokens.length);</div><div style="font-size: 11px;"><br style="font-size: 11px;"></div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; for (int j = 0; j &lt; rTokens.length; j++) {</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; parameters.put(rTokens[j], rvals[j]);</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; for (String token : pTokens) {</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; parameters.put(token, "");</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="font-size: 11px;"><br style="font-size: 11px;"></div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; Object result = expression.execute(parameters);</div><div style="font-size: 11px;"><br style="font-size: 11px;"></div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; if (streamEffector != null) {</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ((boolean) result) {</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; streamEffector.push(Effect.Allow, 0, 1);</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else {</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; streamEffector.push(Effect.Indeterminate, 0, 1);</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; } else {</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ((boolean) result) {</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; policyEffects[0] = Effect.Allow;</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else {</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; policyEffects[0] = Effect.Indeterminate;</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="font-size: 11px;">&nbsp; &nbsp; }</div><div style="font-size: 11px;"><br style="font-size: 11px;"></div><div style="font-size: 11px;">&nbsp; &nbsp; boolean result;</div><div style="font-size: 11px;"><br style="font-size: 11px;"></div><div style="font-size: 11px;">&nbsp; &nbsp; if (streamEffector != null &amp;&amp; streamEffector.current() != null) {</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; result = streamEffector.current().hasEffect();</div><div style="font-size: 11px;">&nbsp; &nbsp; } else {</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; result = eft.mergeEffects(model.model.get("e").get(eType).value, policyEffects, matcherResults);</div><div style="font-size: 11px;">&nbsp; &nbsp; }</div><div style="font-size: 11px;"><br style="font-size: 11px;"></div><div style="font-size: 11px;">&nbsp; &nbsp; List&lt;String&gt; explain = new ArrayList&lt;&gt;();</div><div style="font-size: 11px;">&nbsp; &nbsp; if (explainIndex != -1) {</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; explain.addAll(policy.get(explainIndex));</div><div style="font-size: 11px;">&nbsp; &nbsp; }</div><div style="font-size: 11px;"><br style="font-size: 11px;"></div><div style="font-size: 11px;">&nbsp; &nbsp; Util.logEnforce(rvals, result, explain);</div><div style="font-size: 11px;">&nbsp; &nbsp; return new EnforceResult(result, explain);</div><div style="font-size: 11px;">}</div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;arcSize=1;fontSize=11;" vertex="1" parent="1">
<mxGeometry x="760" y="480" width="680" height="2400" as="geometry" />
</mxCell>
<mxCell id="QtVUoe-s8aGA1qfG5qBj-36" value="CoreEnforcer" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
<mxGeometry x="815" y="450" width="90" height="30" as="geometry" />
</mxCell>
<mxCell id="QtVUoe-s8aGA1qfG5qBj-37" value="可拓展点:<br><ul><li><br></li></ul>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
<mxGeometry x="680" y="10" width="80" height="70" as="geometry" />
</mxCell>
<mxCell id="QtVUoe-s8aGA1qfG5qBj-38" value="<p style="margin: 4px 0px 0px; text-align: center; font-size: 12px;"><b style="font-size: 12px;">AviatorEvaluatorInstance</b><br style="font-size: 12px;"></p><hr style="font-size: 12px;"><p style="margin: 0px 0px 0px 4px; font-size: 12px;"><font color="#007fff" style="font-size: 12px;"><span style="background-color: initial; font-size: 12px;"><b>封装的Aviator表达式执行引擎</b></span></font></p><p style="margin: 0px 0px 0px 4px; font-size: 12px;"><font color="#007fff" style="font-size: 12px;"><span style="background-color: initial; font-size: 12px;"><br></span></font></p><p style="margin: 0px 0px 0px 4px; font-size: 12px;"><span style="background-color: initial;">private volatile AviatorClassLoader aviatorClassLoader = this.initAviatorClassLoader();</span><br></p><p style="margin: 0px 0px 0px 4px; font-size: 12px;">private OutputStream traceOutputStream;</p><p style="margin: 0px 0px 0px 4px; font-size: 12px;">private FunctionMissing functionMissing;</p><p style="margin: 0px 0px 0px 4px; font-size: 12px;">private int bytecodeVersion;</p><p style="margin: 0px 0px 0px 4px; font-size: 12px;">private EnvProcessor envProcessor;</p><p style="margin: 0px 0px 0px 4px; font-size: 12px;">private volatile Map&lt;Options, Options.Value&gt; options;</p><p style="margin: 0px 0px 0px 4px; font-size: 12px;">private List&lt;FunctionLoader&gt; functionLoaders;</p><p style="margin: 0px 0px 0px 4px; font-size: 12px;">private static final String[] libs = new String[]{"aviator.av"};</p><p style="margin: 0px 0px 0px 4px; font-size: 12px;">private static volatile Map&lt;String, AviatorFunction&gt; internalASMLibFunctions;</p><p style="margin: 0px 0px 0px 4px; font-size: 12px;">private static volatile Map&lt;String, AviatorFunction&gt; internalInterpretedLibFunctions;</p><p style="margin: 0px 0px 0px 4px; font-size: 12px;"><font color="#007fff">// 内置函数、生成的 GFunction 都存放在这里</font></p><p style="margin: 0px 0px 0px 4px; font-size: 12px;">private final Map&lt;String, Object&gt; <b>funcMap</b>;</p><p style="margin: 0px 0px 0px 4px; font-size: 12px;">private final ConcurrentHashMap&lt;String, Object&gt; moduleCache;</p><p style="margin: 0px 0px 0px 4px; font-size: 12px;">private final Map&lt;OperatorType, AviatorFunction&gt; opsMap;</p><p style="margin: 0px 0px 0px 4px; font-size: 12px;">private final ConcurrentHashMap&lt;String, FutureTask&lt;Expression&gt;&gt; expressionCache;</p><p style="margin: 0px 0px 0px 4px; font-size: 12px;">private LRUMap&lt;String, FutureTask&lt;Expression&gt;&gt; expressionLRUCache;</p><p style="margin: 0px 0px 0px 4px; font-size: 12px;">private boolean cachedExpressionByDefault;</p><hr style="font-size: 12px;"><p style="margin: 0px 0px 0px 4px; font-size: 12px;"><br style="font-size: 12px;"></p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=12;fontFamily=Helvetica;html=1;whiteSpace=wrap;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
<mxGeometry x="-1000" y="560" width="520" height="360" as="geometry" />
</mxCell>
<mxCell id="QtVUoe-s8aGA1qfG5qBj-42" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="QtVUoe-s8aGA1qfG5qBj-40" target="QtVUoe-s8aGA1qfG5qBj-34">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="QtVUoe-s8aGA1qfG5qBj-40" value="return enforce(null, rvals)<br>.isAllow();" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="520" y="480" width="200" height="60" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>