1 package org.metricshub.jawk.ext;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 import java.lang.reflect.Method;
26 import java.util.Collections;
27 import java.util.LinkedHashMap;
28 import java.util.Map;
29 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
30 import org.metricshub.jawk.ext.annotations.JawkFunction;
31 import org.metricshub.jawk.jrt.IllegalAwkArgumentException;
32 import org.metricshub.jawk.jrt.JRT;
33 import org.metricshub.jawk.jrt.VariableManager;
34 import org.metricshub.jawk.util.AwkSettings;
35
36
37
38
39
40
41
42
43
44
45 public abstract class AbstractExtension implements JawkExtension {
46
47 private JRT jrt;
48 private VariableManager vm;
49 private AwkSettings settings;
50 private Map<String, ExtensionFunction> annotatedFunctions;
51
52
53 @Override
54 public String getExtensionName() {
55 return getClass().getSimpleName();
56 }
57
58
59 @Override
60 @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "Extension needs direct access to runtime, VM and settings")
61 public void init(VariableManager vmParam, JRT runtime, final AwkSettings conf) {
62 this.vm = vmParam;
63 this.jrt = runtime;
64 this.settings = conf;
65 }
66
67
68
69
70
71
72
73
74
75 protected final String toAwkString(Object obj) {
76 return JRT.toAwkString(obj, getVm().getCONVFMT().toString(), settings.getLocale());
77 }
78
79
80
81
82
83
84
85
86
87 protected static void checkNumArgs(Object[] arr, int expectedNum) {
88
89
90
91
92 assert arr != null;
93 assert expectedNum >= 0;
94
95 if (arr.length != expectedNum) {
96 throw new IllegalAwkArgumentException("Expecting " + expectedNum + " arg(s), got " + arr.length);
97 }
98 }
99
100
101
102
103
104
105
106
107 protected JRT getJrt() {
108 return jrt;
109 }
110
111
112
113
114
115
116
117
118 protected VariableManager getVm() {
119 return vm;
120 }
121
122
123
124
125
126
127
128
129 protected AwkSettings getSettings() {
130 return settings;
131 }
132
133 private Map<String, ExtensionFunction> getAnnotatedFunctions() {
134 if (annotatedFunctions == null) {
135 annotatedFunctions = Collections.unmodifiableMap(scanAnnotatedFunctions());
136 }
137 return annotatedFunctions;
138 }
139
140 private Map<String, ExtensionFunction> scanAnnotatedFunctions() {
141 Map<String, ExtensionFunction> discovered = new LinkedHashMap<String, ExtensionFunction>();
142 Class<? extends AbstractExtension> type = getClass();
143 for (Method method : type.getMethods()) {
144 JawkFunction function = method.getAnnotation(JawkFunction.class);
145 if (function == null) {
146 continue;
147 }
148 String keyword = function.value();
149 ExtensionFunction existing = discovered.put(keyword, new ExtensionFunction(keyword, method));
150 if (existing != null) {
151 throw new IllegalStateException(
152 "Duplicate @JawkFunction mapping for keyword '" + keyword + "' in " + type.getName());
153 }
154 }
155 return discovered;
156 }
157
158
159 @Override
160 public Map<String, ExtensionFunction> getExtensionFunctions() {
161 return getAnnotatedFunctions();
162 }
163 }