1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.jexl3.internal;
18
19 import org.apache.commons.jexl3.JexlContext;
20 import org.apache.commons.jexl3.introspection.JexlUberspect;
21
22 import java.util.HashMap;
23 import java.util.LinkedHashSet;
24 import java.util.Map;
25 import java.util.Set;
26 import java.util.concurrent.locks.ReadWriteLock;
27 import java.util.concurrent.locks.ReentrantReadWriteLock;
28
29
30
31
32
33
34 class FqcnResolver implements JexlContext.ClassNameResolver {
35
36
37
38 private final JexlUberspect uberspect;
39
40
41
42 private final ReadWriteLock lock = new ReentrantReadWriteLock();
43
44
45
46 private final Set<String> imports = new LinkedHashSet<>();
47
48
49
50
51 private final Map<String, String> fqcns = new HashMap<>();
52
53
54
55 private final FqcnResolver parent;
56
57
58
59
60
61 private void importCheck(final Iterable<String> names) {
62 if (names != null) {
63 names.forEach(this::importCheck);
64 }
65 }
66
67
68
69
70
71 private void importCheck(final String name) {
72
73 if (name != null && Package.getPackage(name) != null) {
74 imports.add(name);
75 }
76 }
77
78 @Override
79 public String resolveClassName(final String name) {
80 return getQualifiedName(name);
81 }
82
83
84
85
86
87
88
89 FqcnResolver(final JexlUberspect uber, final Iterable<String> packages) {
90 this.uberspect = uber;
91 this.parent = null;
92 importCheck(packages);
93 }
94
95
96
97
98
99
100
101 FqcnResolver(final FqcnResolver solver) {
102 if (solver == null) {
103 throw new NullPointerException("parent solver can not be null");
104 }
105 this.parent = solver;
106 this.uberspect = solver.uberspect;
107 }
108
109
110
111
112
113
114
115 boolean isImporting(final String pkg) {
116 if (parent != null && parent.isImporting(pkg)) {
117 return true;
118 }
119 lock.readLock().lock();
120 try {
121 return imports.contains(pkg);
122 } finally {
123 lock.readLock().unlock();
124 }
125 }
126
127
128
129
130
131
132
133 FqcnResolver importPackages(final Iterable<String> packages) {
134 if (packages != null) {
135 lock.writeLock().lock();
136 try {
137 if (parent == null) {
138 importCheck(packages);
139 } else {
140 packages.forEach(pkg ->{ if (!parent.isImporting(pkg)) { importCheck(pkg); }});
141 }
142 } finally {
143 lock.writeLock().unlock();
144 }
145 }
146 return this;
147 }
148
149
150
151
152
153
154
155 String getQualifiedName(final String name) {
156 String fqcn;
157 if (parent != null && (fqcn = parent.getQualifiedName(name)) != null) {
158 return fqcn;
159 }
160 lock.readLock().lock();
161 try {
162 fqcn = fqcns.get(name);
163 } finally {
164 lock.readLock().unlock();
165 }
166 if (fqcn == null) {
167 final ClassLoader loader = uberspect.getClassLoader();
168 for (final String pkg : imports) {
169 Class<?> clazz;
170 try {
171 clazz = loader.loadClass(pkg + "." + name);
172 } catch (final ClassNotFoundException e) {
173
174 continue;
175 }
176
177 if (clazz != null) {
178 fqcn = clazz.getName();
179 lock.writeLock().lock();
180 try {
181 fqcns.put(name, fqcn);
182 } finally {
183 lock.writeLock().unlock();
184 }
185 break;
186 }
187 }
188 }
189 return fqcn;
190 }
191 }