This repository was archived by the owner on Jul 20, 2024. It is now read-only.
forked from splunk/splunk-sdk-java
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathInputCollection.java
More file actions
407 lines (366 loc) · 14.8 KB
/
InputCollection.java
File metadata and controls
407 lines (366 loc) · 14.8 KB
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
/*
* Copyright 2012 Splunk, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"): you may
* not use this file except in compliance with the License. You may obtain
* a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package com.splunk;
import java.util.*;
/**
* The {@code InputCollection} class represents a collection of inputs. The
* collection is heterogeneous and each member contains an {@code InputKind}
* value that indicates the specific type of input.
*/
public class InputCollection extends EntityCollection<Input> {
protected Set<InputKind> inputKinds = new HashSet<InputKind>();
/**
* Class constructor.
*
* @param service The connected {@code Service} instance.
*/
InputCollection(Service service) {
super(service, "data/inputs");
}
/**
* Class constructor.
*
* @param service The connected {@code Service} instance.
* @param args Collection arguments that specify the number of entities to
* return and how to sort them. See {@link CollectionArgs}.
*/
InputCollection(Service service, Args args) {
super(service, "data/inputs", args);
}
/** {@inheritDoc} */
@Override public boolean containsKey(Object key) {
Input input = retrieveInput((String)key);
return (input != null);
}
/**
* Creates a stub for a new data input.
*
* @param name Depending on the type of input, a string that contains:
* <ul><li>The filename or directory and path (for monitor and oneshot
* inputs)</li>
* <li> The script name (for script inputs)</li>
* <li> The port number (for TCP and UDP inputs)</li>
* <li> The collection name (for Windows Perfmon and WMI inputs)</li>
* <li> The stanza (for Windows Registry inputs)</li>
* <li> The name of the configuration (for Windows AD inputs)</li></ul>
* @return No return value.
* @throws UnsupportedOperationException
*/
@Override public Input create(String name) {
throw new UnsupportedOperationException();
}
/**
* Creates a stub for a new data input based on additional arguments.
*
* @param name Depending on the type of data input, a string that contains:
* <ul><li>The filename or directory and path (for monitor and oneshot
* inputs)</li>
* <li> The script name (for script inputs)</li>
* <li> The port number (for TCP and UDP inputs)</li>
* <li> The collection name (for Windows Perfmon and WMI inputs)</li>
* <li> The stanza (for Windows Registry inputs)</li>
* <li> The name of the configuration (for Windows AD inputs)</li></ul>
* @param args Optional arguments to define the data input. For a list of
* the available parameters, see
* <a href="http://dev.splunk.com/view/SP-CAAAEJ2#inputparams"
* target="_blank">Input parameters</a> on
* <a href="http://dev.splunk.com/view/SP-CAAAEJ2"
* target="_blank">dev.splunk.com</a>.
* @return No return value.
* @throws UnsupportedOperationException
*/
@Override public Input create(String name, Map args) {
throw new UnsupportedOperationException();
}
/**
* Creates a new data input based on the input kind.
*
* @param name Depending on the type of data input, a string that contains:
* <ul><li>The filename or directory and path (for monitor and oneshot
* inputs)</li>
* <li> The script name (for script inputs)</li>
* <li> The port number (for TCP and UDP inputs)</li>
* <li> The collection name (for Windows Perfmon and WMI inputs)</li>
* <li> The stanza (for Windows Registry inputs)</li>
* <li> The name of the configuration (for Windows AD inputs)</li></ul>
* @param kind A member of {@code InputKind}, indicating the type of input.
* @param <T> The implicit type of the input.
* @return The {@code Input} that was created.
*/
public <T extends Input> T create(String name, InputKind kind) {
return (T)create(name, kind, (Map<String, Object>)null);
}
/**
* Creates a new data input based on the input kind and additional
* arguments.
*
* @param name Depending on the type of data input, a string that contains:
* <ul><li>The filename or directory and path (for monitor and oneshot
* inputs)</li>
* <li> The script name (for script inputs)</li>
* <li> The port number (for TCP and UDP inputs)</li>
* <li> The collection name (for Windows Perfmon and WMI inputs)</li>
* <li> The stanza (for Windows Registry inputs)</li>
* <li> The name of the configuration (for Windows AD inputs)</li></ul>
* @param kind A member of {@code InputKind}, indicating the type of input.
* @param args Optional arguments to define the data input. For a list of
* the available parameters, see
* <a href="http://dev.splunk.com/view/SP-CAAAEJ2#inputparams"
* target="_blank">Input parameters</a> on
* <a href="http://dev.splunk.com/view/SP-CAAAEJ2"
* target="_blank">dev.splunk.com</a>.
* @param <T> The implicit type of the input.
* @return The {@code Input} that was created.
*/
public <T extends Input> T
create(String name, InputKind kind, Map<String, Object> args) {
args = Args.create(args).add("name", name);
String path = this.path + "/" + kind.getRelativePath();
service.post(path, args);
invalidate();
return (T)get(name);
}
/**
* Creates a new data input based on an Atom entry.
*
* @param entry The {@code AtomEntry} object describing the entry.
* @return The {@code Input} that was created.
*/
@Override
protected Input createItem(AtomEntry entry) {
String path = itemPath(entry);
InputKind kind = itemKind(path);
Class inputClass = kind.getInputClass();
return createItem(inputClass, path, null);
}
/**
* {@inheritDoc}
*/
@Override public Input get(Object key) {
return retrieveInput((String)key);
}
/**
* Returns the value of a scoped, namespace-constrained key, if it
* exists within this collection.
*
* @param key The key to look up.
* @param namespace The namespace to constrain the search to.
* @return The value indexed by the key, or {@code null} if it doesn't
* exist.
*/
public Input get(Object key, Args namespace) {
Util.ensureNamespaceIsExact(namespace);
return retrieveInput((String)key, namespace);
}
/**
* Returns the input kind for a given path.
*
* @param path The relative endpoint path (the path that follows
* data/inputs).
* @return A member of {@code InputKind}, indicating the type of input.
*/
protected InputKind itemKind(String path) {
String relpathWithInputName = Util.substringAfter(path, "/data/inputs/", null);
for (InputKind kind : inputKinds) {
if (relpathWithInputName.startsWith(kind.getRelativePath())) {
return kind;
}
}
// Not good. This means that there is an input of an unknown kind.
return InputKind.Unknown;
}
/**
* Return a set of all the input kinds recognized by the Splunk server.
*
* @return A set of {@code InputKind}s.
*/
public Set<InputKind> getInputKinds() {
return this.inputKinds;
}
/**
* Indicates whether a given string matches the input name (string
* equality). For scripted inputs, which are listed by their full path, this
* method compares only the final component of the filename for a match.
*
* @param kind A member of {@code InputKind}, indicating the type of input.
* @param searchFor A string to search for.
* @param searchIn The string that contains the input name.
* @return {@code true} if the string matches the input name, {@code false}
* if not.
*/
protected static boolean matchesInputName(InputKind kind, String searchFor, String searchIn) {
if (kind == InputKind.Script) {
return searchIn.endsWith("/" + searchFor) || searchIn.endsWith("\\" + searchFor);
} else {
return searchFor.equals(searchIn);
}
}
/**
* Assembles a set of all the input kinds that are available on this Splunk
* instance. To list all inputs, pass an empty list to {@code subPath}. Or,
* specify a component of the path such as "tcp" to list all TCP inputs.
*
* @param subPath A list of strings containing the components of the
* endpoint path that follow data/inputs/.
* @return A set of available {@code InputKind}s.
*/
private Set<InputKind> assembleInputKindSet(List<String> subPath) {
Set<InputKind> kinds = new HashSet<InputKind>();
ResponseMessage response = service.get(this.path + "/" + Util.join("/", subPath));
AtomFeed feed = AtomFeed.parseStream(response.getContent());
for (AtomEntry entry : feed.entries) {
String itemKeyName = itemKey(entry);
boolean hasCreateLink = false;
for (String linkName : entry.links.keySet()) {
if (linkName.equals("create")) {
hasCreateLink = true;
}
}
List<String> thisSubPath = new ArrayList<String>(subPath);
thisSubPath.add(itemKeyName);
String relpath = Util.join("/", thisSubPath);
if (relpath.equals("all") || relpath.equals("tcp/ssl")) {
// Skip these input types
continue;
} else if (hasCreateLink) {
// Found an InputKind leaf
InputKind newKind = InputKind.create(relpath);
kinds.add(newKind);
} else {
Set<InputKind> subKinds = assembleInputKindSet(thisSubPath);
kinds.addAll(subKinds);
}
}
return kinds;
}
/**
* Refreshes the {@code inputKinds} field on this object.
*/
private void refreshInputKinds() {
Set<InputKind> kinds = assembleInputKindSet(new ArrayList<String>());
this.inputKinds.clear();
this.inputKinds.addAll(kinds);
}
/**
* Refreshes this input collection.
*
* @return The refreshed {@code InputCollection}.
*/
@Override public InputCollection refresh() {
// Populate this.inputKinds
refreshInputKinds();
items.clear();
// Iterate over all input kinds and collect all instances.
for (InputKind kind : this.inputKinds) {
if (service.versionIsAtLeast("6.0.0")) {
// In Splunk 6 and later, the registry endpoint has been deprecated in favor of the new
// WinRegMon modular input, but both now point to the same place. To avoid duplicates, we have
// to read only one of them.
if (kind.getKind().equals("registry")) {
continue;
}
}
String relpath = kind.getRelativePath();
String inputs = String.format("%s/%s?count=-1", path, relpath);
ResponseMessage response;
try {
response = service.get(inputs);
}
catch (HttpException e) {
// On some platforms certain input endpoints don't exist, for
// example the Windows inputs endpoints don't exist on non-
// Windows platforms.
if (e.getStatus() == 404) continue;
throw e;
}
AtomFeed feed;
try {
feed = AtomFeed.parseStream(response.getContent());
} catch (Exception e) {
throw new RuntimeException(e);
}
load(feed);
}
return this;
}
/**
* {@inheritDoc}
*/
@Override public Input remove(String key) {
Input input = retrieveInput(key);
if (input != null) {
input.remove();
}
return input;
}
/**
* {@inheritDoc}
*/
@Override public Input remove(
String key, Args namespace) {
Util.ensureNamespaceIsExact(namespace);
Input input = retrieveInput(key, namespace);
if (input != null) {
input.remove();
}
return input;
}
private Input retrieveInput(String key) {
validate();
// Because scripted input names are not 1:1 with the original name
// (they are the absolute path on the Splunk instance followed by
// the original name), we will iterate over the entities in the list,
// and if we find one that matches, return it.
Set<Entry<String, LinkedList<Input>>> set = items.entrySet();
for (Entry<String, LinkedList<Input>> entry: set) {
String entryKey = entry.getKey();
LinkedList<Input> entryValue = entry.getValue();
InputKind kind = entryValue.get(0).getKind();
if (InputCollection.matchesInputName(kind, key, entryKey)) {
if (entryValue.size() > 1) {
throw new SplunkException(SplunkException.AMBIGUOUS,
"Multiple inputs matched " + key + "; specify a namespace to disambiguate.");
} else {
return entryValue.get(0);
}
}
}
return null;
}
private Input retrieveInput(String key, Args namespace) {
Util.ensureNamespaceIsExact(namespace);
validate();
// Because scripted input names are not 1:1 with the original name
// (they are the absolute path on the Splunk instance followed by
// the original name), we will iterate over the entities in the list,
// and if we find one that matches, return it.
String pathMatcher = service.fullpath("", namespace);
Set<Entry<String, LinkedList<Input>>> set = items.entrySet();
for (Entry<String, LinkedList<Input>> entry: set) {
String entryKey = entry.getKey();
LinkedList<Input> entryValue = entry.getValue();
InputKind kind = entryValue.get(0).getKind();
if (InputCollection.matchesInputName(kind, key, entryKey)) {
for (Input entity: entryValue) {
if (entity.path.startsWith(pathMatcher)) {
return entity;
}
}
}
}
return null;
}
}