diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d008e42b..e7eae23c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,11 +12,12 @@ jobs: name: Java SDK Release runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up JDK 1.8 - uses: actions/setup-java@v1 + uses: actions/setup-java@v4 with: - java-version: 1.8 + java-version: 17 + distribution: oracle server-username: MAVEN_USERNAME server-password: MAVEN_PASSWORD server-id: splunk-artifactory @@ -36,7 +37,7 @@ jobs: MAVEN_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD }} - name: Upload Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: java_sdk_docs path: splunk/target/apidocs diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1c1ae02a..125e5dab 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -11,7 +11,7 @@ jobs: os: - ubuntu-latest java-version: - - 1.8 + - 17 splunk-version: - "8.2" - "latest" @@ -35,14 +35,15 @@ jobs: - 10668:10668/udp steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up JDK - uses: actions/setup-java@v1 + uses: actions/setup-java@v4 with: - java-version: 1.8 + distribution: oracle + java-version: 17 - name: Cache local Maven repository - uses: actions/cache@v2 + uses: actions/cache@v4 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} diff --git a/pom.xml b/pom.xml index 37ef9e19..2021e472 100644 --- a/pom.xml +++ b/pom.xml @@ -9,8 +9,8 @@ 1.9.5 true UTF-8 - 8 - 8 + 17 + 17 com.splunk diff --git a/splunk/src/main/java/com/splunk/Args.java b/splunk/src/main/java/com/splunk/Args.java index 4e93f36a..f5853406 100644 --- a/splunk/src/main/java/com/splunk/Args.java +++ b/splunk/src/main/java/com/splunk/Args.java @@ -154,8 +154,8 @@ public String encode() { if (builder.length() > 0) builder.append('&'); String key = entry.getKey(); Object value = entry.getValue(); - if (value instanceof String[]) { - encodeValues(builder, key, (String[])value); + if (value instanceof String[] valueInst) { + encodeValues(builder, key, valueInst); } else { builder.append(encode(key)); diff --git a/splunk/src/main/java/com/splunk/AtomFeed.java b/splunk/src/main/java/com/splunk/AtomFeed.java index 27915701..3de9b75c 100644 --- a/splunk/src/main/java/com/splunk/AtomFeed.java +++ b/splunk/src/main/java/com/splunk/AtomFeed.java @@ -20,14 +20,13 @@ import java.util.*; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; -import javax.xml.stream.XMLStreamConstants; /** * The {@code AtomFeed} class represents an Atom feed. */ public class AtomFeed extends AtomObject { /** The list of Atom entries contained in this {@code AtomFeed} object. */ - public ArrayList entries = new ArrayList(); + public ArrayList entries = new ArrayList<>(); /** The value of the Atom feed's {@code } element. */ public String itemsPerPage = null; diff --git a/splunk/src/main/java/com/splunk/AtomObject.java b/splunk/src/main/java/com/splunk/AtomObject.java index 67567134..6e130096 100644 --- a/splunk/src/main/java/com/splunk/AtomObject.java +++ b/splunk/src/main/java/com/splunk/AtomObject.java @@ -34,7 +34,7 @@ public class AtomObject { public String id; /** The value of the {@code } elements in this {@code AtomObject}. */ - public Map links = new HashMap(); + public Map links = new HashMap<>(); /** The value of the Atom {@code } element. */ public String title; diff --git a/splunk/src/main/java/com/splunk/CollectionArgs.java b/splunk/src/main/java/com/splunk/CollectionArgs.java index 25fd35aa..741ad4d3 100644 --- a/splunk/src/main/java/com/splunk/CollectionArgs.java +++ b/splunk/src/main/java/com/splunk/CollectionArgs.java @@ -1,177 +1,177 @@ -/* - * 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; - -/** - * The {@code CollectionArgs} class contains arguments for retrieving and - * listing entities from a collection, such as the number of entities to return - * and how to sort them. - */ -public class CollectionArgs extends Args { - - /** - * Indicates whether to sort entries in ascending or descending order. - */ - public static enum SortDirection { - /** Sort entries in ascending order. */ - ASC("asc"), - /** Sort entries in descending order. */ - DESC("desc"); - - private String value; - - private SortDirection(String value) { - this.value = value; - } - - /** - * @return The REST API value for this enumerated constant. - */ - public String toString() { - return this.value; - } - } - - /** - * Indicates the sorting mode for entries. - */ - public static enum SortMode { - /** - * If all values of the field are numbers, collate numerically. - * Otherwise, collate alphabetically. - */ - AUTO("auto"), - /** Collate alphabetically. */ - ALPHA("alpha"), - /** Collate alphabetically, case-sensitive. */ - ALPHA_CASE("alpha_case"), - /** Collate numerically. */ - NUM("num"); - - private String value; - - private SortMode(String value) { - this.value = value; - } - - /** - * @return The REST API value for this enumerated constant. - */ - public String toString() { - return this.value; - } - } - - /** - * Class constructor. - */ - public CollectionArgs() { super(); } - - /* BEGIN AUTOGENERATED CODE */ - - /** - * Sets the app context in which to list the collection. - * - * @param app - * The app context in which to list the collection. A {@code null} value indicates no app context, and a value of {@code "-"} indicates an app wildcard. - */ - public void setApp(String app) { - this.put("app", app); - } - - /** - * Sets the owner context in which to list the collection. - * - * @param owner - * The owner context in which to list the collection. A value of {@code "-"} indicates a wildcard, and a {@code null} value indicates no owner context. - */ - public void setOwner(String owner) { - this.put("owner", owner); - } - - /** - * Sets the sharing context in which to list the collection. - * - * @param sharing - * The sharing context in which to list the collection. Valid values are "user", "app", "global", and "system". - */ - public void setSharing(String sharing) { - this.put("sharing", sharing); - } - - /** - * Sets the maximum number of entries to return. - * - * @param count - * The maximum number of entries to return. To return all entries, specify 0. - */ - public void setCount(int count) { - this.put("count", count); - } - - /** - * Sets the index of the first entry to return. - * - * @param offset - * The index of the first entry to return. - */ - public void setOffset(int offset) { - this.put("offset", offset); - } - - /** - * Sets a search query to filter the response. The response matches field values against the search query. For example, "foo" matches any object that has "foo" as a substring in a field, and "field_name=field_value" restricts the match to a single field. - * - * @param search - * A search query to filter the response. - */ - public void setSearch(String search) { - this.put("search", search); - } - - /** - * Sets the direction to sort entries. - * - * @param sortDirection - * The sorting order--ascending or descending. - */ - public void setSortDirection(SortDirection sortDirection) { - this.put("sort_dir", sortDirection); - } - - /** - * Sets the field to use for sorting. - * - * @param sortKey - * The field to sort by. - */ - public void setSortKey(String sortKey) { - this.put("sort_key", sortKey); - } - - /** - * Sets the mode to use for sorting. - * - * @param sortMode - * The collating sequence for sorting entries. - */ - public void setSortMode(SortMode sortMode) { - this.put("sort_mode", sortMode); - } - - /* END AUTOGENERATED CODE */ -} +/* + * 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; + +/** + * The {@code CollectionArgs} class contains arguments for retrieving and + * listing entities from a collection, such as the number of entities to return + * and how to sort them. + */ +public class CollectionArgs extends Args { + + /** + * Indicates whether to sort entries in ascending or descending order. + */ + public enum SortDirection { + /** Sort entries in ascending order. */ + ASC("asc"), + /** Sort entries in descending order. */ + DESC("desc"); + + private String value; + + private SortDirection(String value) { + this.value = value; + } + + /** + * @return The REST API value for this enumerated constant. + */ + public String toString() { + return this.value; + } + } + + /** + * Indicates the sorting mode for entries. + */ + public enum SortMode { + /** + * If all values of the field are numbers, collate numerically. + * Otherwise, collate alphabetically. + */ + AUTO("auto"), + /** Collate alphabetically. */ + ALPHA("alpha"), + /** Collate alphabetically, case-sensitive. */ + ALPHA_CASE("alpha_case"), + /** Collate numerically. */ + NUM("num"); + + private String value; + + private SortMode(String value) { + this.value = value; + } + + /** + * @return The REST API value for this enumerated constant. + */ + public String toString() { + return this.value; + } + } + + /** + * Class constructor. + */ + public CollectionArgs() { super(); } + + /* BEGIN AUTOGENERATED CODE */ + + /** + * Sets the app context in which to list the collection. + * + * @param app + * The app context in which to list the collection. A {@code null} value indicates no app context, and a value of {@code "-"} indicates an app wildcard. + */ + public void setApp(String app) { + this.put("app", app); + } + + /** + * Sets the owner context in which to list the collection. + * + * @param owner + * The owner context in which to list the collection. A value of {@code "-"} indicates a wildcard, and a {@code null} value indicates no owner context. + */ + public void setOwner(String owner) { + this.put("owner", owner); + } + + /** + * Sets the sharing context in which to list the collection. + * + * @param sharing + * The sharing context in which to list the collection. Valid values are "user", "app", "global", and "system". + */ + public void setSharing(String sharing) { + this.put("sharing", sharing); + } + + /** + * Sets the maximum number of entries to return. + * + * @param count + * The maximum number of entries to return. To return all entries, specify 0. + */ + public void setCount(int count) { + this.put("count", count); + } + + /** + * Sets the index of the first entry to return. + * + * @param offset + * The index of the first entry to return. + */ + public void setOffset(int offset) { + this.put("offset", offset); + } + + /** + * Sets a search query to filter the response. The response matches field values against the search query. For example, "foo" matches any object that has "foo" as a substring in a field, and "field_name=field_value" restricts the match to a single field. + * + * @param search + * A search query to filter the response. + */ + public void setSearch(String search) { + this.put("search", search); + } + + /** + * Sets the direction to sort entries. + * + * @param sortDirection + * The sorting order--ascending or descending. + */ + public void setSortDirection(SortDirection sortDirection) { + this.put("sort_dir", sortDirection); + } + + /** + * Sets the field to use for sorting. + * + * @param sortKey + * The field to sort by. + */ + public void setSortKey(String sortKey) { + this.put("sort_key", sortKey); + } + + /** + * Sets the mode to use for sorting. + * + * @param sortMode + * The collating sequence for sorting entries. + */ + public void setSortMode(SortMode sortMode) { + this.put("sort_mode", sortMode); + } + + /* END AUTOGENERATED CODE */ +} diff --git a/splunk/src/main/java/com/splunk/Command.java b/splunk/src/main/java/com/splunk/Command.java index 4dbd39b6..aaee5d9c 100644 --- a/splunk/src/main/java/com/splunk/Command.java +++ b/splunk/src/main/java/com/splunk/Command.java @@ -18,7 +18,6 @@ import java.io.BufferedReader; import java.io.File; -import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; @@ -45,12 +44,12 @@ public class Command { public String[] args = new String[0]; // The parsed command line options (flags) - public HashMap<String, Object> opts = new HashMap<String, Object>(); + public HashMap<String, Object> opts = new HashMap<>(); // Whether or not this is a help request public Boolean help = false; - public static final HashMap<String, Object> defaultValues = new HashMap<String, Object>(); + public static final HashMap<String, Object> defaultValues = new HashMap<>(); { defaultValues.put("scheme", "https"); defaultValues.put("host", "localhost"); @@ -117,29 +116,21 @@ public Command addRule(String name, Class argType, String description) { // Load a file of options and arguments public Command load(String path) { - ArrayList<String> argList = new ArrayList<String>(); + ArrayList<String> argList = new ArrayList<>(); - try { - FileReader fileReader = new FileReader(path); - try { - BufferedReader reader = new BufferedReader(fileReader); - while (true) { - String line; - line = reader.readLine(); - if (line == null) - break; - if (line.startsWith("#")) - continue; - line = line.trim(); - if (line.length() == 0) - continue; - if (!line.startsWith("-")) - line = "--" + line; - argList.add(line); - } - } - finally { - fileReader.close(); + try (FileReader fileReader = new FileReader(path); + BufferedReader reader = new BufferedReader(fileReader);) { + while (true) { + String line; + line = reader.readLine(); + if (line == null) + break; + if (line.startsWith("#") || line.isBlank()) + continue; + line = line.trim(); + if (!line.startsWith("-")) + line = "--" + line; + argList.add(line); } } catch (IOException e) { @@ -198,7 +189,9 @@ else if (type == Integer.class) { java.lang.reflect.Field field = this.getClass().getField(name); field.set(this, value); } - catch (NoSuchFieldException e) { continue; } + catch (NoSuchFieldException e) { + continue; + } catch (IllegalAccessException e) { throw new RuntimeException(e.getMessage(), e); } diff --git a/splunk/src/main/java/com/splunk/DataModel.java b/splunk/src/main/java/com/splunk/DataModel.java index ce42f6f9..82a4c13b 100644 --- a/splunk/src/main/java/com/splunk/DataModel.java +++ b/splunk/src/main/java/com/splunk/DataModel.java @@ -28,8 +28,8 @@ * data model objects, which specify structured views on Splunk data. */ public class DataModel extends Entity { - private final static JsonParser jsonParser = new JsonParser(); - private final static Gson gson = new Gson(); + private static final JsonParser jsonParser = new JsonParser(); + private static final Gson gson = new Gson(); private static final String ACCELERATION_LABEL = "acceleration"; private static final String MODEL_NAME_LABEL = "modelName"; @@ -140,7 +140,7 @@ Entity load(AtomObject value) { * @param input a String containing JSON. */ private void parseDescription(String input) { - objects = new HashMap<String, DataModelObject>(); + objects = new HashMap<>(); JsonElement rootElement = jsonParser.parse(input); @@ -284,7 +284,7 @@ public void setManualRebuilds(boolean enabled) { public void update() { // We have to do some munging on the acceleration fields to pass them as JSON // to the server. - Map<String, Object> accelerationMap = new HashMap<String, Object>(); + Map<String, Object> accelerationMap = new HashMap<>(); for (String key : new String[] {"enabled", "earliest_time", "cron_schedule", "manual_rebuilds"}) { if (toUpdate.containsKey(key)) { accelerationMap.put(key, toUpdate.get(key)); diff --git a/splunk/src/main/java/com/splunk/DataModelCalculation.java b/splunk/src/main/java/com/splunk/DataModelCalculation.java index 499c0584..ff866d39 100644 --- a/splunk/src/main/java/com/splunk/DataModelCalculation.java +++ b/splunk/src/main/java/com/splunk/DataModelCalculation.java @@ -98,7 +98,7 @@ static DataModelCalculation parse(JsonElement json) { String type = null; String calculationId = null; List<LookupDataModelCalculation.LookupFieldMapping> lookupInputs = - new ArrayList<LookupDataModelCalculation.LookupFieldMapping>(); + new ArrayList<>(); String comment = null; String expression = null; String lookupName = null; @@ -106,7 +106,7 @@ static DataModelCalculation parse(JsonElement json) { String inputField = null; // where there is only one entry, and it's not in an array. String[] owner = new String[0]; // Should always be set below boolean editable = false; - Map<String, DataModelField> outputFields = new HashMap<String, DataModelField>(); + Map<String, DataModelField> outputFields = new HashMap<>(); String key; for (Entry<String, JsonElement> entry : json.getAsJsonObject().entrySet()) { @@ -122,10 +122,9 @@ static DataModelCalculation parse(JsonElement json) { } } else if (key.equals("lookupInputs")) { for (JsonElement lookupInputJsonElement : entry.getValue().getAsJsonArray()) { - if (!(lookupInputJsonElement instanceof JsonObject)) { + if (!(lookupInputJsonElement instanceof JsonObject lookupInputJson)) { throw new RuntimeException("Expected a JSON object for lookupInput entry."); } - JsonObject lookupInputJson = (JsonObject)lookupInputJsonElement; LookupDataModelCalculation.LookupFieldMapping mapping = new LookupDataModelCalculation.LookupFieldMapping(); mapping.inputField = lookupInputJson.get("inputField").getAsString(); mapping.lookupField = lookupInputJson.get("lookupField").getAsString(); diff --git a/splunk/src/main/java/com/splunk/DataModelField.java b/splunk/src/main/java/com/splunk/DataModelField.java index d83dca1c..3487f80e 100644 --- a/splunk/src/main/java/com/splunk/DataModelField.java +++ b/splunk/src/main/java/com/splunk/DataModelField.java @@ -44,7 +44,7 @@ private DataModelField() {} /** * @return The name of this field. */ - public String getName() { return this.name; }; + public String getName() { return this.name; } /** * Return the name of the data model object on which this field is defined. That need not diff --git a/splunk/src/main/java/com/splunk/DataModelObject.java b/splunk/src/main/java/com/splunk/DataModelObject.java index 75c84d88..d8aade24 100644 --- a/splunk/src/main/java/com/splunk/DataModelObject.java +++ b/splunk/src/main/java/com/splunk/DataModelObject.java @@ -185,7 +185,7 @@ public Collection<DataModelField> getAutoExtractedFields() { * @return a collection of DataModelField objects. */ public Collection<DataModelField> getFields() { - Collection<DataModelField> fields = new ArrayList<DataModelField>(); + Collection<DataModelField> fields = new ArrayList<>(); fields.addAll(this.autoextractedFields.values()); for (DataModelCalculation c : this.calculations.values()) { fields.addAll(c.getGeneratedFields()); @@ -297,18 +297,18 @@ static DataModelObject parse(DataModel dataModel, JsonElement object) { String comment = null; String[] lineage = new String[0]; String parentName = null; - Map<String, DataModelField> fields = new HashMap<String, DataModelField>(); - Collection<String> children = new ArrayList<String>(); - Collection<DataModelConstraint> constraints = new ArrayList<DataModelConstraint>(); - Map<String, DataModelCalculation> calculations = new HashMap<String, DataModelCalculation>(); + Map<String, DataModelField> fields = new HashMap<>(); + Collection<String> children = new ArrayList<>(); + Collection<DataModelConstraint> constraints = new ArrayList<>(); + Map<String, DataModelCalculation> calculations = new HashMap<>(); // Fields specific to objects inheriting directly from BaseSearch. String baseSearch = null; // Fields specific to objects inheriting directly from BaseTransaction String transactionMaxPause = null; String transactionMaxTimeSpan = null; - Collection<String> groupByFields = new ArrayList<String>(); - Collection<String> objectsToGroup = new ArrayList<String>(); + Collection<String> groupByFields = new ArrayList<>(); + Collection<String> objectsToGroup = new ArrayList<>(); for (Entry<String, JsonElement> entry : object.getAsJsonObject().entrySet()) { if (entry.getKey().equals("objectName")) { diff --git a/splunk/src/main/java/com/splunk/Entity.java b/splunk/src/main/java/com/splunk/Entity.java index a4856e2a..c2275736 100644 --- a/splunk/src/main/java/com/splunk/Entity.java +++ b/splunk/src/main/java/com/splunk/Entity.java @@ -23,7 +23,7 @@ */ public class Entity extends Resource implements Map<String, Object> { protected Record content; - protected HashMap<String, Object> toUpdate = new LinkedHashMap<String, Object>(); + protected HashMap<String, Object> toUpdate = new LinkedHashMap<>(); /** * Class constructor. @@ -429,7 +429,7 @@ public void update(Map<String, Object> args) { if (!toUpdate.isEmpty() || !args.isEmpty()) { // Merge cached setters and live args together before updating. Map<String, Object> mergedArgs = - new LinkedHashMap<String, Object>(); + new LinkedHashMap<>(); mergedArgs.putAll(toUpdate); mergedArgs.putAll(args); diff --git a/splunk/src/main/java/com/splunk/EntityCollection.java b/splunk/src/main/java/com/splunk/EntityCollection.java index a0378d60..588bd413 100644 --- a/splunk/src/main/java/com/splunk/EntityCollection.java +++ b/splunk/src/main/java/com/splunk/EntityCollection.java @@ -138,7 +138,7 @@ public T remove(String key, Args namespace) { if (!containsKey(key)) return null; LinkedList<T> entities = items.get(key); String pathMatcher = service.fullpath("", namespace); - if (entities == null || entities.size() == 0) return null; + if (entities == null || entities.isEmpty()) return null; for (T entity: entities) { if (entity.path.startsWith(pathMatcher)) { entity.remove(); diff --git a/splunk/src/main/java/com/splunk/Event.java b/splunk/src/main/java/com/splunk/Event.java index a37b91bc..42dcb377 100644 --- a/splunk/src/main/java/com/splunk/Event.java +++ b/splunk/src/main/java/com/splunk/Event.java @@ -34,7 +34,7 @@ * {@link ResultsReaderXml} class, the delimiter is a comma (,). */ public class Event extends HashMap<String, String> { - private Map<String, String[]> arrayValues = new HashMap<String, String[]>(); + private Map<String, String[]> arrayValues = new HashMap<>(); private String segmentedRaw; // Prevent non-SDK instantiation. diff --git a/splunk/src/main/java/com/splunk/ExportResultsStream.java b/splunk/src/main/java/com/splunk/ExportResultsStream.java index c56067dd..175a3781 100644 --- a/splunk/src/main/java/com/splunk/ExportResultsStream.java +++ b/splunk/src/main/java/com/splunk/ExportResultsStream.java @@ -1,31 +1,31 @@ -/* - * 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.io.FilterInputStream; -import java.io.InputStream; - -/** - * The {@code ExportResultsStream} class represents a stream constructed by the - * {@link Service#export} method. - * - */ -class ExportResultsStream extends FilterInputStream { - public ExportResultsStream(InputStream stream) { - super(stream); - } -} +/* + * 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.io.FilterInputStream; +import java.io.InputStream; + +/** + * The {@code ExportResultsStream} class represents a stream constructed by the + * {@link Service#export} method. + * + */ +class ExportResultsStream extends FilterInputStream { + public ExportResultsStream(InputStream stream) { + super(stream); + } +} diff --git a/splunk/src/main/java/com/splunk/FieldType.java b/splunk/src/main/java/com/splunk/FieldType.java index 8f78a469..ff0253b0 100644 --- a/splunk/src/main/java/com/splunk/FieldType.java +++ b/splunk/src/main/java/com/splunk/FieldType.java @@ -50,7 +50,7 @@ public String toString() { } }; - private final static Map<String, FieldType> typeLookup = new HashMap<String, FieldType>() {{ + private static final Map<String, FieldType> typeLookup = new HashMap<>() {{ put("string", STRING); put("number", NUMBER); put("boolean", BOOLEAN); diff --git a/splunk/src/main/java/com/splunk/FiredAlertGroup.java b/splunk/src/main/java/com/splunk/FiredAlertGroup.java index 7d6b0994..ec643cfa 100644 --- a/splunk/src/main/java/com/splunk/FiredAlertGroup.java +++ b/splunk/src/main/java/com/splunk/FiredAlertGroup.java @@ -37,7 +37,7 @@ public class FiredAlertGroup extends Entity { * @return The fired alerts in the group. */ public EntityCollection<FiredAlert> getAlerts() { - return new EntityCollection<FiredAlert>( + return new EntityCollection<>( service, this.path, FiredAlert.class); } } diff --git a/splunk/src/main/java/com/splunk/HttpService.java b/splunk/src/main/java/com/splunk/HttpService.java index 54724cea..8f87e243 100644 --- a/splunk/src/main/java/com/splunk/HttpService.java +++ b/splunk/src/main/java/com/splunk/HttpService.java @@ -1,619 +1,619 @@ -/* - * 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 javax.net.ssl.*; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.net.*; -import java.security.cert.X509Certificate; -import java.util.*; -import java.util.Map.Entry; - -/** - * The {@code HttpService} class represents a generic HTTP service at a given - * address ({@code host:port}), accessed using a given protocol scheme - * ({@code http} or {@code https}). - */ -public class HttpService { - // For debugging purposes - private static final boolean VERBOSE_REQUESTS = false; - protected static SSLSecurityProtocol sslSecurityProtocol = null; - - /** - * Boolean flag for validating certificates at either of the sides (client/server). - * If true, then it will check and validate relevant certificates otherwise, in case of false, it will accept all certificates. - * For PROD environment, TRUE is strongly recommended, whereas working in localhost OR development environment, FALSE is used. - * Default Value: TRUE - */ - protected static boolean validateCertificates = true; - - private static SSLSocketFactory sslSocketFactory = createSSLFactory(); - private static String HTTPS_SCHEME = "https"; - private static String HTTP_SCHEME = "http"; - private static List<String> VALID_HOSTS = new ArrayList<String>(Arrays.asList("localhost", "127.0.0.1", "::1")); - - private static final HostnameVerifier HOSTNAME_VERIFIER = new HostnameVerifier() { - public boolean verify(String s, SSLSession sslSession) { - if(VALID_HOSTS.contains(s)){ - return true; - } else { - HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier(); - return hv.verify(s, sslSession); - } - } - }; - - /** - * A variable to hold an optional custom HTTPS handler - */ - protected URLStreamHandler httpsHandler = null; - - /** - * The scheme used to access the service. - */ - protected String scheme = "https"; - - /** - * The host name of the service. - */ - protected String host = "localhost"; - - /** - * The port number of the service. - */ - protected int port = 8089; - - protected Integer connectTimeout = null; - protected Integer readTimeout = null; - - private String prefix = null; - - static Map<String, String> defaultHeader = new HashMap<String, String>() {{ - put("User-Agent", "splunk-sdk-java/1.9.5"); - put("Accept", "*/*"); - }}; - - protected Map<String, String> customHeaders = new HashMap<>(); - - protected SimpleCookieStore cookieStore = new SimpleCookieStore(); - - /** - * Constructs a new {@code HttpService} instance. - */ - public HttpService() { - } - - /** - * Constructs a new {@code HttpService} instance at the given host. - * - * @param host The host name of the service. - */ - public HttpService(String host) { - this.host = host; - } - - /** - * Constructs a new {@code HttpService} instance at the given host and port. - * - * @param host The host name of the service. - * @param port The port number of the service. - */ - public HttpService(String host, int port) { - this.host = host; - this.port = port; - } - - /** - * Constructs a new {@code HttpService} instance using the given host, - * port, and scheme. - * - * @param host The host name of the service. - * @param port The port number of the service. - * @param scheme Scheme for accessing the service ({@code http} or - * {@code https}). - */ - public HttpService(String host, int port, String scheme) { - this.host = host; - this.port = port; - this.scheme = scheme; - } - - /** - * Constructs a new {@code HttpService} instance using the given host, - * port, and scheme, and instructing it to use the specified HTTPS handler. - * - * @param host The host name of the service. - * @param port The port number of the service. - * @param scheme Scheme for accessing the service ({@code http} or - * {@code https}). - * @param httpsHandler A custom URL Stream handler. - */ - public HttpService(String host, int port, String scheme, - URLStreamHandler httpsHandler) { - this.host = host; - this.port = port; - this.scheme = scheme; - this.httpsHandler = httpsHandler; - } - - // Returns the count of arguments in the given {@code args} map. - private static int count(Map<String, Object> args) { - if (args == null) return 0; - return args.size(); - } - - /** - * Issues an HTTP GET request against the service using a given path. - * - * @param path The request path. - * @return The HTTP response. - */ - public ResponseMessage get(String path) { - return send(path, new RequestMessage("GET")); - } - - /** - * Issues an HTTP GET request against the service using a given path and - * query arguments. - * - * @param path The request path. - * @param args The query arguments. - * @return The HTTP response. - */ - public ResponseMessage get(String path, Map<String, Object> args) { - if (count(args) > 0) - path = path + "?" + Args.encode(args); - RequestMessage request = new RequestMessage("GET"); - return send(path, request); - } - - /** - * Returns the host name of this service. - * - * @return The host name. - */ - public String getHost() { - return this.host; - } - - /** - * Returns the port number of this service. - * - * @return The port number. - */ - public int getPort() { - return this.port; - } - - /** - * Sets Custom Headers of this service - * - * @param headers The custom headers. - */ - public void setCustomHeaders(Map<String, String> headers) { - if (Objects.nonNull(headers)) { - customHeaders = headers; - } - } - - /** - * Returns the SSL security protocol of this service. - * - * @return The SSL security protocol. - */ - public static SSLSecurityProtocol getSslSecurityProtocol() { - return sslSecurityProtocol; - } - - /** - * Sets the SSL security protocol of this service. - * @param securityProtocol The SSLSecurityProtocal instance - */ - public static void setSslSecurityProtocol(SSLSecurityProtocol securityProtocol) { - // Only update the SSL_SOCKET_FACTORY if changing protocols - if (sslSecurityProtocol != securityProtocol) { - sslSecurityProtocol = securityProtocol; - sslSocketFactory = createSSLFactory(); - } - } - - /** - * Adds list of Cluster Master Hosts to the list of Valid Hosts for Hostname verification. - * @param searchHeadService Splunk SearchHead Service instance - */ - public static void addClusterMasterURIsToHosts(Service searchHeadService){ - VALID_HOSTS.addAll(searchHeadService.getClusterMasters()); - } - - /** - * Returns the URL prefix of this service, consisting of - * {@code scheme://host[:port]}. - * - * @return The URL prefix. - */ - public String getPrefix() { - if (this.prefix == null) - this.prefix = String.format("%s://%s:%s", - this.scheme, this.host, this.port); - return this.prefix; - } - - /** - * Returns the scheme used by this service. - * - * @return The scheme. - */ - public String getScheme() { - return this.scheme; - } - - /** - * Constructs a fully-qualified URL for this service using a given path. - * - * @param path The path to qualify. - * @return The fully-qualified URL for the service. - */ - public URL getUrl(String path) { - try { - if (HTTPS_SCHEME.equals(getScheme()) && httpsHandler != null) { - // This branch is not currently covered by unit tests as I - // could not figure out a generic way to get the default - // HTTPS handler. - return new URL(getScheme(), getHost(), getPort(), path, - httpsHandler); - } else { - return new URL(getScheme(), getHost(), getPort(), path); - } - } catch (MalformedURLException e) { - throw new RuntimeException(e.getMessage(), e); - } - } - - /** - * Returns all the stored custom headers - * - * @return customHeaders The custom headers - */ - public Map<String, String> getCustomHeaders() { - return customHeaders; - } - - /** - * Returns all the stored cookies - * - * @return All cookies as in a string in the format key=value; key=value; etc=etc - */ - public String stringifyCookies() { - return cookieStore.getCookies(); - } - - /** - * Adds the passed cookie header to the cookieStore - * - * @param setCookieHeader The result from a getRequestHeader("Set-Cookie") call - */ - public void addCookie(String setCookieHeader) { - cookieStore.add(setCookieHeader); - } - - /** - * Removes all cookies from the cookieStore - */ - public void removeAllCookies() { - cookieStore.removeAll(); - } - - /** - * Returns true if the cookieStore has any Splunk Authorization cookies, false otherwise - * - * @return True if there are cookies, false otherwise - */ - public Boolean hasSplunkAuthCookies() { - return cookieStore.hasSplunkAuthCookie(); - } - - /** - * Returns the connect timeout used by this service. - * - * @return The timeout in milliseconds. - */ - public Integer getConnectTimeout() { - return connectTimeout; - } - - /** - * Sets a specified timeout value, in milliseconds, to be used when opening a communications link. - * - * @param connectTimeout timeout in milliseconds, a timeout of zero is interpreted as an infinite timeout. - */ - public void setConnectTimeout(Integer connectTimeout) { - this.connectTimeout = connectTimeout; - } - - /** - * Returns the read timeout used by this service. - * - * @return The timeout in milliseconds. - */ - public Integer getReadTimeout() { - return readTimeout; - } - - /** - * Sets a specified timeout value, in milliseconds, to be used when reading from a communications link. - * - * @param readTimeout timeout in milliseconds, a timeout of zero is interpreted as an infinite timeout. - */ - public void setReadTimeout(Integer readTimeout) { - this.readTimeout = readTimeout; - } - - /** - * Issues a POST request against the service using a given path. - * - * @param path The request path. - * @return The HTTP response. - */ - public ResponseMessage post(String path) { - return post(path, null); - } - - /** - * Issues a POST request against the service using a given path and - * form arguments. - * - * @param path The request path. - * @param args The form arguments. - * @return The HTTP response. - */ - public ResponseMessage post(String path, Map<String, Object> args) { - RequestMessage request = new RequestMessage("POST"); - request.getHeader().put( - "Content-Type", "application/x-www-form-urlencoded"); - if (count(args) > 0) - request.setContent(Args.encode(args)); - return send(path, request); - } - - /** - * Issues a DELETE request against the service using a given path. - * - * @param path The request path. - * @return The HTTP response. - */ - public ResponseMessage delete(String path) { - RequestMessage request = new RequestMessage("DELETE"); - return send(path, request); - } - - /** - * Issues a DELETE request against the service using a given path - * and query arguments. - * - * @param path The request path. - * @param args The query arguments. - * @return The HTTP response. - */ - public ResponseMessage delete(String path, Map<String, Object> args) { - if (count(args) > 0) - path = path + "?" + Args.encode(args); - RequestMessage request = new RequestMessage("DELETE"); - return send(path, request); - } - - /** - * Opens a socket to this service. - * - * @return The socket. - * @throws IOException - */ - Socket open() throws IOException { - if (this.scheme.equals("https")) { - return sslSocketFactory.createSocket(this.host, this.port); - } - return new Socket(this.host, this.port); - } - - /** - * Issue an HTTP request against the service using a given path and - * request message. - * - * @param path The request path. - * @param request The request message. - * @return The HTTP response. - */ - public ResponseMessage send(String path, RequestMessage request) { - // Construct a full URL to the resource - URL url = getUrl(path); - // Create and initialize the connection object - HttpURLConnection cn; - try { - cn = (HttpURLConnection) url.openConnection(); - } catch (IOException e) { - throw new RuntimeException(e.getMessage(), e); - } - if (cn instanceof HttpsURLConnection) { - ((HttpsURLConnection) cn).setSSLSocketFactory(sslSocketFactory); - ((HttpsURLConnection) cn).setHostnameVerifier(HOSTNAME_VERIFIER); - } - cn.setUseCaches(false); - cn.setAllowUserInteraction(false); - cn.setConnectTimeout(connectTimeout == null ? 0 : connectTimeout); - cn.setReadTimeout(readTimeout == null ? 0 : readTimeout); - - // Set the request method - String method = request.getMethod(); - try { - cn.setRequestMethod(method); - } catch (ProtocolException e) { - throw new RuntimeException(e.getMessage(), e); - } - - // Add headers from request message - Map<String, String> header = request.getHeader(); - for (Entry<String, String> entry : header.entrySet()) - cn.setRequestProperty(entry.getKey(), entry.getValue()); - // Add default headers that were absent from the request message - for (Entry<String, String> entry : defaultHeader.entrySet()) { - String key = entry.getKey(); - if (header.containsKey(key)) continue; - cn.setRequestProperty(key, entry.getValue()); - } - // Add Custom Headers - for (Entry<String, String> entry: customHeaders.entrySet()) { - String key = entry.getKey(); - if (!header.containsKey(key)) { - cn.setRequestProperty(key, entry.getValue()); - } - } - - // Add cookies to header - cn.setRequestProperty("Cookie", cookieStore.getCookies()); - - // Write out request content, if any - try { - Object content = request.getContent(); - if (content != null) { - cn.setDoOutput(true); - OutputStream stream = cn.getOutputStream(); - OutputStreamWriter writer = new OutputStreamWriter(stream, "UTF-8"); - writer.write((String) content); - writer.close(); - } - } catch (IOException e) { - throw new RuntimeException(e.getMessage(), e); - } - - if (VERBOSE_REQUESTS) { - System.out.format("%s %s => ", method, url.toString()); - } - - // Execute the request - try { - cn.connect(); - } catch (IOException e) { - throw new RuntimeException(e.getMessage(), e); - } - - int status; - try { - status = cn.getResponseCode(); - } catch (IOException e) { - throw new RuntimeException(e.getMessage(), e); - } - - InputStream input = null; - try { - input = status >= 400 - ? cn.getErrorStream() - : cn.getInputStream(); - } catch (IOException e) { - assert (false); - } - - // If user session has expired check for 'autologin' flag to either re-login or throw HTTPException - if(this instanceof Service && status == 401){ - return new ResponseMessage(401, input); - } - - // Add cookies to cookie Store - Map<String, List<String>> headers = cn.getHeaderFields(); - if (headers.containsKey("Set-Cookie")) { - for (String cookieHeader : headers.get("Set-Cookie")) { - if (cookieHeader != null && cookieHeader.length() > 0) - cookieStore.add(cookieHeader); - } - } - - ResponseMessage response = new ResponseMessage(status, input); - - if (VERBOSE_REQUESTS) { - System.out.format("%d\n", status); - if (method.equals("POST")) { - System.out.println(" " + request.getContent()); - } - } - - if (status >= 400) - throw HttpException.create(response); - - return response; - } - - public static void setSSLSocketFactory(SSLSocketFactory sslSocketFactory) { - if (sslSocketFactory == null) - throw new IllegalArgumentException("The sslSocketFactory cannot be null."); - HttpService.sslSocketFactory = sslSocketFactory; - } - - public static SSLSocketFactory getSSLSocketFactory() { - return HttpService.sslSocketFactory; - } - - public static void setValidateCertificates(boolean validateCertificate) { - // update the SSL_SOCKET_FACTORY if validateCertificates flag is changed - if (validateCertificates != validateCertificate) { - validateCertificates = validateCertificate; - sslSocketFactory = createSSLFactory(); - } - } - - public static SSLSocketFactory createSSLFactory() { - - try { - SSLContext context; - if (sslSecurityProtocol != null) { - String contextStr = sslSecurityProtocol.toString().contains("SSL") ? "SSL" : "TLS"; - context = SSLContext.getInstance(contextStr); - } else if (System.getProperty("java.version").compareTo("1.8") >= 0) { - context = SSLContext.getInstance("TLS"); - } else { - context = SSLContext.getDefault(); - } - - if (validateCertificates) { - context.init(null, null, null); - // For now this check is set as null. - // TODO: Implementation logic for validating client certificate. - } else { - TrustManager[] trustAll = new TrustManager[]{ - new X509TrustManager() { - public X509Certificate[] getAcceptedIssuers() { - return null; - } - - public void checkClientTrusted(X509Certificate[] certs, String authType) { - } - - public void checkServerTrusted(X509Certificate[] certs, String authType) { - } - } - }; - context.init(null, trustAll, null); - } - - return context.getSocketFactory(); - } catch (Exception e) { - throw new RuntimeException("Error setting up SSL socket factory: " + e, e); - } - } - -} - +/* + * 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 javax.net.ssl.*; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.net.*; +import java.security.cert.X509Certificate; +import java.util.*; +import java.util.Map.Entry; + +/** + * The {@code HttpService} class represents a generic HTTP service at a given + * address ({@code host:port}), accessed using a given protocol scheme + * ({@code http} or {@code https}). + */ +public class HttpService { + // For debugging purposes + private static final boolean VERBOSE_REQUESTS = false; + protected static SSLSecurityProtocol sslSecurityProtocol = null; + + /** + * Boolean flag for validating certificates at either of the sides (client/server). + * If true, then it will check and validate relevant certificates otherwise, in case of false, it will accept all certificates. + * For PROD environment, TRUE is strongly recommended, whereas working in localhost OR development environment, FALSE is used. + * Default Value: TRUE + */ + protected static boolean validateCertificates = true; + + private static SSLSocketFactory sslSocketFactory = createSSLFactory(); + private static String HTTPS_SCHEME = "https"; + private static String HTTP_SCHEME = "http"; + private static List<String> VALID_HOSTS = new ArrayList<>(Arrays.asList("localhost", "127.0.0.1", "::1")); + + private static final HostnameVerifier HOSTNAME_VERIFIER = new HostnameVerifier() { + public boolean verify(String s, SSLSession sslSession) { + if(VALID_HOSTS.contains(s)){ + return true; + } else { + HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier(); + return hv.verify(s, sslSession); + } + } + }; + + /** + * A variable to hold an optional custom HTTPS handler + */ + protected URLStreamHandler httpsHandler = null; + + /** + * The scheme used to access the service. + */ + protected String scheme = "https"; + + /** + * The host name of the service. + */ + protected String host = "localhost"; + + /** + * The port number of the service. + */ + protected int port = 8089; + + protected Integer connectTimeout = null; + protected Integer readTimeout = null; + + private String prefix = null; + + static Map<String, String> defaultHeader = new HashMap<>() {{ + put("User-Agent", "splunk-sdk-java/1.9.5"); + put("Accept", "*/*"); + }}; + + protected Map<String, String> customHeaders = new HashMap<>(); + + protected SimpleCookieStore cookieStore = new SimpleCookieStore(); + + /** + * Constructs a new {@code HttpService} instance. + */ + public HttpService() { + } + + /** + * Constructs a new {@code HttpService} instance at the given host. + * + * @param host The host name of the service. + */ + public HttpService(String host) { + this.host = host; + } + + /** + * Constructs a new {@code HttpService} instance at the given host and port. + * + * @param host The host name of the service. + * @param port The port number of the service. + */ + public HttpService(String host, int port) { + this.host = host; + this.port = port; + } + + /** + * Constructs a new {@code HttpService} instance using the given host, + * port, and scheme. + * + * @param host The host name of the service. + * @param port The port number of the service. + * @param scheme Scheme for accessing the service ({@code http} or + * {@code https}). + */ + public HttpService(String host, int port, String scheme) { + this.host = host; + this.port = port; + this.scheme = scheme; + } + + /** + * Constructs a new {@code HttpService} instance using the given host, + * port, and scheme, and instructing it to use the specified HTTPS handler. + * + * @param host The host name of the service. + * @param port The port number of the service. + * @param scheme Scheme for accessing the service ({@code http} or + * {@code https}). + * @param httpsHandler A custom URL Stream handler. + */ + public HttpService(String host, int port, String scheme, + URLStreamHandler httpsHandler) { + this.host = host; + this.port = port; + this.scheme = scheme; + this.httpsHandler = httpsHandler; + } + + // Returns the count of arguments in the given {@code args} map. + private static int count(Map<String, Object> args) { + if (args == null) return 0; + return args.size(); + } + + /** + * Issues an HTTP GET request against the service using a given path. + * + * @param path The request path. + * @return The HTTP response. + */ + public ResponseMessage get(String path) { + return send(path, new RequestMessage("GET")); + } + + /** + * Issues an HTTP GET request against the service using a given path and + * query arguments. + * + * @param path The request path. + * @param args The query arguments. + * @return The HTTP response. + */ + public ResponseMessage get(String path, Map<String, Object> args) { + if (count(args) > 0) + path = path + "?" + Args.encode(args); + RequestMessage request = new RequestMessage("GET"); + return send(path, request); + } + + /** + * Returns the host name of this service. + * + * @return The host name. + */ + public String getHost() { + return this.host; + } + + /** + * Returns the port number of this service. + * + * @return The port number. + */ + public int getPort() { + return this.port; + } + + /** + * Sets Custom Headers of this service + * + * @param headers The custom headers. + */ + public void setCustomHeaders(Map<String, String> headers) { + if (Objects.nonNull(headers)) { + customHeaders = headers; + } + } + + /** + * Returns the SSL security protocol of this service. + * + * @return The SSL security protocol. + */ + public static SSLSecurityProtocol getSslSecurityProtocol() { + return sslSecurityProtocol; + } + + /** + * Sets the SSL security protocol of this service. + * @param securityProtocol The SSLSecurityProtocal instance + */ + public static void setSslSecurityProtocol(SSLSecurityProtocol securityProtocol) { + // Only update the SSL_SOCKET_FACTORY if changing protocols + if (sslSecurityProtocol != securityProtocol) { + sslSecurityProtocol = securityProtocol; + sslSocketFactory = createSSLFactory(); + } + } + + /** + * Adds list of Cluster Master Hosts to the list of Valid Hosts for Hostname verification. + * @param searchHeadService Splunk SearchHead Service instance + */ + public static void addClusterMasterURIsToHosts(Service searchHeadService){ + VALID_HOSTS.addAll(searchHeadService.getClusterMasters()); + } + + /** + * Returns the URL prefix of this service, consisting of + * {@code scheme://host[:port]}. + * + * @return The URL prefix. + */ + public String getPrefix() { + if (this.prefix == null) + this.prefix = String.format("%s://%s:%s", + this.scheme, this.host, this.port); + return this.prefix; + } + + /** + * Returns the scheme used by this service. + * + * @return The scheme. + */ + public String getScheme() { + return this.scheme; + } + + /** + * Constructs a fully-qualified URL for this service using a given path. + * + * @param path The path to qualify. + * @return The fully-qualified URL for the service. + */ + public URL getUrl(String path) { + try { + if (HTTPS_SCHEME.equals(getScheme()) && httpsHandler != null) { + // This branch is not currently covered by unit tests as I + // could not figure out a generic way to get the default + // HTTPS handler. + return new URL(getScheme(), getHost(), getPort(), path, + httpsHandler); + } else { + return new URL(getScheme(), getHost(), getPort(), path); + } + } catch (MalformedURLException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + /** + * Returns all the stored custom headers + * + * @return customHeaders The custom headers + */ + public Map<String, String> getCustomHeaders() { + return customHeaders; + } + + /** + * Returns all the stored cookies + * + * @return All cookies as in a string in the format key=value; key=value; etc=etc + */ + public String stringifyCookies() { + return cookieStore.getCookies(); + } + + /** + * Adds the passed cookie header to the cookieStore + * + * @param setCookieHeader The result from a getRequestHeader("Set-Cookie") call + */ + public void addCookie(String setCookieHeader) { + cookieStore.add(setCookieHeader); + } + + /** + * Removes all cookies from the cookieStore + */ + public void removeAllCookies() { + cookieStore.removeAll(); + } + + /** + * Returns true if the cookieStore has any Splunk Authorization cookies, false otherwise + * + * @return True if there are cookies, false otherwise + */ + public Boolean hasSplunkAuthCookies() { + return cookieStore.hasSplunkAuthCookie(); + } + + /** + * Returns the connect timeout used by this service. + * + * @return The timeout in milliseconds. + */ + public Integer getConnectTimeout() { + return connectTimeout; + } + + /** + * Sets a specified timeout value, in milliseconds, to be used when opening a communications link. + * + * @param connectTimeout timeout in milliseconds, a timeout of zero is interpreted as an infinite timeout. + */ + public void setConnectTimeout(Integer connectTimeout) { + this.connectTimeout = connectTimeout; + } + + /** + * Returns the read timeout used by this service. + * + * @return The timeout in milliseconds. + */ + public Integer getReadTimeout() { + return readTimeout; + } + + /** + * Sets a specified timeout value, in milliseconds, to be used when reading from a communications link. + * + * @param readTimeout timeout in milliseconds, a timeout of zero is interpreted as an infinite timeout. + */ + public void setReadTimeout(Integer readTimeout) { + this.readTimeout = readTimeout; + } + + /** + * Issues a POST request against the service using a given path. + * + * @param path The request path. + * @return The HTTP response. + */ + public ResponseMessage post(String path) { + return post(path, null); + } + + /** + * Issues a POST request against the service using a given path and + * form arguments. + * + * @param path The request path. + * @param args The form arguments. + * @return The HTTP response. + */ + public ResponseMessage post(String path, Map<String, Object> args) { + RequestMessage request = new RequestMessage("POST"); + request.getHeader().put( + "Content-Type", "application/x-www-form-urlencoded"); + if (count(args) > 0) + request.setContent(Args.encode(args)); + return send(path, request); + } + + /** + * Issues a DELETE request against the service using a given path. + * + * @param path The request path. + * @return The HTTP response. + */ + public ResponseMessage delete(String path) { + RequestMessage request = new RequestMessage("DELETE"); + return send(path, request); + } + + /** + * Issues a DELETE request against the service using a given path + * and query arguments. + * + * @param path The request path. + * @param args The query arguments. + * @return The HTTP response. + */ + public ResponseMessage delete(String path, Map<String, Object> args) { + if (count(args) > 0) + path = path + "?" + Args.encode(args); + RequestMessage request = new RequestMessage("DELETE"); + return send(path, request); + } + + /** + * Opens a socket to this service. + * + * @return The socket. + * @throws IOException + */ + Socket open() throws IOException { + if (this.scheme.equals("https")) { + return sslSocketFactory.createSocket(this.host, this.port); + } + return new Socket(this.host, this.port); + } + + /** + * Issue an HTTP request against the service using a given path and + * request message. + * + * @param path The request path. + * @param request The request message. + * @return The HTTP response. + */ + public ResponseMessage send(String path, RequestMessage request) { + // Construct a full URL to the resource + URL url = getUrl(path); + // Create and initialize the connection object + HttpURLConnection cn; + try { + cn = (HttpURLConnection) url.openConnection(); + } catch (IOException e) { + throw new RuntimeException(e.getMessage(), e); + } + if (cn instanceof HttpsURLConnection cnInst) { + cnInst.setSSLSocketFactory(sslSocketFactory); + cnInst.setHostnameVerifier(HOSTNAME_VERIFIER); + } + cn.setUseCaches(false); + cn.setAllowUserInteraction(false); + cn.setConnectTimeout(connectTimeout == null ? 0 : connectTimeout); + cn.setReadTimeout(readTimeout == null ? 0 : readTimeout); + + // Set the request method + String method = request.getMethod(); + try { + cn.setRequestMethod(method); + } catch (ProtocolException e) { + throw new RuntimeException(e.getMessage(), e); + } + + // Add headers from request message + Map<String, String> header = request.getHeader(); + for (Entry<String, String> entry : header.entrySet()) + cn.setRequestProperty(entry.getKey(), entry.getValue()); + // Add default headers that were absent from the request message + for (Entry<String, String> entry : defaultHeader.entrySet()) { + String key = entry.getKey(); + if (header.containsKey(key)) continue; + cn.setRequestProperty(key, entry.getValue()); + } + // Add Custom Headers + for (Entry<String, String> entry: customHeaders.entrySet()) { + String key = entry.getKey(); + if (!header.containsKey(key)) { + cn.setRequestProperty(key, entry.getValue()); + } + } + + // Add cookies to header + cn.setRequestProperty("Cookie", cookieStore.getCookies()); + + // Write out request content, if any + try { + Object content = request.getContent(); + if (content != null) { + cn.setDoOutput(true); + OutputStream stream = cn.getOutputStream(); + OutputStreamWriter writer = new OutputStreamWriter(stream, "UTF-8"); + writer.write((String) content); + writer.close(); + } + } catch (IOException e) { + throw new RuntimeException(e.getMessage(), e); + } + + if (VERBOSE_REQUESTS) { + System.out.format("%s %s => ", method, url.toString()); + } + + // Execute the request + try { + cn.connect(); + } catch (IOException e) { + throw new RuntimeException(e.getMessage(), e); + } + + int status; + try { + status = cn.getResponseCode(); + } catch (IOException e) { + throw new RuntimeException(e.getMessage(), e); + } + + InputStream input = null; + try { + input = status >= 400 + ? cn.getErrorStream() + : cn.getInputStream(); + } catch (IOException e) { + assert (false); + } + + // If user session has expired check for 'autologin' flag to either re-login or throw HTTPException + if(this instanceof Service && status == 401){ + return new ResponseMessage(401, input); + } + + // Add cookies to cookie Store + Map<String, List<String>> headers = cn.getHeaderFields(); + if (headers.containsKey("Set-Cookie")) { + for (String cookieHeader : headers.get("Set-Cookie")) { + if (cookieHeader != null && cookieHeader.length() > 0) + cookieStore.add(cookieHeader); + } + } + + ResponseMessage response = new ResponseMessage(status, input); + + if (VERBOSE_REQUESTS) { + System.out.format("%d\n", status); + if (method.equals("POST")) { + System.out.println(" " + request.getContent()); + } + } + + if (status >= 400) + throw HttpException.create(response); + + return response; + } + + public static void setSSLSocketFactory(SSLSocketFactory sslSocketFactory) { + if (sslSocketFactory == null) + throw new IllegalArgumentException("The sslSocketFactory cannot be null."); + HttpService.sslSocketFactory = sslSocketFactory; + } + + public static SSLSocketFactory getSSLSocketFactory() { + return HttpService.sslSocketFactory; + } + + public static void setValidateCertificates(boolean validateCertificate) { + // update the SSL_SOCKET_FACTORY if validateCertificates flag is changed + if (validateCertificates != validateCertificate) { + validateCertificates = validateCertificate; + sslSocketFactory = createSSLFactory(); + } + } + + public static SSLSocketFactory createSSLFactory() { + + try { + SSLContext context; + if (sslSecurityProtocol != null) { + String contextStr = sslSecurityProtocol.toString().contains("SSL") ? "SSL" : "TLS"; + context = SSLContext.getInstance(contextStr); + } else if (System.getProperty("java.version").compareTo("1.8") >= 0) { + context = SSLContext.getInstance("TLS"); + } else { + context = SSLContext.getDefault(); + } + + if (validateCertificates) { + context.init(null, null, null); + // For now this check is set as null. + // TODO: Implementation logic for validating client certificate. + } else { + TrustManager[] trustAll = new TrustManager[]{ + new X509TrustManager() { + public X509Certificate[] getAcceptedIssuers() { + return null; + } + + public void checkClientTrusted(X509Certificate[] certs, String authType) { + } + + public void checkServerTrusted(X509Certificate[] certs, String authType) { + } + } + }; + context.init(null, trustAll, null); + } + + return context.getSocketFactory(); + } catch (Exception e) { + throw new RuntimeException("Error setting up SSL socket factory: " + e, e); + } + } + +} + diff --git a/splunk/src/main/java/com/splunk/IPv4PivotFilter.java b/splunk/src/main/java/com/splunk/IPv4PivotFilter.java index 9fe794d4..af07fa76 100644 --- a/splunk/src/main/java/com/splunk/IPv4PivotFilter.java +++ b/splunk/src/main/java/com/splunk/IPv4PivotFilter.java @@ -19,7 +19,6 @@ import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; -import java.net.Inet4Address; /** * Represents a filter on an IPv4 valued field in a pivot. diff --git a/splunk/src/main/java/com/splunk/Index.java b/splunk/src/main/java/com/splunk/Index.java index f39dd2e7..18a9adbd 100644 --- a/splunk/src/main/java/com/splunk/Index.java +++ b/splunk/src/main/java/com/splunk/Index.java @@ -64,16 +64,10 @@ public Socket attach() throws IOException { * @throws IOException The IOException class */ public void attachWith(ReceiverBehavior behavior) throws IOException { - Socket socket = null; - OutputStream output = null; - try { - socket = attach(); - output = socket.getOutputStream(); + try (Socket socket = attach(); + OutputStream output = socket.getOutputStream();) { behavior.run(output); output.flush(); - } finally { - if (output != null) { output.close(); } - if (socket != null) { socket.close(); } } } diff --git a/splunk/src/main/java/com/splunk/IndexCollection.java b/splunk/src/main/java/com/splunk/IndexCollection.java index cf98d95a..38c18453 100644 --- a/splunk/src/main/java/com/splunk/IndexCollection.java +++ b/splunk/src/main/java/com/splunk/IndexCollection.java @@ -49,7 +49,7 @@ public Index remove(String key) { "Indexes cannot be deleted via the REST API in versions " + "prior to 5.0"); } else { - return (Index)super.remove(key); + return super.remove(key); } } } diff --git a/splunk/src/main/java/com/splunk/Input.java b/splunk/src/main/java/com/splunk/Input.java index 95ca6c8d..2029e3e3 100644 --- a/splunk/src/main/java/com/splunk/Input.java +++ b/splunk/src/main/java/com/splunk/Input.java @@ -16,7 +16,6 @@ package com.splunk; -import java.util.Map; /** * The {@code Input} class represents a data input. This class is the base for diff --git a/splunk/src/main/java/com/splunk/InputCollection.java b/splunk/src/main/java/com/splunk/InputCollection.java index 0fcefa02..4f871936 100644 --- a/splunk/src/main/java/com/splunk/InputCollection.java +++ b/splunk/src/main/java/com/splunk/InputCollection.java @@ -24,7 +24,7 @@ * value that indicates the specific type of input. */ public class InputCollection extends EntityCollection<Input> { - protected Set<InputKind> inputKinds = new HashSet<InputKind>(); + protected Set<InputKind> inputKinds = new HashSet<>(); /** * Class constructor. @@ -239,7 +239,7 @@ protected static boolean matchesInputName(InputKind kind, String searchFor, Stri * @return A set of available {@code InputKind}s. */ private Set<InputKind> assembleInputKindSet(List<String> subPath) { - Set<InputKind> kinds = new HashSet<InputKind>(); + Set<InputKind> kinds = new HashSet<>(); ResponseMessage response = service.get(this.path + "/" + Util.join("/", subPath)); AtomFeed feed = AtomFeed.parseStream(response.getContent()); for (AtomEntry entry : feed.entries) { @@ -252,7 +252,7 @@ private Set<InputKind> assembleInputKindSet(List<String> subPath) { } } - List<String> thisSubPath = new ArrayList<String>(subPath); + List<String> thisSubPath = new ArrayList<>(subPath); thisSubPath.add(itemKeyName); String relpath = Util.join("/", thisSubPath); @@ -276,7 +276,7 @@ private Set<InputKind> assembleInputKindSet(List<String> subPath) { * Refreshes the {@code inputKinds} field on this object. */ private void refreshInputKinds() { - Set<InputKind> kinds = assembleInputKindSet(new ArrayList<String>()); + Set<InputKind> kinds = assembleInputKindSet(new ArrayList<>()); this.inputKinds.clear(); this.inputKinds.addAll(kinds); @@ -295,13 +295,11 @@ private void refreshInputKinds() { // Iterate over all input kinds and collect all instances. for (InputKind kind : this.inputKinds) { - if (service.versionIsAtLeast("6.0.0")) { + if (service.versionIsAtLeast("6.0.0") && kind.getKind().equals("registry")) { // 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; - } + continue; } String relpath = kind.getRelativePath(); String inputs = String.format("%s/%s?count=-1", path, relpath); diff --git a/splunk/src/main/java/com/splunk/InputKind.java b/splunk/src/main/java/com/splunk/InputKind.java index f3cd62b3..f85ebe85 100644 --- a/splunk/src/main/java/com/splunk/InputKind.java +++ b/splunk/src/main/java/com/splunk/InputKind.java @@ -30,7 +30,7 @@ public class InputKind { private String relpath; private Class<? extends Input> inputClass; - private static Map<String, InputKind> knownRelpaths = new HashMap<String, InputKind>(); + private static Map<String, InputKind> knownRelpaths = new HashMap<>(); /** Unknown type of input. */ public static final InputKind Unknown = new InputKind(null, Input.class, "unknown"); diff --git a/splunk/src/main/java/com/splunk/JobArgs.java b/splunk/src/main/java/com/splunk/JobArgs.java index d0f5eaf4..8601383c 100644 --- a/splunk/src/main/java/com/splunk/JobArgs.java +++ b/splunk/src/main/java/com/splunk/JobArgs.java @@ -25,7 +25,7 @@ public class JobArgs extends Args { * Specifies how to create a job using the {@link JobCollection#create} * method. */ - public static enum ExecutionMode { + public enum ExecutionMode { /** Runs a search asynchronously and returns a search job immediately.*/ NORMAL("normal"), /** Runs a search synchronously and does not return a search job until @@ -53,7 +53,7 @@ public String toString() { * Specifies how to create a job using the {@link JobCollection#create} * method. */ - public static enum SearchMode { + public enum SearchMode { /** * Searches historical data. */ diff --git a/splunk/src/main/java/com/splunk/JobCollection.java b/splunk/src/main/java/com/splunk/JobCollection.java index 661e21ff..d776f08e 100644 --- a/splunk/src/main/java/com/splunk/JobCollection.java +++ b/splunk/src/main/java/com/splunk/JobCollection.java @@ -74,9 +74,8 @@ public Job create(String query) { * @return The unique search identifier (SID). */ public Job create(String query, Map args) { - if (args != null && args.containsKey("exec_mode")) { - if (args.get("exec_mode").equals("oneshot")) - throw new RuntimeException(oneShotNotAllowed); + if (args != null && args.containsKey("exec_mode") && args.get("exec_mode").equals("oneshot")) { + throw new RuntimeException(oneShotNotAllowed); } args = Args.create(args).add("search", query); ResponseMessage response = service.post(path, args); diff --git a/splunk/src/main/java/com/splunk/JobEventsArgs.java b/splunk/src/main/java/com/splunk/JobEventsArgs.java index 233e3c1b..4268a590 100644 --- a/splunk/src/main/java/com/splunk/JobEventsArgs.java +++ b/splunk/src/main/java/com/splunk/JobEventsArgs.java @@ -25,7 +25,7 @@ public class JobEventsArgs extends Args { /** * Specifies the format for the returned output. */ - public static enum OutputMode { + public enum OutputMode { /** Returns output in Atom format. */ ATOM("atom"), /** Returns output in CSV format. */ @@ -59,7 +59,7 @@ public String toString() { * Specifies how to truncate lines to achieve the value in * {@link #setMaximumLines}. */ - public static enum TruncationMode { + public enum TruncationMode { /** Use the "abstract" truncation mode.*/ ABSTRACT("abstract"), /** Use the "truncate" truncation mode.*/ diff --git a/splunk/src/main/java/com/splunk/JobExportArgs.java b/splunk/src/main/java/com/splunk/JobExportArgs.java index 5d5f8930..5d728d4a 100644 --- a/splunk/src/main/java/com/splunk/JobExportArgs.java +++ b/splunk/src/main/java/com/splunk/JobExportArgs.java @@ -25,7 +25,7 @@ public class JobExportArgs extends Args { /** * Specifies the format for the returned output. */ - public static enum OutputMode { + public enum OutputMode { /** Returns output in Atom format. */ ATOM("atom"), /** Returns output in CSV format. */ @@ -59,7 +59,7 @@ public String toString() { * Specifies how to create a job using the {@link JobCollection#create} * method. */ - public static enum SearchMode { + public enum SearchMode { /** * Searches historical data. */ @@ -98,7 +98,7 @@ public String toString() { * Specifies how to truncate lines to achieve the value in * {@link #setMaximumLines}. */ - public static enum TruncationMode { + public enum TruncationMode { /** Use the "abstract" truncation mode.*/ ABSTRACT("abstract"), /** Use the "truncate" truncation mode.*/ diff --git a/splunk/src/main/java/com/splunk/JobResultsArgs.java b/splunk/src/main/java/com/splunk/JobResultsArgs.java index a35bbd8b..5e60ecc7 100644 --- a/splunk/src/main/java/com/splunk/JobResultsArgs.java +++ b/splunk/src/main/java/com/splunk/JobResultsArgs.java @@ -25,7 +25,7 @@ public class JobResultsArgs extends Args { /** * Specifies the format for the returned output. */ - public static enum OutputMode { + public enum OutputMode { /** Returns output in Atom format. */ ATOM("atom"), /** Returns output in CSV format. */ diff --git a/splunk/src/main/java/com/splunk/JobResultsPreviewArgs.java b/splunk/src/main/java/com/splunk/JobResultsPreviewArgs.java index d929f010..ce0ba673 100644 --- a/splunk/src/main/java/com/splunk/JobResultsPreviewArgs.java +++ b/splunk/src/main/java/com/splunk/JobResultsPreviewArgs.java @@ -25,7 +25,7 @@ public class JobResultsPreviewArgs extends Args { /** * Specifies the format for the returned output. */ - public static enum OutputMode { + public enum OutputMode { /** Returns output in Atom format. */ ATOM("atom"), /** Returns output in CSV format. */ diff --git a/splunk/src/main/java/com/splunk/LicensePool.java b/splunk/src/main/java/com/splunk/LicensePool.java index 613fcaac..b9565fe6 100644 --- a/splunk/src/main/java/com/splunk/LicensePool.java +++ b/splunk/src/main/java/com/splunk/LicensePool.java @@ -17,7 +17,6 @@ package com.splunk; import java.util.HashMap; -import java.util.List; import java.util.Map; /** @@ -83,10 +82,10 @@ public Map<String, Long> getSlavesUsageBytes() { @SuppressWarnings("unchecked") HashMap<String, Object> values = (HashMap<String, Object>)get("slaves_usage_bytes"); if (values == null) { - values = new HashMap<String, Object>(); + values = new HashMap<>(); } - HashMap<String, Long> usageBytes = new HashMap<String, Long>(); + HashMap<String, Long> usageBytes = new HashMap<>(); for(String key : values.keySet()) { String value = (String)values.get(key); diff --git a/splunk/src/main/java/com/splunk/ModularInputKind.java b/splunk/src/main/java/com/splunk/ModularInputKind.java index 5cc6f2a5..c7d17f8b 100644 --- a/splunk/src/main/java/com/splunk/ModularInputKind.java +++ b/splunk/src/main/java/com/splunk/ModularInputKind.java @@ -17,7 +17,6 @@ import java.util.HashMap; import java.util.Map; -import java.util.List; /** * The {@code ModularInputKind} class represents a particular modular input. @@ -47,7 +46,7 @@ public class ModularInputKind extends Entity { * @return A {@code Map} containing the argument key-value pairs. */ public Map<String, ModularInputKindArgument> getArguments() { - Map<String, ModularInputKindArgument> arguments = new HashMap<String, ModularInputKindArgument>(); + Map<String, ModularInputKindArgument> arguments = new HashMap<>(); for (String argumentName : args.keySet()) { arguments.put(argumentName, getArgument(argumentName)); } @@ -60,8 +59,7 @@ public Map<String, ModularInputKindArgument> getArguments() { * @return The streaming mode ("xml" or "simple"). */ public String getStreamingMode() { - String mode = getString("streaming_mode"); - return mode; + return getString("streaming_mode"); } /** diff --git a/splunk/src/main/java/com/splunk/ModularInputKindArgument.java b/splunk/src/main/java/com/splunk/ModularInputKindArgument.java index 6f42de3d..3ac28fa0 100644 --- a/splunk/src/main/java/com/splunk/ModularInputKindArgument.java +++ b/splunk/src/main/java/com/splunk/ModularInputKindArgument.java @@ -23,7 +23,7 @@ * specialized to represent arguments for modular input kinds. */ public class ModularInputKindArgument extends HashMap<String,String> { - public enum Type { NUMBER, STRING, BOOLEAN }; + public enum Type { NUMBER, STRING, BOOLEAN } /** * Class constructor. diff --git a/splunk/src/main/java/com/splunk/MultiResultsReader.java b/splunk/src/main/java/com/splunk/MultiResultsReader.java index cc57b97f..aa1cfa5c 100644 --- a/splunk/src/main/java/com/splunk/MultiResultsReader.java +++ b/splunk/src/main/java/com/splunk/MultiResultsReader.java @@ -1,63 +1,63 @@ -/* - * 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.io.IOException; -import java.util.Iterator; - -/** - * The {@code MultiResultsReader} class represents a streaming reader - * for Splunk search results. Using {@code <T extends ResultsReader>} allows - * specialization of {@code T} in subclasses of {@code MultiResultsReader}, such - * as {@link MultiResultsReaderXml} and {@link MultiResultsReaderJson}. - */ -public class MultiResultsReader<T extends ResultsReader> - extends StreamIterableBase<SearchResults> { - private T resultsReader; - - MultiResultsReader(T resultsReader) throws IOException { - this.resultsReader = resultsReader; - } - - /** - * Returns an iterator over the sets of results from this reader. - * @return An iterator. - */ - @Override - public final Iterator<SearchResults> iterator() { - return super.iterator(); - } - - /** - * Closes the reader and releases resources. - * @throws IOException If reader is not closed. - */ - public final void close() throws IOException { - resultsReader.close(); - } - - protected final T getNextElement() { - try { - if (!resultsReader.resetIteratorToNextSet()) { - return null; - } - return resultsReader; - } catch (IOException e) { - throw new RuntimeException(e); - } - } +/* + * 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.io.IOException; +import java.util.Iterator; + +/** + * The {@code MultiResultsReader} class represents a streaming reader + * for Splunk search results. Using {@code <T extends ResultsReader>} allows + * specialization of {@code T} in subclasses of {@code MultiResultsReader}, such + * as {@link MultiResultsReaderXml} and {@link MultiResultsReaderJson}. + */ +public class MultiResultsReader<T extends ResultsReader> + extends StreamIterableBase<SearchResults> { + private T resultsReader; + + MultiResultsReader(T resultsReader) throws IOException { + this.resultsReader = resultsReader; + } + + /** + * Returns an iterator over the sets of results from this reader. + * @return An iterator. + */ + @Override + public final Iterator<SearchResults> iterator() { + return super.iterator(); + } + + /** + * Closes the reader and releases resources. + * @throws IOException If reader is not closed. + */ + public final void close() throws IOException { + resultsReader.close(); + } + + protected final T getNextElement() { + try { + if (!resultsReader.resetIteratorToNextSet()) { + return null; + } + return resultsReader; + } catch (IOException e) { + throw new RuntimeException(e); + } + } } \ No newline at end of file diff --git a/splunk/src/main/java/com/splunk/MultiResultsReaderJson.java b/splunk/src/main/java/com/splunk/MultiResultsReaderJson.java index 77a2c9f6..3d360fbd 100644 --- a/splunk/src/main/java/com/splunk/MultiResultsReaderJson.java +++ b/splunk/src/main/java/com/splunk/MultiResultsReaderJson.java @@ -1,42 +1,42 @@ -/* - * 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.io.IOException; -import java.io.InputStream; - -/** - * The {@code MultiResultsReaderJson} class represents a streaming JSON reader - * for Splunk search results. This reader supports streams from export searches, - * which might return one of more previews before returning final results. - */ -public class MultiResultsReaderJson - extends MultiResultsReader<ResultsReaderJson> { - /** - * Class constructor. - * - * Constructs a streaming JSON reader for the event stream. You should only - * attempt to parse a JSON stream with this reader. Unpredictable results - * may occur if you try to parse a stream with a different format. - * - * @param inputStream The JSON stream to parse. - * @throws IOException The IOException instance - */ - public MultiResultsReaderJson(InputStream inputStream) throws IOException { - super(new ResultsReaderJson(inputStream, true)); - } +/* + * 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.io.IOException; +import java.io.InputStream; + +/** + * The {@code MultiResultsReaderJson} class represents a streaming JSON reader + * for Splunk search results. This reader supports streams from export searches, + * which might return one of more previews before returning final results. + */ +public class MultiResultsReaderJson + extends MultiResultsReader<ResultsReaderJson> { + /** + * Class constructor. + * + * Constructs a streaming JSON reader for the event stream. You should only + * attempt to parse a JSON stream with this reader. Unpredictable results + * may occur if you try to parse a stream with a different format. + * + * @param inputStream The JSON stream to parse. + * @throws IOException The IOException instance + */ + public MultiResultsReaderJson(InputStream inputStream) throws IOException { + super(new ResultsReaderJson(inputStream, true)); + } } \ No newline at end of file diff --git a/splunk/src/main/java/com/splunk/MultiResultsReaderXml.java b/splunk/src/main/java/com/splunk/MultiResultsReaderXml.java index 53088389..3675dc57 100644 --- a/splunk/src/main/java/com/splunk/MultiResultsReaderXml.java +++ b/splunk/src/main/java/com/splunk/MultiResultsReaderXml.java @@ -1,42 +1,42 @@ -/* - * 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.io.IOException; -import java.io.InputStream; - -/** - * The {@code MultiResultsReaderXml} class represents a streaming XML reader for - * Splunk search results. This reader supports streams from export searches, - * which might return one of more previews before returning final results. - */ -public class MultiResultsReaderXml - extends MultiResultsReader<ResultsReaderXml> { - /** - * Class constructor. - * - * Constructs a streaming XML reader for the event stream. You should only - * attempt to parse an XML stream with this reader. Unpredictable results - * may occur if you try to parse a stream with a different format. - * - * @param inputStream The XML stream to parse. - * @throws IOException The IOException instance - */ - public MultiResultsReaderXml(InputStream inputStream) throws IOException { - super(new ResultsReaderXml(inputStream, true)); - } -} +/* + * 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.io.IOException; +import java.io.InputStream; + +/** + * The {@code MultiResultsReaderXml} class represents a streaming XML reader for + * Splunk search results. This reader supports streams from export searches, + * which might return one of more previews before returning final results. + */ +public class MultiResultsReaderXml + extends MultiResultsReader<ResultsReaderXml> { + /** + * Class constructor. + * + * Constructs a streaming XML reader for the event stream. You should only + * attempt to parse an XML stream with this reader. Unpredictable results + * may occur if you try to parse a stream with a different format. + * + * @param inputStream The XML stream to parse. + * @throws IOException The IOException instance + */ + public MultiResultsReaderXml(InputStream inputStream) throws IOException { + super(new ResultsReaderXml(inputStream, true)); + } +} diff --git a/splunk/src/main/java/com/splunk/PasswordCollection.java b/splunk/src/main/java/com/splunk/PasswordCollection.java index 47a50a22..1a8da1c1 100644 --- a/splunk/src/main/java/com/splunk/PasswordCollection.java +++ b/splunk/src/main/java/com/splunk/PasswordCollection.java @@ -89,8 +89,8 @@ public Password get(String realm, String name) { @Override public Password get(Object key) { // Make it compatible with the old way (low-efficient) - if (key instanceof String && !((String) key).contains(":")) { - return getByUsername((String) key); + if (key instanceof String keyInst && !keyInst.contains(":")) { + return getByUsername(keyInst); } return super.get(key); } @@ -116,7 +116,7 @@ public Password remove(String key) { } // Make it compatible with the old way (low-efficient) if (!key.contains(":")) { - Password password = getByUsername((String) key); + Password password = getByUsername(key); validate(); if (password == null) return null; password.remove(); @@ -129,8 +129,8 @@ public Password remove(String key) { @Override public boolean containsKey(Object key) { - if (key instanceof String && !((String) key).contains(":")) { - return getByUsername((String) key) != null; + if (key instanceof String keyInst && !keyInst.contains(":")) { + return getByUsername(keyInst) != null; } return super.containsKey(key); } diff --git a/splunk/src/main/java/com/splunk/PivotFilter.java b/splunk/src/main/java/com/splunk/PivotFilter.java index 21645ef3..ccd3f361 100644 --- a/splunk/src/main/java/com/splunk/PivotFilter.java +++ b/splunk/src/main/java/com/splunk/PivotFilter.java @@ -17,9 +17,6 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; -import com.google.gson.JsonPrimitive; - -import java.util.ArrayList; /** * Base class representing filters in pivots. diff --git a/splunk/src/main/java/com/splunk/PivotSpecification.java b/splunk/src/main/java/com/splunk/PivotSpecification.java index 1aa154a9..3e12ad03 100644 --- a/splunk/src/main/java/com/splunk/PivotSpecification.java +++ b/splunk/src/main/java/com/splunk/PivotSpecification.java @@ -30,10 +30,10 @@ public class PivotSpecification { private DataModelObject dataModelObject; private String accelerationNamespace = null; - private List<PivotColumnSplit> columns = new ArrayList<PivotColumnSplit>(); - private List<PivotFilter> filters = new ArrayList<PivotFilter>(); - private List<PivotCellValue> cells = new ArrayList<PivotCellValue>(); - private List<PivotRowSplit> rows = new ArrayList<PivotRowSplit>(); + private List<PivotColumnSplit> columns = new ArrayList<>(); + private List<PivotFilter> filters = new ArrayList<>(); + private List<PivotCellValue> cells = new ArrayList<>(); + private List<PivotRowSplit> rows = new ArrayList<>(); PivotSpecification(DataModelObject dataModelObject) { this.dataModelObject = dataModelObject; diff --git a/splunk/src/main/java/com/splunk/RangePivotRowSplit.java b/splunk/src/main/java/com/splunk/RangePivotRowSplit.java index a6882ce4..a1e2c8f0 100644 --- a/splunk/src/main/java/com/splunk/RangePivotRowSplit.java +++ b/splunk/src/main/java/com/splunk/RangePivotRowSplit.java @@ -17,7 +17,6 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; -import com.google.gson.JsonPrimitive; /** * Split values of a field into rows by ranges of a numeric field. diff --git a/splunk/src/main/java/com/splunk/Receiver.java b/splunk/src/main/java/com/splunk/Receiver.java index 8ae4d826..b8afc43b 100644 --- a/splunk/src/main/java/com/splunk/Receiver.java +++ b/splunk/src/main/java/com/splunk/Receiver.java @@ -18,7 +18,6 @@ import java.io.*; import java.net.Socket; -import java.lang.StringBuilder; import java.util.ArrayList; import java.util.List; @@ -108,7 +107,7 @@ public Socket attach(String indexName, Args args) throws IOException { headers.add(String.format("Authorization: %s", service.getToken())); } headers.add(""); - headers.forEach(header -> writer.println(header)); + headers.forEach(writer::println); writer.flush(); return socket; } diff --git a/splunk/src/main/java/com/splunk/RequestMessage.java b/splunk/src/main/java/com/splunk/RequestMessage.java index 816e1fe2..a44ceebf 100644 --- a/splunk/src/main/java/com/splunk/RequestMessage.java +++ b/splunk/src/main/java/com/splunk/RequestMessage.java @@ -63,7 +63,7 @@ boolean checkMethod(String value) { */ public Map<String, String> getHeader() { if (this.header == null) - this.header = new TreeMap<String, String>( + this.header = new TreeMap<>( String.CASE_INSENSITIVE_ORDER); return this.header; } diff --git a/splunk/src/main/java/com/splunk/Resource.java b/splunk/src/main/java/com/splunk/Resource.java index 4dc43e27..1335a728 100644 --- a/splunk/src/main/java/com/splunk/Resource.java +++ b/splunk/src/main/java/com/splunk/Resource.java @@ -66,7 +66,7 @@ public abstract class Resource { this.service = service; this.path = service.fullpath( - path, namespace.size() == 0 ? null : namespace); + path, namespace.isEmpty() ? null : namespace); this.refreshArgs = args; } diff --git a/splunk/src/main/java/com/splunk/ResourceCollection.java b/splunk/src/main/java/com/splunk/ResourceCollection.java index b81ecb8a..94f2b006 100644 --- a/splunk/src/main/java/com/splunk/ResourceCollection.java +++ b/splunk/src/main/java/com/splunk/ResourceCollection.java @@ -30,7 +30,7 @@ public class ResourceCollection<T extends Resource> extends Resource implements Map<String, T> { protected LinkedHashMap<String, LinkedList<T>> - items = new LinkedHashMap<String, LinkedList<T>>(); + items = new LinkedHashMap<>(); protected Class itemClass; /** @@ -83,7 +83,7 @@ public boolean containsKey(Object key, Args namespace) { validate(); LinkedList<T> entities = items.get(key); - if (entities == null || entities.size() == 0) return false; + if (entities == null || entities.isEmpty()) return false; String pathMatcher = service.fullpath("", namespace); for (T entity: entities) { if (entity.path.startsWith(pathMatcher)) { @@ -97,7 +97,7 @@ public boolean containsKey(Object key, Args namespace) { public boolean containsValue(Object value) { // value should be a non-linked-list value; values are stored as linked // lists inside our container. - LinkedList<Object> linkedList = new LinkedList<Object>(); + LinkedList<Object> linkedList = new LinkedList<>(); linkedList.add(value); return validate().items.containsValue(linkedList); } @@ -162,7 +162,7 @@ protected T createItem(AtomEntry entry) { } /** {@inheritDoc} */ - public Set<Map.Entry<String, T>> entrySet() { + public Set<Entry<String, T>> entrySet() { throw new UnsupportedOperationException(); } @@ -187,7 +187,7 @@ public T get(Object key) { throw new SplunkException(SplunkException.AMBIGUOUS, "Key has multiple values, specify a namespace"); } - if (entities == null || entities.size() == 0) return null; + if (entities == null || entities.isEmpty()) return null; return entities.get(0); } @@ -205,7 +205,7 @@ public T get(Object key, Args namespace) { validate(); LinkedList<T> entities = items.get(key); - if (entities == null || entities.size() == 0) return null; + if (entities == null || entities.isEmpty()) return null; String pathMatcher = service.fullpath("", namespace); for (T entity: entities) { if (entity.path.startsWith(pathMatcher)) { @@ -262,7 +262,7 @@ private Args namespace(AtomEntry entry) { // If there is no ACL info, we just create an empty map if (entityMetadata == null) { - entityMetadata = new HashMap<String, String>(); + entityMetadata = new HashMap<>(); } if (entityMetadata.containsKey("owner")) @@ -303,7 +303,7 @@ ResourceCollection<T> load(AtomFeed value) { LinkedList<T> list = items.get(key); list.add(item); } else { - LinkedList<T> list = new LinkedList<T>(); + LinkedList<T> list = new LinkedList<>(); list.add(item); items.put(key, list); } @@ -359,7 +359,7 @@ public int size() { /** {@inheritDoc} */ public Collection<T> values() { - LinkedList<T> collection = new LinkedList<T>(); + LinkedList<T> collection = new LinkedList<>(); validate(); Set<String> keySet = items.keySet(); for (String key: keySet) { @@ -380,7 +380,7 @@ public Collection<T> values() { public int valueSize(Object key) { validate(); LinkedList<T> entities = items.get(key); - if (entities == null || entities.size() == 0) return 0; + if (entities == null || entities.isEmpty()) return 0; return entities.size(); } } diff --git a/splunk/src/main/java/com/splunk/ResponseMessage.java b/splunk/src/main/java/com/splunk/ResponseMessage.java index 6eb50c06..911b15d6 100644 --- a/splunk/src/main/java/com/splunk/ResponseMessage.java +++ b/splunk/src/main/java/com/splunk/ResponseMessage.java @@ -65,7 +65,7 @@ public InputStream getContent() { public Map<String, String> getHeader() { if (this.header == null) this.header = - new TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER); + new TreeMap<>(String.CASE_INSENSITIVE_ORDER); return this.header; } diff --git a/splunk/src/main/java/com/splunk/ResultsReader.java b/splunk/src/main/java/com/splunk/ResultsReader.java index 3ccaee6c..a0f8a8eb 100644 --- a/splunk/src/main/java/com/splunk/ResultsReader.java +++ b/splunk/src/main/java/com/splunk/ResultsReader.java @@ -1,178 +1,177 @@ -/* - * 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.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.Iterator; - -/** - * The {@code ResultsReader} class is a base class for the streaming readers - * for Splunk search results. This class should not be used to retrieve preview - * results for an export search. - */ -public abstract class ResultsReader - extends StreamIterableBase<Event> - implements SearchResults { - protected final InputStream inputStream; - // Default should be false which will result in no result set skipping. - boolean isPreview; - boolean isExportStream; - private boolean isInMultiReader; - - ResultsReader(InputStream inputStream, boolean isInMultiReader) - throws IOException { - this.inputStream = inputStream; - isExportStream = inputStream instanceof ExportResultsStream; - this.isInMultiReader = isInMultiReader; - } - - /** - * Closes the reader and returns resources. - * - * @throws IOException On IO exception. - */ - public void close() throws IOException { - inputStream.close(); - } - - /** - * Returns the next event in the event stream. - * - * @return The map of key-value pairs for an event. - * The format of multi-item values is implementation-specific. - * We recommend using the methods from the - * {@link Event} class to interpret multi-item values. - * @throws IOException On IO exception. - */ - final public Event getNextEvent() throws IOException { - return getNextElement(); - } - - /** - * Returns an iterator over the events from this reader. - * @return an Iterator. - */ - @Override - public final Iterator<Event> iterator() { - return super.iterator(); - } - - /** - * Returns the next event while moving to the next set - * automatically when needed, such as concatenating final results - * across multiple sets. - * - * @return null {@code null} if the end is reached. - * @throws IOException On IO exception. - */ - final Event getNextElement() throws IOException { - Event event; - while (true) { - event = getNextEventInCurrentSet(); - - // If we actually managed to get an event, then we break and return it - if (event != null) - break; - - // We don't concatenate across previews across sets, since each set - // might be a snapshot at a given time or a summary result with - // partial data from a reporting search - // (for example "count by host"). So if this is a preview, - // break. Null return indicating the end of the set. - if (isPreview) - break; - - // If we did not advance to next set, i.e. the end of stream is - // reached, break. Null return indicating the end of the set. - if (!advanceStreamToNextSet()) - break; - - // We have advanced to the next set. isPreview is for that set. - // It should not be a preview. Splunk should never return a preview - // after final results which we might have concatenated together - // across sets. - assert (!isPreview) : - "Preview result set should never be after a final set."; - } - return event; - } - - /* - * Get the next event in the current result set. Return null - * if the end is reached. - */ - abstract Event getNextEventInCurrentSet() throws IOException; - - /* - * Return false if the end is reached. - */ - final boolean resetIteratorToNextSet() throws IOException { - - // Get to the beginning of the next set in the stream - // skipping remaining event(s) if any in the current set. - boolean hasMoreResults = advanceStreamToNextSet(); - - // Reset the iterator so that it would either fetch a new - // element for the next iteration or stop. - resetIteration(hasMoreResults); - - return hasMoreResults; - } - - /* - * Return false if the end is reached. - */ - boolean advanceStreamToNextSet() throws IOException { - // Indicate that no more sets are available - // Subclasses can override this method to support - // MultiResultsReader. - return false; - } - - /* - * This method is used by constructors of result readers to do - * the following for single reader: - * 1. Obtain the preview flag and the field list. - * 2. Skip any previews for export. - */ - final void finishInitialization() throws IOException { - if (isInMultiReader) - return; - - while (true) { - // Stop if no more set is available - if (!advanceStreamToNextSet()) { - // Terminating the iteration. - // This avoids future callings into the underlying reader - // to get events, which may result in exceptions. - resetIteration(false); - break; - } - - // No skipping of result sets if the stream - // is not from an export endpoint. - if (!isExportStream) - break; - - // Skipping ends at any file results. - if (!isPreview) - break; - } - } -} +/* + * 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.io.IOException; +import java.io.InputStream; +import java.util.Iterator; + +/** + * The {@code ResultsReader} class is a base class for the streaming readers + * for Splunk search results. This class should not be used to retrieve preview + * results for an export search. + */ +public abstract class ResultsReader + extends StreamIterableBase<Event> + implements SearchResults { + protected final InputStream inputStream; + // Default should be false which will result in no result set skipping. + boolean isPreview; + boolean isExportStream; + private boolean isInMultiReader; + + ResultsReader(InputStream inputStream, boolean isInMultiReader) + throws IOException { + this.inputStream = inputStream; + isExportStream = inputStream instanceof ExportResultsStream; + this.isInMultiReader = isInMultiReader; + } + + /** + * Closes the reader and returns resources. + * + * @throws IOException On IO exception. + */ + public void close() throws IOException { + inputStream.close(); + } + + /** + * Returns the next event in the event stream. + * + * @return The map of key-value pairs for an event. + * The format of multi-item values is implementation-specific. + * We recommend using the methods from the + * {@link Event} class to interpret multi-item values. + * @throws IOException On IO exception. + */ + public final Event getNextEvent() throws IOException { + return getNextElement(); + } + + /** + * Returns an iterator over the events from this reader. + * @return an Iterator. + */ + @Override + public final Iterator<Event> iterator() { + return super.iterator(); + } + + /** + * Returns the next event while moving to the next set + * automatically when needed, such as concatenating final results + * across multiple sets. + * + * @return null {@code null} if the end is reached. + * @throws IOException On IO exception. + */ + final Event getNextElement() throws IOException { + Event event; + while (true) { + event = getNextEventInCurrentSet(); + + // If we actually managed to get an event, then we break and return it + if (event != null) + break; + + // We don't concatenate across previews across sets, since each set + // might be a snapshot at a given time or a summary result with + // partial data from a reporting search + // (for example "count by host"). So if this is a preview, + // break. Null return indicating the end of the set. + if (isPreview) + break; + + // If we did not advance to next set, i.e. the end of stream is + // reached, break. Null return indicating the end of the set. + if (!advanceStreamToNextSet()) + break; + + // We have advanced to the next set. isPreview is for that set. + // It should not be a preview. Splunk should never return a preview + // after final results which we might have concatenated together + // across sets. + assert (!isPreview) : + "Preview result set should never be after a final set."; + } + return event; + } + + /* + * Get the next event in the current result set. Return null + * if the end is reached. + */ + abstract Event getNextEventInCurrentSet() throws IOException; + + /* + * Return false if the end is reached. + */ + final boolean resetIteratorToNextSet() throws IOException { + + // Get to the beginning of the next set in the stream + // skipping remaining event(s) if any in the current set. + boolean hasMoreResults = advanceStreamToNextSet(); + + // Reset the iterator so that it would either fetch a new + // element for the next iteration or stop. + resetIteration(hasMoreResults); + + return hasMoreResults; + } + + /* + * Return false if the end is reached. + */ + boolean advanceStreamToNextSet() throws IOException { + // Indicate that no more sets are available + // Subclasses can override this method to support + // MultiResultsReader. + return false; + } + + /* + * This method is used by constructors of result readers to do + * the following for single reader: + * 1. Obtain the preview flag and the field list. + * 2. Skip any previews for export. + */ + final void finishInitialization() throws IOException { + if (isInMultiReader) + return; + + while (true) { + // Stop if no more set is available + if (!advanceStreamToNextSet()) { + // Terminating the iteration. + // This avoids future callings into the underlying reader + // to get events, which may result in exceptions. + resetIteration(false); + break; + } + + // No skipping of result sets if the stream + // is not from an export endpoint. + if (!isExportStream) + break; + + // Skipping ends at any file results. + if (!isPreview) + break; + } + } +} diff --git a/splunk/src/main/java/com/splunk/ResultsReaderCsv.java b/splunk/src/main/java/com/splunk/ResultsReaderCsv.java index 64b3dec8..668de189 100644 --- a/splunk/src/main/java/com/splunk/ResultsReaderCsv.java +++ b/splunk/src/main/java/com/splunk/ResultsReaderCsv.java @@ -1,116 +1,116 @@ -/* - * 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 au.com.bytecode.opencsv.CSVReader; - -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; - -/** - * The {@code ResultsReaderCsv} class represents a streaming CSV reader for - * Splunk search results. This class requires the opencsv-2.3.jar file in your - * build path. - */ -public class ResultsReaderCsv extends ResultsReader { - - private CSVReader csvReader = null; - private List<String> keys; - - /** - * Class constructor. - * - * Constructs a streaming CSV reader for the event stream. You should only - * attempt to parse a CSV stream with this reader. If you attempt to parse - * a different type of stream, unpredictable results may occur. - * - * @param inputStream The CSV stream to parse. - * @throws IOException The IOException instance - */ - public ResultsReaderCsv(InputStream inputStream) throws IOException { - super(inputStream, false); - if (isExportStream) - throw new UnsupportedOperationException( - "A stream from an export endpoint is not supported " + - "by a CSV result reader. Use XML or JSON search output "+ - "format and matching reader instead." - ); - csvReader = new CSVReader(new InputStreamReader(inputStream, "UTF-8")); - // initial line contains the keyArray, except for oneshot -- which - // contains a blank line, and then the key list. - String[] keyArray = csvReader.readNext(); - if (keyArray.length == 1 && keyArray[0].trim().equals("")) { - keyArray = csvReader.readNext(); - } - keys = Arrays.asList(keyArray); - } - - /** {@inheritDoc} */ - @Override public void close() throws IOException { - super.close(); - if (csvReader != null) - csvReader.close(); - csvReader = null; - } - - /** - * This method is not supported. - * @return Not applicable. - */ - public boolean isPreview(){ - throw new UnsupportedOperationException( - "isPreview() is not supported by this subclass."); - } - - /** {@inheritDoc} */ - public Collection<String> getFields(){ - return keys; - } - - /* - * Multiple result sets are not supported by this reader. - * This function reads the entire stream. - * An application won't reach here with a stream from - * an /export endpoint. The constructor will throw an error in that case. - */ - @Override Event getNextEventInCurrentSet() throws IOException { - Event returnData = null; - String[] line; - - if ((line = csvReader.readNext()) != null) { - if (line.length == 1 && line[0].equals("")) { - line = csvReader.readNext(); - if (line == null) { - return returnData; - } - } - - returnData = new Event(); - int count = 0; - for (String key : keys) { - String delimitedValues = line[count++]; - returnData.putSingleOrDelimited(key, delimitedValues); - } - } - - return returnData; - } -} +/* + * 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 au.com.bytecode.opencsv.CSVReader; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +/** + * The {@code ResultsReaderCsv} class represents a streaming CSV reader for + * Splunk search results. This class requires the opencsv-2.3.jar file in your + * build path. + */ +public class ResultsReaderCsv extends ResultsReader { + + private CSVReader csvReader = null; + private List<String> keys; + + /** + * Class constructor. + * + * Constructs a streaming CSV reader for the event stream. You should only + * attempt to parse a CSV stream with this reader. If you attempt to parse + * a different type of stream, unpredictable results may occur. + * + * @param inputStream The CSV stream to parse. + * @throws IOException The IOException instance + */ + public ResultsReaderCsv(InputStream inputStream) throws IOException { + super(inputStream, false); + if (isExportStream) + throw new UnsupportedOperationException( + "A stream from an export endpoint is not supported " + + "by a CSV result reader. Use XML or JSON search output "+ + "format and matching reader instead." + ); + csvReader = new CSVReader(new InputStreamReader(inputStream, "UTF-8")); + // initial line contains the keyArray, except for oneshot -- which + // contains a blank line, and then the key list. + String[] keyArray = csvReader.readNext(); + if (keyArray.length == 1 && keyArray[0].trim().equals("")) { + keyArray = csvReader.readNext(); + } + keys = Arrays.asList(keyArray); + } + + /** {@inheritDoc} */ + @Override public void close() throws IOException { + super.close(); + if (csvReader != null) + csvReader.close(); + csvReader = null; + } + + /** + * This method is not supported. + * @return Not applicable. + */ + public boolean isPreview(){ + throw new UnsupportedOperationException( + "isPreview() is not supported by this subclass."); + } + + /** {@inheritDoc} */ + public Collection<String> getFields(){ + return keys; + } + + /* + * Multiple result sets are not supported by this reader. + * This function reads the entire stream. + * An application won't reach here with a stream from + * an /export endpoint. The constructor will throw an error in that case. + */ + @Override Event getNextEventInCurrentSet() throws IOException { + Event returnData = null; + String[] line; + + if ((line = csvReader.readNext()) != null) { + if (line.length == 1 && line[0].equals("")) { + line = csvReader.readNext(); + if (line == null) { + return returnData; + } + } + + returnData = new Event(); + int count = 0; + for (String key : keys) { + String delimitedValues = line[count++]; + returnData.putSingleOrDelimited(key, delimitedValues); + } + } + + return returnData; + } +} diff --git a/splunk/src/main/java/com/splunk/ResultsReaderJson.java b/splunk/src/main/java/com/splunk/ResultsReaderJson.java index 6544f614..e1760b21 100644 --- a/splunk/src/main/java/com/splunk/ResultsReaderJson.java +++ b/splunk/src/main/java/com/splunk/ResultsReaderJson.java @@ -1,356 +1,356 @@ -/* - * 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 com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonToken; - -import java.io.EOFException; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -/** - * The {@code ResultsReaderJson} class represents a streaming JSON reader for - * Splunk search results. This class requires the gson-2.1.jar file in your - * build path. If you want to access the preview events, use the - * {@link MultiResultsReaderJson} class. - */ -public class ResultsReaderJson extends ResultsReader { - private JsonReader jsonReader; - // Helper object that will only be constructed if the reader is handling - // json format used by export. - private ExportHelper exportHelper; - // Whether the 'preview' flag is read - private boolean previewFlagRead; - - /** - * Class constructor. - * - * Constructs a streaming JSON reader for the event stream. You should only - * attempt to parse a JSON stream with this reader. If you attempt to parse - * a different type of stream, unpredictable results may occur. - * - * @param inputStream The JSON stream to parse. - * @throws IOException The IOException instance - */ - public ResultsReaderJson(InputStream inputStream) throws IOException { - this(inputStream, false); - } - - ResultsReaderJson(InputStream inputStream, boolean isInMultiReader) - throws IOException { - super(inputStream, isInMultiReader); - jsonReader = new JsonReader(new InputStreamReader(inputStream, "UTF-8")); - // if stream is empty, return a null reader. - jsonReader.setLenient(true); - if (isExportStream || isInMultiReader) - exportHelper = new ExportHelper(); - finishInitialization(); - } - - // Advance in the json stream, reading meta data if available, and - // get ready for readEvent method. - // Return false if end of stream is encountered. - boolean advanceIntoNextSetBeforeEvent() throws IOException { - // jsonReader will be set to null once the end is reached. - if (jsonReader == null) - return false; - - // In Splunk 5.0 from the export endpoint, - // each result is in its own top level object. - // In Splunk 5.0 not from the export endpoint, the results are - // an array at that object's key "results". - // In Splunk 4.3, the - // array was the top level returned. So if we find an object - // at top level, we step into it until we find the right key, - // then leave it in that state to iterate over. - try { - // Json single-reader depends on 'isExport' flag to function. - // It does not support a stream from a file saved from - // a stream from an export endpoint. - // Json multi-reader assumes export format thus does not support - // a stream from none export endpoints. - if (exportHelper != null) { - if (jsonReader.peek() == JsonToken.BEGIN_ARRAY) - throw new UnsupportedOperationException( - "A stream from an export endpoint of " + - "a Splunk 4.x server in the JSON output format " + - "is not supported by this class. " + - "Use the XML search output format, " + - "and an XML result reader instead."); - /* - * We're on a stream from an export endpoint - * Below is an example of an input stream. - * {"preview":true,"offset":0,"lastrow":true,"result":{"host":"Andy-PC","count":"62"}} - * {"preview":true,"offset":0,"result":{"host":"Andy-PC","count":"1682"}} - */ - // Read into first result object of the next set. - while (true) { - boolean endPassed = exportHelper.lastRow; - exportHelper.skipRestOfRow(); - if (!exportHelper.readIntoRow()) - return false; - if (endPassed) - break; - } - return true; - } - // Single-reader not from an export endpoint - if (jsonReader.peek() == JsonToken.BEGIN_OBJECT) { - /* - * We're on Splunk 5 with a single-reader not from - * an export endpoint - * Below is an example of an input stream. - * {"preview":false,"init_offset":0,"messages":[{"type":"DEBUG","text":"base lispy: [ AND index::_internal ]"},{"type":"DEBUG","text":"search context: user=\"admin\", app=\"search\", bs-pathname=\"/Users/fross/splunks/splunk-5.0/etc\""}],"results":[{"sum(kb)":"14372242.758775","series":"twitter"},{"sum(kb)":"267802.333926","series":"splunkd"},{"sum(kb)":"5979.036338","series":"splunkd_access"}]} - */ - jsonReader.beginObject(); - String key; - while (true) { - key = jsonReader.nextName(); - if (key.equals("preview")) - readPreviewFlag(); - else if (key.equals("results")) { - jsonReader.beginArray(); - return true; - } else { - skipEntity(); - } - } - } else { // We're on Splunk 4.x, and we just need to start the array. - /* - * Below is an example of an input stream - * [ - * { - * "sum(kb)":"14372242.758775", - * "series":"twitter" - * }, - * { - * "sum(kb)":"267802.333926", - * "series":"splunkd" - * }, - * { - * "sum(kb)":"5979.036338", - * "series":"splunkd_access" - * } - * ] - */ - jsonReader.beginArray(); - return true; - } - } catch (EOFException e) { - return false; - } - } - - private void readPreviewFlag() throws IOException { - isPreview = jsonReader.nextBoolean(); - previewFlagRead = true; - } - - /** - * Skip the next value, whether it is atomic or compound, in the JSON - * stream. - */ - private void skipEntity() throws IOException { - if (jsonReader.peek() == JsonToken.STRING) { - jsonReader.nextString(); - } else if (jsonReader.peek() == JsonToken.BOOLEAN) { - jsonReader.nextBoolean(); - } else if (jsonReader.peek() == JsonToken.NUMBER) { - jsonReader.nextDouble(); - } else if (jsonReader.peek() == JsonToken.NULL) { - jsonReader.nextNull(); - } else if (jsonReader.peek() == JsonToken.NAME) { - jsonReader.nextName(); - } else if (jsonReader.peek() == JsonToken.BEGIN_ARRAY) { - jsonReader.beginArray(); - while (jsonReader.peek() != JsonToken.END_ARRAY) { - skipEntity(); - } - jsonReader.endArray(); - } else if (jsonReader.peek() == JsonToken.BEGIN_OBJECT) { - jsonReader.beginObject(); - while (jsonReader.peek() != JsonToken.END_OBJECT) { - skipEntity(); - } - jsonReader.endObject(); - } - } - - /** {@inheritDoc} */ - @Override public void close() throws IOException { - super.close(); - if (jsonReader != null) - jsonReader.close(); - jsonReader = null; - } - - /** {@inheritDoc} */ - public boolean isPreview(){ - if (!previewFlagRead) - throw new UnsupportedOperationException( - "isPreview() is not supported " + - "with a stream from a Splunk 4.x server by this class. " + - "Use the XML format and an XML result reader instead."); - return isPreview; - } - - /** - * This method is not supported. - * @return Not applicable. - */ - public Collection<String> getFields(){ - throw new UnsupportedOperationException( - "getFields() is not supported by this subclass."); - } - - @Override Event getNextEventInCurrentSet() throws IOException { - if (exportHelper != null) { - // If the last row has been passed and moveToNextStreamPosition - // has not been called, end the current set. - if (exportHelper.lastRow && !exportHelper.inRow ) { - return null; - } - exportHelper.readIntoRow(); - } - - Event returnData = readEvent(); - - if (exportHelper != null) { - exportHelper.skipRestOfRow(); - return returnData; - } - // Single reader not from export - if (returnData == null) - close(); - return returnData; - } - - private Event readEvent() throws IOException { - Event returnData = null; - String name = null; - List<String> values = new ArrayList<String>(); - - if (jsonReader == null) - return null; - - // Events are almost flat, so no need for a true general parser - // solution. But the Gson parser is a little unintuitive here. Nested - // objects, have their own relative notion of hasNext. This - // means that for every object or array start, hasNext() returns false - // and one must consume the closing (END) object to get back to the - // previous object. - while (jsonReader.hasNext()) { - if (returnData == null) { - returnData = new Event(); - } - if (jsonReader.peek() == JsonToken.BEGIN_OBJECT) { - jsonReader.beginObject(); - } - if (jsonReader.peek() == JsonToken.BEGIN_ARRAY) { - jsonReader.beginArray(); - // The Gson parser is a little unintuitive here. Nested objects, - // have their own relative notion of hasNext; when hasNext() - // is done, it is only for this array. - while (jsonReader.hasNext()) { - JsonToken jsonToken2 = jsonReader.peek(); - if (jsonToken2 == JsonToken.STRING) { - values.add(jsonReader.nextString()); - } - } - jsonReader.endArray(); - - String[] valuesArray = - values.toArray(new String[values.size()]); - returnData.putArray(name, valuesArray); - - values.clear(); - } - if (jsonReader.peek() == JsonToken.NAME) { - name = jsonReader.nextName(); - } - if (jsonReader.peek() == JsonToken.STRING) { - String delimitedValues = jsonReader.nextString(); - returnData.putSingleOrDelimited(name, delimitedValues); - } - if (jsonReader.peek() == JsonToken.END_OBJECT) { - jsonReader.endObject(); - break; - } - if (jsonReader.peek() == JsonToken.END_ARRAY) { - jsonReader.endArray(); - } - } - return returnData; - } - - @Override boolean advanceStreamToNextSet() throws IOException{ - return advanceIntoNextSetBeforeEvent(); - } - - /** - * Contains code only used for streams from the export endpoint. - */ - private class ExportHelper { - // Initial value must be true so that - // the first row is treated as the start of a new set. - boolean lastRow = true; - boolean inRow; - - ExportHelper() { } - - // Return false if end of stream is encountered. - private boolean readIntoRow() throws IOException { - if (inRow) - return true; - if (jsonReader.peek() == JsonToken.END_DOCUMENT) - return false; - inRow = true; - jsonReader.beginObject(); - // lastrow name and value pair does not appear if the row - // is not the last in the set. - lastRow = false; - while (jsonReader.hasNext()) { - String key = jsonReader.nextName(); - if (key.equals("preview")) { - readPreviewFlag(); - } else if (key.equals("lastrow")) { - lastRow = jsonReader.nextBoolean(); - } else if (key.equals("result")) { - return true; - } else { - skipEntity(); - } - } - return false; - } - - private void skipRestOfRow() throws IOException { - if (!inRow) - return; - inRow = false; - while (jsonReader.peek() != JsonToken.END_OBJECT) { - skipEntity(); - } - jsonReader.endObject(); - } - } -} +/* + * 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 com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; + +import java.io.EOFException; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * The {@code ResultsReaderJson} class represents a streaming JSON reader for + * Splunk search results. This class requires the gson-2.1.jar file in your + * build path. If you want to access the preview events, use the + * {@link MultiResultsReaderJson} class. + */ +public class ResultsReaderJson extends ResultsReader { + private JsonReader jsonReader; + // Helper object that will only be constructed if the reader is handling + // json format used by export. + private ExportHelper exportHelper; + // Whether the 'preview' flag is read + private boolean previewFlagRead; + + /** + * Class constructor. + * + * Constructs a streaming JSON reader for the event stream. You should only + * attempt to parse a JSON stream with this reader. If you attempt to parse + * a different type of stream, unpredictable results may occur. + * + * @param inputStream The JSON stream to parse. + * @throws IOException The IOException instance + */ + public ResultsReaderJson(InputStream inputStream) throws IOException { + this(inputStream, false); + } + + ResultsReaderJson(InputStream inputStream, boolean isInMultiReader) + throws IOException { + super(inputStream, isInMultiReader); + jsonReader = new JsonReader(new InputStreamReader(inputStream, "UTF-8")); + // if stream is empty, return a null reader. + jsonReader.setLenient(true); + if (isExportStream || isInMultiReader) + exportHelper = new ExportHelper(); + finishInitialization(); + } + + // Advance in the json stream, reading meta data if available, and + // get ready for readEvent method. + // Return false if end of stream is encountered. + boolean advanceIntoNextSetBeforeEvent() throws IOException { + // jsonReader will be set to null once the end is reached. + if (jsonReader == null) + return false; + + // In Splunk 5.0 from the export endpoint, + // each result is in its own top level object. + // In Splunk 5.0 not from the export endpoint, the results are + // an array at that object's key "results". + // In Splunk 4.3, the + // array was the top level returned. So if we find an object + // at top level, we step into it until we find the right key, + // then leave it in that state to iterate over. + try { + // Json single-reader depends on 'isExport' flag to function. + // It does not support a stream from a file saved from + // a stream from an export endpoint. + // Json multi-reader assumes export format thus does not support + // a stream from none export endpoints. + if (exportHelper != null) { + if (jsonReader.peek() == JsonToken.BEGIN_ARRAY) + throw new UnsupportedOperationException( + "A stream from an export endpoint of " + + "a Splunk 4.x server in the JSON output format " + + "is not supported by this class. " + + "Use the XML search output format, " + + "and an XML result reader instead."); + /* + * We're on a stream from an export endpoint + * Below is an example of an input stream. + * {"preview":true,"offset":0,"lastrow":true,"result":{"host":"Andy-PC","count":"62"}} + * {"preview":true,"offset":0,"result":{"host":"Andy-PC","count":"1682"}} + */ + // Read into first result object of the next set. + while (true) { + boolean endPassed = exportHelper.lastRow; + exportHelper.skipRestOfRow(); + if (!exportHelper.readIntoRow()) + return false; + if (endPassed) + break; + } + return true; + } + // Single-reader not from an export endpoint + if (jsonReader.peek() == JsonToken.BEGIN_OBJECT) { + /* + * We're on Splunk 5 with a single-reader not from + * an export endpoint + * Below is an example of an input stream. + * {"preview":false,"init_offset":0,"messages":[{"type":"DEBUG","text":"base lispy: [ AND index::_internal ]"},{"type":"DEBUG","text":"search context: user=\"admin\", app=\"search\", bs-pathname=\"/Users/fross/splunks/splunk-5.0/etc\""}],"results":[{"sum(kb)":"14372242.758775","series":"twitter"},{"sum(kb)":"267802.333926","series":"splunkd"},{"sum(kb)":"5979.036338","series":"splunkd_access"}]} + */ + jsonReader.beginObject(); + String key; + while (true) { + key = jsonReader.nextName(); + if (key.equals("preview")) + readPreviewFlag(); + else if (key.equals("results")) { + jsonReader.beginArray(); + return true; + } else { + skipEntity(); + } + } + } else { // We're on Splunk 4.x, and we just need to start the array. + /* + * Below is an example of an input stream + * [ + * { + * "sum(kb)":"14372242.758775", + * "series":"twitter" + * }, + * { + * "sum(kb)":"267802.333926", + * "series":"splunkd" + * }, + * { + * "sum(kb)":"5979.036338", + * "series":"splunkd_access" + * } + * ] + */ + jsonReader.beginArray(); + return true; + } + } catch (EOFException e) { + return false; + } + } + + private void readPreviewFlag() throws IOException { + isPreview = jsonReader.nextBoolean(); + previewFlagRead = true; + } + + /** + * Skip the next value, whether it is atomic or compound, in the JSON + * stream. + */ + private void skipEntity() throws IOException { + if (jsonReader.peek() == JsonToken.STRING) { + jsonReader.nextString(); + } else if (jsonReader.peek() == JsonToken.BOOLEAN) { + jsonReader.nextBoolean(); + } else if (jsonReader.peek() == JsonToken.NUMBER) { + jsonReader.nextDouble(); + } else if (jsonReader.peek() == JsonToken.NULL) { + jsonReader.nextNull(); + } else if (jsonReader.peek() == JsonToken.NAME) { + jsonReader.nextName(); + } else if (jsonReader.peek() == JsonToken.BEGIN_ARRAY) { + jsonReader.beginArray(); + while (jsonReader.peek() != JsonToken.END_ARRAY) { + skipEntity(); + } + jsonReader.endArray(); + } else if (jsonReader.peek() == JsonToken.BEGIN_OBJECT) { + jsonReader.beginObject(); + while (jsonReader.peek() != JsonToken.END_OBJECT) { + skipEntity(); + } + jsonReader.endObject(); + } + } + + /** {@inheritDoc} */ + @Override public void close() throws IOException { + super.close(); + if (jsonReader != null) + jsonReader.close(); + jsonReader = null; + } + + /** {@inheritDoc} */ + public boolean isPreview(){ + if (!previewFlagRead) + throw new UnsupportedOperationException( + "isPreview() is not supported " + + "with a stream from a Splunk 4.x server by this class. " + + "Use the XML format and an XML result reader instead."); + return isPreview; + } + + /** + * This method is not supported. + * @return Not applicable. + */ + public Collection<String> getFields(){ + throw new UnsupportedOperationException( + "getFields() is not supported by this subclass."); + } + + @Override Event getNextEventInCurrentSet() throws IOException { + if (exportHelper != null) { + // If the last row has been passed and moveToNextStreamPosition + // has not been called, end the current set. + if (exportHelper.lastRow && !exportHelper.inRow ) { + return null; + } + exportHelper.readIntoRow(); + } + + Event returnData = readEvent(); + + if (exportHelper != null) { + exportHelper.skipRestOfRow(); + return returnData; + } + // Single reader not from export + if (returnData == null) + close(); + return returnData; + } + + private Event readEvent() throws IOException { + Event returnData = null; + String name = null; + List<String> values = new ArrayList<>(); + + if (jsonReader == null) + return null; + + // Events are almost flat, so no need for a true general parser + // solution. But the Gson parser is a little unintuitive here. Nested + // objects, have their own relative notion of hasNext. This + // means that for every object or array start, hasNext() returns false + // and one must consume the closing (END) object to get back to the + // previous object. + while (jsonReader.hasNext()) { + if (returnData == null) { + returnData = new Event(); + } + if (jsonReader.peek() == JsonToken.BEGIN_OBJECT) { + jsonReader.beginObject(); + } + if (jsonReader.peek() == JsonToken.BEGIN_ARRAY) { + jsonReader.beginArray(); + // The Gson parser is a little unintuitive here. Nested objects, + // have their own relative notion of hasNext; when hasNext() + // is done, it is only for this array. + while (jsonReader.hasNext()) { + JsonToken jsonToken2 = jsonReader.peek(); + if (jsonToken2 == JsonToken.STRING) { + values.add(jsonReader.nextString()); + } + } + jsonReader.endArray(); + + String[] valuesArray = + values.toArray(new String[values.size()]); + returnData.putArray(name, valuesArray); + + values.clear(); + } + if (jsonReader.peek() == JsonToken.NAME) { + name = jsonReader.nextName(); + } + if (jsonReader.peek() == JsonToken.STRING) { + String delimitedValues = jsonReader.nextString(); + returnData.putSingleOrDelimited(name, delimitedValues); + } + if (jsonReader.peek() == JsonToken.END_OBJECT) { + jsonReader.endObject(); + break; + } + if (jsonReader.peek() == JsonToken.END_ARRAY) { + jsonReader.endArray(); + } + } + return returnData; + } + + @Override boolean advanceStreamToNextSet() throws IOException{ + return advanceIntoNextSetBeforeEvent(); + } + + /** + * Contains code only used for streams from the export endpoint. + */ + private class ExportHelper { + // Initial value must be true so that + // the first row is treated as the start of a new set. + boolean lastRow = true; + boolean inRow; + + ExportHelper() { } + + // Return false if end of stream is encountered. + private boolean readIntoRow() throws IOException { + if (inRow) + return true; + if (jsonReader.peek() == JsonToken.END_DOCUMENT) + return false; + inRow = true; + jsonReader.beginObject(); + // lastrow name and value pair does not appear if the row + // is not the last in the set. + lastRow = false; + while (jsonReader.hasNext()) { + String key = jsonReader.nextName(); + if (key.equals("preview")) { + readPreviewFlag(); + } else if (key.equals("lastrow")) { + lastRow = jsonReader.nextBoolean(); + } else if (key.equals("result")) { + return true; + } else { + skipEntity(); + } + } + return false; + } + + private void skipRestOfRow() throws IOException { + if (!inRow) + return; + inRow = false; + while (jsonReader.peek() != JsonToken.END_OBJECT) { + skipEntity(); + } + jsonReader.endObject(); + } + } +} diff --git a/splunk/src/main/java/com/splunk/ResultsReaderXml.java b/splunk/src/main/java/com/splunk/ResultsReaderXml.java index e242ff8e..dd22d3bf 100644 --- a/splunk/src/main/java/com/splunk/ResultsReaderXml.java +++ b/splunk/src/main/java/com/splunk/ResultsReaderXml.java @@ -1,428 +1,427 @@ -/* - * 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 javax.xml.namespace.QName; -import javax.xml.stream.*; -import javax.xml.stream.events.Attribute; -import javax.xml.stream.events.StartElement; -import javax.xml.stream.events.XMLEvent; -import java.io.*; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; - -/** - * The {@code ResultsReaderXml} class represents a streaming XML reader for - * Splunk search results. When a stream from an export search is passed to this - * reader, it skips any preview events in the stream. If you want to access the - * preview events, use the {@link MultiResultsReaderXml} class. - */ -public class ResultsReaderXml - extends ResultsReader { - - private XMLEventReader xmlReader = null; - private ArrayList<String> fields = new ArrayList<String>(); - private PushbackInputStream pushbackInputStream; - - /** - * Class constructor. - * - * Constructs a streaming XML reader for the event stream. You should only - * attempt to parse an XML stream with this reader. If you attempt to parse - * a different type of stream, unpredictable results may occur. - * <br> - * The pushback reader modifies export streams to generate non-strict XML - * at the beginning of the stream. The streaming reader ignores preview - * data, and only extracts finalized data. - * - * @param inputStream The XML stream to parse. - * @throws IOException The IOException instance - */ - public ResultsReaderXml(InputStream inputStream) throws IOException { - this(inputStream, false); - } - - ResultsReaderXml( - InputStream inputStream, - boolean isInMultiReader) - throws IOException { - super(inputStream, isInMultiReader); - - // We need to do read-ahead, so we have to use a PushbackInputStream for everything - // in this class. - this.pushbackInputStream = new PushbackInputStream(inputStream); - XMLInputFactory inputFactory = XMLInputFactory.newInstance(); - - int ch = this.pushbackInputStream.read(); - if (ch == -1) { - return; // Stream is empty. - } else { - ((PushbackInputStream)this.pushbackInputStream).unread(ch); - } - - inputFactory.setProperty(XMLInputFactory.IS_COALESCING, true); - try { - InputStream filteredStream = new InsertRootElementFilterInputStream(this.pushbackInputStream); - xmlReader = inputFactory.createXMLEventReader(filteredStream); - finishInitialization(); - } catch (XMLStreamException e) { - throw new RuntimeException(e); - } - } - - /** {@inheritDoc} */ - @Override public void close() throws IOException { - if (xmlReader != null) { - try { - xmlReader.close(); - } catch (XMLStreamException e) { - throw new RuntimeException(e); - } - } - xmlReader = null; - - super.close(); - } - - /** {@inheritDoc} */ - public boolean isPreview() { - return isPreview; - } - - /** {@inheritDoc} */ - public Collection<String> getFields() { - return fields; - } - - @Override Event getNextEventInCurrentSet() throws IOException { - // Handle empty stream or other cases where xmlReader is - // not constructed. - if (xmlReader == null) { - return null; - } - try { - Event event = null; - XMLEvent xmlEvent = readToStartOfElementAtSameLevelWithName("result"); - if (xmlEvent != null) { - event = getResultKVPairs(); - } - return event; - } catch (XMLStreamException e) { - throw new RuntimeException(e); - } - } - - // Reads the preview flag and field name list, and position in the middle of - // the result element for reading actual results later. - // Return value indicates whether the next 'results' element is found. - boolean readIntoNextResultsElement() - throws XMLStreamException, IOException { - XMLEvent xmlEvent = readToStartOfElementWithName("results"); - if (xmlEvent == null) { - return false; - } - - if (xmlEvent != null && - xmlEvent.asStartElement() - .getAttributeByName(QName.valueOf("preview")) - .getValue() - .equals("0") ){ - isPreview = false; - } else { - isPreview = true; - } - - // Read <meta> element. - final String meta = "meta"; - if (readToStartOfElementAtSameLevelWithName(meta) != null) { - readFieldOrderElement(); - readToEndElementWithName(meta); - } - return true; - } - - XMLEvent readToStartOfElementWithName(String elementName) - throws XMLStreamException { - while (xmlReader.hasNext()) { - XMLEvent xmlEvent = xmlReader.nextEvent(); - int eType = xmlEvent.getEventType(); - if (eType != XMLStreamConstants.START_ELEMENT){ - continue; - } - - StartElement startElement = xmlEvent.asStartElement(); - if(startElement - .getName() - .getLocalPart() - .equals(elementName)){ - return xmlEvent; - } - } - return null; - } - - void readToEndElementWithName(String elementName) throws XMLStreamException { - XMLEvent xmlEvent; - int eType; - - while (xmlReader.hasNext()) { - xmlEvent = xmlReader.nextEvent(); - eType = xmlEvent.getEventType(); - switch (eType) { - case XMLStreamConstants.START_ELEMENT: - break; - case XMLStreamConstants.END_ELEMENT: - if (xmlEvent.asEndElement() - .getName() - .getLocalPart() - .equals(elementName)) { - return; - } - break; - default: - break; - } - } - - throw new RuntimeException("End tag of " + elementName + " not found."); - } - - /** - * Reads to the next specified start element at the same level. The reader - * stops past that element if it is found. Otherwise, the reader stops - * before the end element of the current level. - * - * @param elementName The name of the start element. - * @return The start element, or {@code null} if not found. - * @throws XMLStreamException - */ - XMLEvent readToStartOfElementAtSameLevelWithName(String elementName) - throws XMLStreamException { - XMLEvent xmlEvent; - int eType; - int level = 0; - while (xmlReader.hasNext()) { - xmlEvent = xmlReader.peek(); - eType = xmlEvent.getEventType(); - switch (eType) { - case XMLStreamConstants.START_ELEMENT: - if (level++ > 0){ - break; - } - StartElement startElement = xmlEvent.asStartElement(); - if (startElement - .getName() - .getLocalPart() - .equals(elementName)) { - xmlReader.nextEvent(); - return xmlEvent; - } - break; - case XMLStreamConstants.END_ELEMENT: - if (level-- == 0) { - return null; - } - break; - default: - break; - } - xmlReader.nextEvent(); - } - - throw new RuntimeException("Parent end element not found:" + elementName); - } - - // At the end, move off the end element of 'fieldOrder' - private void readFieldOrderElement() - throws IOException, XMLStreamException { - XMLEvent xmlEvent; - int eType; - int level = 0; - - if (readToStartOfElementAtSameLevelWithName("fieldOrder") == null) - return; - - while (xmlReader.hasNext()) { - xmlEvent = xmlReader.nextEvent(); - eType = xmlEvent.getEventType(); - switch (eType) { - case XMLStreamConstants.START_ELEMENT: - level++; - break; - case XMLStreamConstants.END_ELEMENT: - if (xmlEvent.asEndElement() - .getName() - .getLocalPart() - .equals("fieldOrder")) { - return; - } - level--; - break; - case XMLStreamConstants.CHARACTERS: - if (level == 1) { - fields.add(xmlEvent.asCharacters().getData()); - } - break; - default: - break; - } - } - - throw new RuntimeException("End tag of fieldOrder not found."); - } - - // At the end, move off the end tag of 'result' - private Event getResultKVPairs() - throws IOException, XMLStreamException { - - Event returnData = new Event(); - XMLEvent xmlEvent; - int eType; - String key = null; - List<String> values = new ArrayList<String>(); - int level = 0; - - // Event results are flat, so extract k/v pairs based on XML indentation - // level throwing away the uninteresting non-data. - - while (xmlReader.hasNext()) { - xmlEvent = xmlReader.nextEvent(); - eType = xmlEvent.getEventType(); - switch (eType) { - case XMLStreamConstants.START_ELEMENT: - final StartElement startElement = xmlEvent.asStartElement(); - @SuppressWarnings("unchecked") - Iterator<Attribute> attrIttr = - startElement.getAttributes(); - if (level == 0) { - if (attrIttr.hasNext()) - key = attrIttr.next().getValue(); - } else if (level == 1 && - key.equals("_raw") && - startElement - .getName() - .getLocalPart() - .equals("v")) { - StringBuilder asString = new StringBuilder(); - StringWriter asXml = new StringWriter(); - readSubtree(startElement, asString, asXml); - values.add(asString.toString()); - returnData.putSegmentedRaw(asXml.toString()); - level--; - } - level++; - break; - case XMLStreamConstants.END_ELEMENT: - if (xmlEvent.asEndElement() - .getName() - .getLocalPart() - .equals("result")) - return returnData; - - if (--level == 0) { - String[] valuesArray = - values.toArray(new String[values.size()]); - returnData.putArray(key, valuesArray); - - key = null; - values.clear(); - } - break; - case XMLStreamConstants.CHARACTERS: - if (level > 1) { - values.add(xmlEvent.asCharacters().getData()); - } - break; - default: - break; - } - } - - throw new RuntimeException("End tag of 'result' not found."); - } - - @Override boolean advanceStreamToNextSet() throws IOException { - // Handle empty stream or other cases where xmlReader is - // not constructed. - if (xmlReader == null) { - return false; - } - try { - return readIntoNextResultsElement(); - } catch (XMLStreamException e) { - throw new RuntimeException(e); - } catch (NullPointerException e) { - // Invalid xml (<doc> and multiple <results> may results in - // this exception in the xml reader with JDK 1.7 at: - // com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.load(XMLEntityScanner.java:1748) - return false; - } catch (ArrayIndexOutOfBoundsException e) { - // Invalid xml (<doc> and multiple <results> may results in - // this exception in the xml reader with JDK 1.6 at: - // com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.endEntity(XMLDocumentFragmentScannerImpl.java:904) - return false; - } - } - - /** - * Read the whole element including those contained in the outer element. - * @param startElement start element (tag) of the outer element. - * @param asString output builder that the element's inner-text - * will be appended to, with markup removed and - * characters un-escaped - * @param asXml output builder that full xml including markups - * will be appended to. Characters are escaped as - * needed. - * @throws IOException - * @throws XMLStreamException - */ - void readSubtree( - StartElement startElement, - StringBuilder asString, - StringWriter asXml) - throws IOException, XMLStreamException { - XMLEventWriter xmlWriter = XMLOutputFactory.newInstance(). - createXMLEventWriter(asXml); - XMLEvent xmlEvent = startElement; - int level = 0; - do { - xmlWriter.add(xmlEvent); - int eType = xmlEvent.getEventType(); - switch (eType) { - case XMLStreamConstants.START_ELEMENT: - level++; - break; - case XMLStreamConstants.END_ELEMENT: - if (--level == 0) { - xmlWriter.close(); - return; - } - break; - case XMLStreamConstants.CHARACTERS: - asString.append(xmlEvent.asCharacters().getData()); - default: - break; - } - xmlEvent = xmlReader.nextEvent(); - } while (xmlReader.hasNext()); - throw new RuntimeException("Invalid XML format."); - } -} - +/* + * 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 javax.xml.namespace.QName; +import javax.xml.stream.*; +import javax.xml.stream.events.Attribute; +import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; +import java.io.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; + +/** + * The {@code ResultsReaderXml} class represents a streaming XML reader for + * Splunk search results. When a stream from an export search is passed to this + * reader, it skips any preview events in the stream. If you want to access the + * preview events, use the {@link MultiResultsReaderXml} class. + */ +public class ResultsReaderXml + extends ResultsReader { + + private XMLEventReader xmlReader = null; + private ArrayList<String> fields = new ArrayList<>(); + private PushbackInputStream pushbackInputStream; + + /** + * Class constructor. + * + * Constructs a streaming XML reader for the event stream. You should only + * attempt to parse an XML stream with this reader. If you attempt to parse + * a different type of stream, unpredictable results may occur. + * <br> + * The pushback reader modifies export streams to generate non-strict XML + * at the beginning of the stream. The streaming reader ignores preview + * data, and only extracts finalized data. + * + * @param inputStream The XML stream to parse. + * @throws IOException The IOException instance + */ + public ResultsReaderXml(InputStream inputStream) throws IOException { + this(inputStream, false); + } + + ResultsReaderXml( + InputStream inputStream, + boolean isInMultiReader) + throws IOException { + super(inputStream, isInMultiReader); + + // We need to do read-ahead, so we have to use a PushbackInputStream for everything + // in this class. + this.pushbackInputStream = new PushbackInputStream(inputStream); + XMLInputFactory inputFactory = XMLInputFactory.newInstance(); + + int ch = this.pushbackInputStream.read(); + if (ch == -1) { + return; // Stream is empty. + } else { + ((PushbackInputStream)this.pushbackInputStream).unread(ch); + } + + inputFactory.setProperty(XMLInputFactory.IS_COALESCING, true); + try { + InputStream filteredStream = new InsertRootElementFilterInputStream(this.pushbackInputStream); + xmlReader = inputFactory.createXMLEventReader(filteredStream); + finishInitialization(); + } catch (XMLStreamException e) { + throw new RuntimeException(e); + } + } + + /** {@inheritDoc} */ + @Override public void close() throws IOException { + if (xmlReader != null) { + try { + xmlReader.close(); + } catch (XMLStreamException e) { + throw new RuntimeException(e); + } + } + xmlReader = null; + + super.close(); + } + + /** {@inheritDoc} */ + public boolean isPreview() { + return isPreview; + } + + /** {@inheritDoc} */ + public Collection<String> getFields() { + return fields; + } + + @Override Event getNextEventInCurrentSet() throws IOException { + // Handle empty stream or other cases where xmlReader is + // not constructed. + if (xmlReader == null) { + return null; + } + try { + Event event = null; + XMLEvent xmlEvent = readToStartOfElementAtSameLevelWithName("result"); + if (xmlEvent != null) { + event = getResultKVPairs(); + } + return event; + } catch (XMLStreamException e) { + throw new RuntimeException(e); + } + } + + // Reads the preview flag and field name list, and position in the middle of + // the result element for reading actual results later. + // Return value indicates whether the next 'results' element is found. + boolean readIntoNextResultsElement() + throws XMLStreamException, IOException { + XMLEvent xmlEvent = readToStartOfElementWithName("results"); + if (xmlEvent == null) { + return false; + } + + if (xmlEvent != null && + xmlEvent.asStartElement() + .getAttributeByName(QName.valueOf("preview")) + .getValue() + .equals("0") ){ + isPreview = false; + } else { + isPreview = true; + } + + // Read <meta> element. + final String meta = "meta"; + if (readToStartOfElementAtSameLevelWithName(meta) != null) { + readFieldOrderElement(); + readToEndElementWithName(meta); + } + return true; + } + + XMLEvent readToStartOfElementWithName(String elementName) + throws XMLStreamException { + while (xmlReader.hasNext()) { + XMLEvent xmlEvent = xmlReader.nextEvent(); + int eType = xmlEvent.getEventType(); + if (eType != XMLStreamConstants.START_ELEMENT){ + continue; + } + + StartElement startElement = xmlEvent.asStartElement(); + if(startElement + .getName() + .getLocalPart() + .equals(elementName)){ + return xmlEvent; + } + } + return null; + } + + void readToEndElementWithName(String elementName) throws XMLStreamException { + XMLEvent xmlEvent; + int eType; + + while (xmlReader.hasNext()) { + xmlEvent = xmlReader.nextEvent(); + eType = xmlEvent.getEventType(); + switch (eType) { + case XMLStreamConstants.START_ELEMENT: + break; + case XMLStreamConstants.END_ELEMENT: + if (xmlEvent.asEndElement() + .getName() + .getLocalPart() + .equals(elementName)) { + return; + } + break; + default: + break; + } + } + + throw new RuntimeException("End tag of " + elementName + " not found."); + } + + /** + * Reads to the next specified start element at the same level. The reader + * stops past that element if it is found. Otherwise, the reader stops + * before the end element of the current level. + * + * @param elementName The name of the start element. + * @return The start element, or {@code null} if not found. + * @throws XMLStreamException + */ + XMLEvent readToStartOfElementAtSameLevelWithName(String elementName) + throws XMLStreamException { + XMLEvent xmlEvent; + int eType; + int level = 0; + while (xmlReader.hasNext()) { + xmlEvent = xmlReader.peek(); + eType = xmlEvent.getEventType(); + switch (eType) { + case XMLStreamConstants.START_ELEMENT: + if (level++ > 0){ + break; + } + StartElement startElement = xmlEvent.asStartElement(); + if (startElement + .getName() + .getLocalPart() + .equals(elementName)) { + xmlReader.nextEvent(); + return xmlEvent; + } + break; + case XMLStreamConstants.END_ELEMENT: + if (level-- == 0) { + return null; + } + break; + default: + break; + } + xmlReader.nextEvent(); + } + + throw new RuntimeException("Parent end element not found:" + elementName); + } + + // At the end, move off the end element of 'fieldOrder' + private void readFieldOrderElement() + throws IOException, XMLStreamException { + XMLEvent xmlEvent; + int eType; + int level = 0; + + if (readToStartOfElementAtSameLevelWithName("fieldOrder") == null) + return; + + while (xmlReader.hasNext()) { + xmlEvent = xmlReader.nextEvent(); + eType = xmlEvent.getEventType(); + switch (eType) { + case XMLStreamConstants.START_ELEMENT: + level++; + break; + case XMLStreamConstants.END_ELEMENT: + if (xmlEvent.asEndElement() + .getName() + .getLocalPart() + .equals("fieldOrder")) { + return; + } + level--; + break; + case XMLStreamConstants.CHARACTERS: + if (level == 1) { + fields.add(xmlEvent.asCharacters().getData()); + } + break; + default: + break; + } + } + + throw new RuntimeException("End tag of fieldOrder not found."); + } + + // At the end, move off the end tag of 'result' + private Event getResultKVPairs() + throws IOException, XMLStreamException { + + Event returnData = new Event(); + XMLEvent xmlEvent; + int eType; + String key = null; + List<String> values = new ArrayList<>(); + int level = 0; + + // Event results are flat, so extract k/v pairs based on XML indentation + // level throwing away the uninteresting non-data. + + while (xmlReader.hasNext()) { + xmlEvent = xmlReader.nextEvent(); + eType = xmlEvent.getEventType(); + switch (eType) { + case XMLStreamConstants.START_ELEMENT: + final StartElement startElement = xmlEvent.asStartElement(); + @SuppressWarnings("unchecked") + Iterator<Attribute> attrIttr = + startElement.getAttributes(); + if (level == 0) { + if (attrIttr.hasNext()) + key = attrIttr.next().getValue(); + } else if (level == 1 && + key.equals("_raw") && + startElement + .getName() + .getLocalPart() + .equals("v")) { + StringBuilder asString = new StringBuilder(); + StringWriter asXml = new StringWriter(); + readSubtree(startElement, asString, asXml); + values.add(asString.toString()); + returnData.putSegmentedRaw(asXml.toString()); + level--; + } + level++; + break; + case XMLStreamConstants.END_ELEMENT: + if (xmlEvent.asEndElement() + .getName() + .getLocalPart() + .equals("result")) + return returnData; + + if (--level == 0) { + String[] valuesArray = + values.toArray(new String[values.size()]); + returnData.putArray(key, valuesArray); + + key = null; + values.clear(); + } + break; + case XMLStreamConstants.CHARACTERS: + if (level > 1) { + values.add(xmlEvent.asCharacters().getData()); + } + break; + default: + break; + } + } + + throw new RuntimeException("End tag of 'result' not found."); + } + + @Override boolean advanceStreamToNextSet() throws IOException { + // Handle empty stream or other cases where xmlReader is + // not constructed. + if (xmlReader == null) { + return false; + } + try { + return readIntoNextResultsElement(); + } catch (XMLStreamException e) { + throw new RuntimeException(e); + } catch (NullPointerException e) { + // Invalid xml (<doc> and multiple <results> may results in + // this exception in the xml reader with JDK 1.7 at: + // com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.load(XMLEntityScanner.java:1748) + return false; + } catch (ArrayIndexOutOfBoundsException e) { + // Invalid xml (<doc> and multiple <results> may results in + // this exception in the xml reader with JDK 1.6 at: + // com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.endEntity(XMLDocumentFragmentScannerImpl.java:904) + return false; + } + } + + /** + * Read the whole element including those contained in the outer element. + * @param startElement start element (tag) of the outer element. + * @param asString output builder that the element's inner-text + * will be appended to, with markup removed and + * characters un-escaped + * @param asXml output builder that full xml including markups + * will be appended to. Characters are escaped as + * needed. + * @throws IOException + * @throws XMLStreamException + */ + void readSubtree( + StartElement startElement, + StringBuilder asString, + StringWriter asXml) + throws IOException, XMLStreamException { + XMLEventWriter xmlWriter = XMLOutputFactory.newInstance(). + createXMLEventWriter(asXml); + XMLEvent xmlEvent = startElement; + int level = 0; + do { + xmlWriter.add(xmlEvent); + int eType = xmlEvent.getEventType(); + switch (eType) { + case XMLStreamConstants.START_ELEMENT: + level++; + break; + case XMLStreamConstants.END_ELEMENT: + if (--level == 0) { + xmlWriter.close(); + return; + } + break; + case XMLStreamConstants.CHARACTERS: + asString.append(xmlEvent.asCharacters().getData()); + default: + break; + } + xmlEvent = xmlReader.nextEvent(); + } while (xmlReader.hasNext()); + throw new RuntimeException("Invalid XML format."); + } +} + diff --git a/splunk/src/main/java/com/splunk/SavedSearchCollectionArgs.java b/splunk/src/main/java/com/splunk/SavedSearchCollectionArgs.java index d846e19d..cdb62914 100644 --- a/splunk/src/main/java/com/splunk/SavedSearchCollectionArgs.java +++ b/splunk/src/main/java/com/splunk/SavedSearchCollectionArgs.java @@ -1,53 +1,53 @@ -/* - * 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; - -/** - * The {@code SavedSearchCollectionArgs} class contains arguments getting a - * collection of saved searches. - */ -public class SavedSearchCollectionArgs extends CollectionArgs { - - /** - * Class constructor. - */ - public SavedSearchCollectionArgs() { super(); } - - /* BEGIN AUTOGENERATED CODE */ - - /** - * Sets the earliest time for which to display the scheduled times for scheduled searches (not just the next run time). - * - * @param earliestTime - * The earliest time. - */ - public void setEarliestTime(String earliestTime) { - this.put("earliest_time", earliestTime); - } - - /** - * Sets the latest time until which to display the scheduled times for scheduled searches (not just the next run time). - * - * @param latestTime - * The latest time. - */ - public void setLatestTime(String latestTime) { - this.put("latest_time", latestTime); - } - - /* END AUTOGENERATED CODE */ -} +/* + * 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; + +/** + * The {@code SavedSearchCollectionArgs} class contains arguments getting a + * collection of saved searches. + */ +public class SavedSearchCollectionArgs extends CollectionArgs { + + /** + * Class constructor. + */ + public SavedSearchCollectionArgs() { super(); } + + /* BEGIN AUTOGENERATED CODE */ + + /** + * Sets the earliest time for which to display the scheduled times for scheduled searches (not just the next run time). + * + * @param earliestTime + * The earliest time. + */ + public void setEarliestTime(String earliestTime) { + this.put("earliest_time", earliestTime); + } + + /** + * Sets the latest time until which to display the scheduled times for scheduled searches (not just the next run time). + * + * @param latestTime + * The latest time. + */ + public void setLatestTime(String latestTime) { + this.put("latest_time", latestTime); + } + + /* END AUTOGENERATED CODE */ +} diff --git a/splunk/src/main/java/com/splunk/SearchResults.java b/splunk/src/main/java/com/splunk/SearchResults.java index 0dfa6060..1feeb85f 100644 --- a/splunk/src/main/java/com/splunk/SearchResults.java +++ b/splunk/src/main/java/com/splunk/SearchResults.java @@ -1,38 +1,38 @@ -/* - * 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.Collection; - -/** - * The {@code SearchResults} interface represents Splunk search results. - */ -public interface SearchResults extends Iterable<Event> { - /** - * Indicates whether the results are a preview from an unfinished search. - * @return {@code true} if the results are a preview, {@code false} if not. - */ - public boolean isPreview(); - - /** - * Returns a collection of field names from the results. - * @return A collection of field names. - * <p> - * Note that any given result will contain a subset of these fields. - */ - public Collection<String> getFields(); -} +/* + * 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.Collection; + +/** + * The {@code SearchResults} interface represents Splunk search results. + */ +public interface SearchResults extends Iterable<Event> { + /** + * Indicates whether the results are a preview from an unfinished search. + * @return {@code true} if the results are a preview, {@code false} if not. + */ + public boolean isPreview(); + + /** + * Returns a collection of field names from the results. + * @return A collection of field names. + * <p> + * Note that any given result will contain a subset of these fields. + */ + public Collection<String> getFields(); +} diff --git a/splunk/src/main/java/com/splunk/Service.java b/splunk/src/main/java/com/splunk/Service.java index 3af59b62..c8087070 100644 --- a/splunk/src/main/java/com/splunk/Service.java +++ b/splunk/src/main/java/com/splunk/Service.java @@ -1,1481 +1,1477 @@ -/* - * 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.io.IOException; -import java.io.InputStream; -import java.io.UnsupportedEncodingException; -import java.net.*; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -/** - * The {@code Service} class represents a Splunk service instance at a given - * address (host:port), accessed using the {@code http} or {@code https} - * protocol scheme. - * <p> - * A {@code Service} instance also captures an optional namespace context - * consisting of an optional owner name (or "-" wildcard) and optional app name - * (or "-" wildcard). - * <p> - * To access {@code Service} members, the {@code Service} instance must be - * authenticated by presenting credentials using the {@code login} method, or - * by constructing the {@code Service} instance using the {@code connect} - * method, which both creates and authenticates the instance. - */ -public class Service extends BaseService { - /** The current app context. */ - protected String app = null; - - /** The current session token. */ - protected String token = null; - - /** The current owner context. A value of "nobody" means that all users - * have access to the resource. - */ - protected String owner = null; - - /** The Splunk account username, which is used to authenticate the Splunk - * instance. */ - protected String username = null; - - /** The password, which is used to authenticate the Splunk instance. */ - protected String password = null; - - /** The default simple receiver endpoint. */ - protected String simpleReceiverEndPoint = "/services/receivers/simple"; - - /** The default password endpoint, can change over Splunk versions. */ - protected String passwordEndPoint = "admin/passwords"; - - /** The version of this Splunk instance, once logged in. */ - public String version = null; - - /** The type of this Splunk instance, once logged in. */ - public String instanceType = null; - - /** The default host name, which is used when a host name is not provided.*/ - public static String DEFAULT_HOST = "localhost"; - - /** The default port number, which is used when a port number is not - * provided. */ - public static int DEFAULT_PORT = 8089; - - /** The default scheme, which is used when a scheme is not provided. */ - public static String DEFAULT_SCHEME = "https"; - - /** Flag to notify SDK to try for re-login if the session has expired API call*/ - protected boolean autologin = false; - - /** - * Creates a new {@code Service} instance using a host. - * - * @param host The host name. - */ - public Service(String host) { - super(host); - } - - /** - * Creates a new {@code Service} instance using a host and port. - * - * @param host The host name. - * @param port The port number. - */ - public Service(String host, int port) { - super(host, port); - } - - /** - * Creates a new {@code Service} instance using a host, port, and - * scheme for accessing the service ({@code http} or {@code https}). - * - * @param host The host name. - * @param port The port number. - * @param scheme The scheme ({@code http} or {@code https}). - */ - public Service(String host, int port, String scheme) { - super(host, port, scheme); - } - - /** - * Constructs a new {@code Service} instance using the given host, - * port, and scheme, and instructing it to use the specified HTTPS handler. - * - * @param host The host name of the service. - * @param port The port number of the service. - * @param scheme Scheme for accessing the service ({@code http} or - * {@code https}). - * @param httpsHandler The URLStreamHandler instance - */ - public Service(String host, int port, String scheme, - URLStreamHandler httpsHandler) { - this.host = host; - this.port = port; - this.scheme = scheme; - this.httpsHandler = httpsHandler; - } - - /** - * Creates a new {@code Service} instance using a collection of arguments. - * - * @param args The {@code ServiceArgs} to initialize the service. - */ - // NOTE: This overload exists primarily to provide better documentation - // for the "args" parameter. - @SuppressWarnings("deprecation") - public Service(ServiceArgs args) { - super(); - // NOTE: Must read the deprecated fields for backward compatibility. - // (Consider the case where the fields are initialized directly, - // rather than using the new setters.) - // NOTE: Must also read the underlying dictionary for forward compatibility. - // (Consider the case where the user calls Map.put() directly, - // rather than using the new setters.) - this.app = Args.<String>get(args, "app", args.app != null ? args.app : null); - this.host = Args.<String>get(args, "host", args.host != null ? args.host : DEFAULT_HOST); - this.owner = Args.<String>get(args, "owner", args.owner != null ? args.owner : null); - this.port = Args.<Integer>get(args, "port", args.port != null ? args.port : DEFAULT_PORT); - this.scheme = Args.<String>get(args, "scheme", args.scheme != null ? args.scheme : DEFAULT_SCHEME); - this.token = Args.<String>get(args, "token", args.token != null ? args.token : null); - this.username = (String)args.get("username"); - this.password = (String)args.get("password"); - this.autologin = Args.<Boolean>get(args, "autologin", false); - this.httpsHandler = Args.<URLStreamHandler>get(args, "httpsHandler", null); - this.setSslSecurityProtocol(Args.get(args, "SSLSecurityProtocol", Service.getSslSecurityProtocol())); - this.addCookie((String)args.get("cookie")); - this.setCustomHeaders((Map<String, String>) args.get("customHeaders")); - } - - /** - * Creates a new {@code Service} instance using a map of arguments. - * - * @param args A {@code Map} of arguments to initialize the service. - */ - public Service(Map<String, Object> args) { - super(); - this.app = Args.<String>get(args, "app", null); - this.host = Args.<String>get(args, "host", DEFAULT_HOST); - this.owner = Args.<String>get(args, "owner", null); - this.port = Args.<Integer>get(args, "port", DEFAULT_PORT); - this.scheme = Args.<String>get(args, "scheme", DEFAULT_SCHEME); - this.token = Args.<String>get(args, "token", null); - this.username = (String)args.get("username"); - this.password = (String)args.get("password"); - this.autologin = Args.<Boolean>get(args, "autologin", false); - this.httpsHandler = Args.<URLStreamHandler>get(args, "httpsHandler", null); - this.setSslSecurityProtocol(Args.get(args, "SSLSecurityProtocol", Service.getSslSecurityProtocol())); - this.addCookie((String)args.get("cookie")); - this.connectTimeout = Args.<Integer>get(args, "connectTimeout", null); - this.readTimeout = Args.<Integer>get(args, "readTimeout", null); - } - - /** - * Establishes a connection to a Splunk service using a map of arguments. - * This member creates a new {@code Service} instance and authenticates - * the session using credentials passed in from the {@code args} map. - * - * @param args The {@code args} map. - * @return A new {@code Service} instance. - */ - public static Service connect(Map<String, Object> args) { - Service service = new Service(args); - if (args.containsKey("username")) { - service.login(); - } - return service; - } - - /** - * Runs an export search (using the {@code search/jobs/export} endpoint), - * and streams results back in an input stream. - * - * @param search The search query to run. - * @return The {@code InputStream} object that contains the search results. - */ - public InputStream export(String search) { - return export(search, null); - } - - /** - * Runs an export search with arguments (using the {@code search/jobs/export} - * endpoint), and streams results back in an input stream. - * - * @param search The search query to run. - * @param args Additional search arguments. - * For a list of possible parameters, see - * <a href="http://dev.splunk.com/view/SP-CAAAEHQ#savedsearchparams" - * target="_blank">Saved search parameters</a> on - * <a href="http://dev.splunk.com/view/SP-CAAAEHQ" - * target="_blank">dev.splunk.com</a>. - * @return The {@code InputStream} object that contains the search results. - */ - public InputStream export(String search, Map args) { - args = Args.create(args).add("search", search); - // By default don't highlight search terms in the output. - if (!args.containsKey("segmentation")) { - args.put("segmentation", "none"); - } - ResponseMessage response; - - if(enableV2SearchApi()) - response = post(JobCollection.REST_PATH_V2 + "/export", args); - else { - response = post(JobCollection.REST_PATH + "/export", args); - } - return new ExportResultsStream(response.getContent()); - } - - /** - * Runs an export search with arguments (using the {@code search/jobs/export} - * endpoint), and streams results back in an input stream. - * - * @param search The search query to run. - * @param args Additional search arguments (see {@code JobExportArgs}). - * @return The {@code InputStream} object that contains the search results. - */ - // NOTE: This overload exists primarily to provide better documentation - // for the "args" parameter. - public InputStream export(String search, JobExportArgs args) { - return export(search, (Map<String, Object>) args); - } - - /** - * Ensures that the given path is fully qualified, prepending a path - * prefix if necessary. The path prefix is constructed using the current - * owner and app context when available. - * - * @param path The path to verify. - * @return A fully-qualified resource path. - */ - String fullpath(String path) { - return fullpath(path, null); - } - - /** - * Ensures that a given path is fully qualified, prepending a path - * prefix if necessary. The path prefix is constructed using the - * current owner and app context when available. - * - * @param path The path to verify. - * @param namespace The namespace dictionary (<i>app, owner, sharing</i>). - * @return A fully-qualified resource path. - */ - public String fullpath(String path, Args namespace) { - - // if already fully qualified (i.e. root begins with /) then return - // the already qualified path. - if (path.startsWith("/")) - return path; - - // if no namespace at all, and no service instance of app, and no - // sharing, return base service endpoint + path. - if (namespace == null && app == null) { - return "/services/" + path; - } - - // base namespace values - String localApp = app; - String localOwner = owner; - String localSharing = ""; - - // override with invocation namespace if set. - if (namespace != null) { - // URL encode the owner and app. - if (namespace.containsKey("app")) { - try { - localApp = URLEncoder.encode((String)namespace.get("app"), "UTF-8"); - } catch (UnsupportedEncodingException e) { - // This is unreachable, since UTF-8 is always supported. - assert false; - } - } - if (namespace.containsKey("owner")) { - try { - localOwner = URLEncoder.encode((String)namespace.get("owner"), "UTF-8"); - } catch (UnsupportedEncodingException e) { - // This is unreachable, since UTF-8 is always supported. - assert false; - } - } - if (namespace.containsKey("sharing")) { - localSharing = (String)namespace.get("sharing"); - } - } - - // sharing, if set calls for special mapping, override here. - // "user" --> {user}/{app} - // "app" --> nobody/{app} - // "global" --> nobody/{app} - // "system" --> nobody/system - if (localSharing.equals("app") || localSharing.equals("global")) - localOwner = "nobody"; - else if (localSharing.equals("system")) { - localApp = "system"; - localOwner = "nobody"; - } - - return String.format("/servicesNS/%s/%s/%s", - localOwner == null ? "-" : localOwner, - localApp == null ? "-" : localApp, - path); - } - - /** - * Returns the app context for this {@code Service} instance. - * A {@code null} value indicates no app context, and a value of - * {@code "-"} indicates an app wildcard. - * - * @return The app context. - */ - public String getApp() { - return this.app; - } - - /** - * Returns the collection of applications. - * - * @return The application collection. - */ - public EntityCollection<Application> getApplications() { - return new EntityCollection<Application>( - this, "/services/apps/local", Application.class); - } - - /** - * Returns the collection of configurations. - * - * @return The configurations collection. - */ - public ConfCollection getConfs() { - return getConfs(null); - } - - /** - * Returns the collection of configurations. - * - * @param args Collection arguments that specify the number of entities to - * return and how to sort them. See {@link CollectionArgs}. - * @return The configurations collection. - */ - public ConfCollection getConfs(Args args) { - return new ConfCollection(this, args); - } - - /** - * Returns an array of system capabilities. - * - * @return An array of capabilities. - */ - public String[] getCapabilities() { - Entity caps = new Entity(this, "authorization/capabilities"); - return caps.getStringArray("capabilities"); - } - - /** - * Returns the collection of data models. - * @return DataModelCollection instance - */ - public DataModelCollection getDataModels() { - return new DataModelCollection(this); - } - - /** - * Returns the configuration and status of a deployment client. - * - * @return The configuration and status. - */ - public DeploymentClient getDeploymentClient() { - return new DeploymentClient(this); - } - - /** - * Returns the configuration of all deployment servers. - * - * @return The configuration of deployment servers. - */ - public EntityCollection<DeploymentServer> getDeploymentServers() { - return getDeploymentServers(null); - } - - /** - * Returns the collection of deployment servers. - * - * @param args Collection arguments that specify the number of entities to - * return and how to sort them. See {@link CollectionArgs}. - * @return The configuration of deployment servers. - */ - public EntityCollection<DeploymentServer> getDeploymentServers(Args args) { - String path; - if (versionIsEarlierThan("6.0.0")) { - path = "deployment/server"; - } else { - path = ""; // TODO: Find out what this should be and fix it. - } - return new EntityCollection<DeploymentServer>( - this, "deployment/server", DeploymentServer.class, args); - } - - /** - * Returns a collection of class configurations for a deployment server. - * - * @return A collection of class configurations. - */ - public EntityCollection<DeploymentServerClass> getDeploymentServerClasses(){ - return getDeploymentServerClasses(null); - } - - /** - * Returns a collection of class configurations for a deployment server. - * - * @param args Collection arguments that specify the number of entities to - * return and how to sort them. See {@link CollectionArgs}. - * @return A collection of server class configurations. - */ - public EntityCollection<DeploymentServerClass> getDeploymentServerClasses( - Args args) { - String path; - if (versionIsEarlierThan("6.0.0")) { - path = "deployment/serverclass"; - } else { - path = "deployment/server/serverclasses"; - } - return new EntityCollection<DeploymentServerClass>( - this, path, DeploymentServerClass.class, args); - } - - /** - * Returns a collection of multi-tenant configurations. - * - * @return A collection of multi-tenant configurations. - */ - public EntityCollection<DeploymentTenant> getDeploymentTenants() { - return getDeploymentTenants(null); - } - - /** - * Returns a collection of multi-tenant configurations. - * - * @param args Collection arguments that specify the number of entities to - * return and how to sort them. See {@link CollectionArgs}. - * @return A collection of multi-tenant configurations. - */ - public EntityCollection<DeploymentTenant> getDeploymentTenants(Args args) { - return new EntityCollection<DeploymentTenant>( - this, "deployment/tenants", DeploymentTenant.class, args); - } - - /** - * Returns information about distributed search options. - * - * @return Distributed search information. - */ - public DistributedConfiguration getDistributedConfiguration() { - return new DistributedConfiguration(this); - } - - /** - * Returns a collection of distributed search peers. A <i>search peer</i> - * is a Splunk server to which another Splunk server distributes searches. - * The Splunk server where the search originates is referred to as the - * <i>search head</i>. - * - * @return A collection of search peers. - */ - public EntityCollection<DistributedPeer> getDistributedPeers() { - return getDistributedPeers(null); - } - - /** - * Returns a collection of distributed search peers. A <i>search peer</i> - * is a Splunk server to which another Splunk server distributes searches. - * The Splunk server where the search originates is referred to as the - * <i>search head</i>. - * - * @param args Collection arguments that specify the number of entities to - * return and how to sort them. See {@link CollectionArgs}. - * @return A collection of search peers. - */ - public EntityCollection<DistributedPeer> getDistributedPeers(Args args) { - return new EntityCollection<DistributedPeer>( - this, "search/distributed/peers", DistributedPeer.class, args); - } - - - /** - * Returns a collection of saved event types. - * - * @return A collection of saved event types. - */ - public EventTypeCollection getEventTypes() { - return getEventTypes(null); - } - - /** - * Returns a collection of saved event types. - * - * @param args Collection arguments that specify the number of entities to - * return and how to sort them. See {@link CollectionArgs}. - * @return A collection of saved event types. - */ - public EventTypeCollection getEventTypes(Args args) { - return new EventTypeCollection(this, args); - } - - /** - * Returns a collection of alerts that have been fired by the service. - * - * @return A collection of fired alerts. - */ - public FiredAlertGroupCollection getFiredAlertGroups() { - return getFiredAlertsGroups(null); - } - - /** - * Returns a collection of alerts that have been fired by the service. - * - * @param args Collection arguments that specify the number of entities to - * return and how to sort them. See {@link CollectionArgs}. - * @return A collection of fired alerts. - */ - public FiredAlertGroupCollection getFiredAlertsGroups(Args args) { - return new FiredAlertGroupCollection(this, args); - } - - /** - * Returns a collection of Splunk indexes. - * - * @return A collection of indexes. - */ - public IndexCollection getIndexes() { - return getIndexes((IndexCollectionArgs)null); - } - - /** - * Returns a collection of Splunk indexes. - * - * @param args Collection arguments that specify the number of entities to - * return and how to sort them. See {@link IndexCollectionArgs}. - * @return A collection of indexes. - */ - // NOTE: This overload exists primarily to provide better documentation - // for the "args" parameter. - public IndexCollection getIndexes(IndexCollectionArgs args) { - return getIndexes((Args)args); - } - - /** - * Returns a collection of Splunk indexes. - * - * @param args Collection arguments that specify the number of entities to - * return and how to sort them. See {@link IndexCollectionArgs}. - * @return A collection of indexes. - */ - public IndexCollection getIndexes(Args args) { - return new IndexCollection(this, args); - } - - /** - * Returns information about the Splunk service. - * - * @return Splunk service information. - */ - public ServiceInfo getInfo() { - return new ServiceInfo(this); - } - - /** - * Returns list of all applicable Cluster Master Hosts for the SearchHead Service. - * - * @return List of Cluster Master Host(s). - */ - public List<String> getClusterMasters(){ - Entity caps = new Entity(this, "cluster/config"); - List<String> hosts = new ArrayList<String>(); - try { - String clusterMasterURIs = caps.getString("master_uri"); - URL clusterMasterUrl; - //for multi-cluster environment, there might be more than cluster master for the searchHead - if(clusterMasterURIs.contains(",")){ - String[] masterURIs = clusterMasterURIs.split(","); - for(String uri : masterURIs){ - clusterMasterUrl = new URL(uri); - hosts.add(clusterMasterUrl.getHost()); - } - }else { - clusterMasterUrl = new URL(clusterMasterURIs); - hosts.add(clusterMasterUrl.getHost()); - } - return hosts; - } catch (MalformedURLException e) { - e.printStackTrace(); - } - return hosts; - } - - /** - * Returns a collection of configured inputs. - * - * @return A collection of inputs. - */ - public InputCollection getInputs() { - return getInputs(null); - } - - /** - * Returns a collection of configured inputs. - * - * @param args Collection arguments that specify the number of entities to - * return and how to sort them. See {@link CollectionArgs}. - * @return A collection of inputs. - */ - public InputCollection getInputs(Args args) { - return new InputCollection(this, args); - } - - /** - * Returns a collection of current search jobs. - * - * @return A collection of search jobs. - */ - public JobCollection getJobs() { - return getJobs((CollectionArgs)null); - } - - /** - * Returns a collection of current search jobs. - * - * @param args Collection arguments that specify the number of entities to - * return and how to sort them. See {@link CollectionArgs}. - * @return A collection of search jobs. - */ - // NOTE: This overload exists primarily to provide better documentation - // for the "args" parameter. - public JobCollection getJobs(CollectionArgs args) { - return getJobs((Args)args); - } - - /** - * Returns a collection of current search jobs. - * - * @param args Collection arguments that specify the number of entities to - * return and how to sort them. See {@link CollectionArgs}. - * @return A collection of search jobs. - */ - public JobCollection getJobs(Args args) { - return new JobCollection(this, args); - } - - /** - * Returns a Job by the provided sid. - * - * @param sid The sid for a job. - * @return A Job. - */ - public Job getJob(String sid) { - return new Job(this, JobCollection.REST_PATH + "/" + sid); - } - - /** - * Returns a collection of license group configurations. - * - * @return A collection of license group configurations. - */ - public EntityCollection<LicenseGroup> getLicenseGroups() { - return getLicenseGroups(null); - } - - /** - * Returns a collection of license group configurations. - * - * @param args Collection arguments that specify the number of entities to - * return and how to sort them. See {@link CollectionArgs}. - * @return A collection of license group configurations. - */ - public EntityCollection<LicenseGroup> getLicenseGroups(Args args) { - return new EntityCollection<LicenseGroup>( - this, "licenser/groups", LicenseGroup.class, args); - } - - /** - * Returns a collection of messages from the licenser. - * - * @return A collection of licenser messages. - */ - public EntityCollection<LicenseMessage> getLicenseMessages() { - return getLicenseMessages(null); - } - - /** - * Returns a collection of messages from the licenser. - * - * @param args Collection arguments that specify the number of entities to - * return and how to sort them. See {@link CollectionArgs}. - * @return A collection of licenser messages. - */ - public EntityCollection<LicenseMessage> getLicenseMessages(Args args) { - return new EntityCollection<LicenseMessage>( - this, "licenser/messages", LicenseMessage.class, args); - } - - /** - * Returns the current owner context for this {@code Service} instance. - * A value of {@code "-"} indicates a wildcard, and a {@code null} value - * indicates no owner context. - * - * @return The current owner context. - */ - public String getOwner() { - return this.owner; - } - - /** - * Returns a collection of licenser pool configurations. - * - * @return A collection of licenser pool configurations. - */ - public LicensePoolCollection getLicensePools() { - return getLicensePools(null); - } - - /** - * Returns a collection of licenser pool configurations. - * - * @param args Collection arguments that specify the number of entities to - * return and how to sort them. See {@link CollectionArgs}. - * @return A collection of licenser pool configurations. - */ - public LicensePoolCollection getLicensePools(Args args) { - return new LicensePoolCollection(this, args); - } - - /** - * Returns a collection of slaves reporting to this license master. - * - * @return A collection of licenser slaves. - */ - public EntityCollection<LicenseSlave> getLicenseSlaves() { - return getLicenseSlaves(null); - } - - /** - * Returns a collection of slaves reporting to this license master. - * - * @param args Collection arguments that specify the number of entities to - * return and how to sort them. See {@link CollectionArgs}. - * @return A collection of licenser slaves. - */ - public EntityCollection<LicenseSlave> getLicenseSlaves(Args args) { - return new EntityCollection<LicenseSlave>( - this, "licenser/slaves", LicenseSlave.class, args); - } - - /** - * Returns a collection of license stack configurations. - * - * @return A collection of license stack configurations. - */ - public EntityCollection<LicenseStack> getLicenseStacks() { - return getLicenseStacks(null); - } - - /** - * Returns a collection of license stack configurations. - * - * @param args Collection arguments that specify the number of entities to - * return and how to sort them. See {@link CollectionArgs}. - * @return A collection of license stack configurations. - */ - public EntityCollection<LicenseStack> getLicenseStacks(Args args) { - return new EntityCollection<LicenseStack>( - this, "licenser/stacks", LicenseStack.class, args); - } - - /** - * Returns a collection of licenses for this service. - * - * @return A collection of licenses. - */ - public EntityCollection<License> getLicenses() { - return getLicenses(null); - } - - /** - * Returns a collection of licenses for this service. - * - * @param args Collection arguments that specify the number of entities to - * return and how to sort them. See {@link CollectionArgs}. - * @return A collection of licenses. - */ - public EntityCollection<License> getLicenses(Args args) { - return new EntityCollection<License>( - this, "licenser/licenses", License.class, args); - } - - /** - * Returns a collection of service logging categories and their status. - * - * @return A collection of logging categories. - */ - public EntityCollection<Logger> getLoggers() { - return getLoggers(null); - } - - /** - * Returns a collection of service logging categories and their status. - * - * @param args Collection arguments that specify the number of entities to - * return and how to sort them. See {@link CollectionArgs}. - * @return A collection of logging categories. - */ - public EntityCollection<Logger> getLoggers(Args args) { - return new EntityCollection<Logger>( - this, "server/logger", Logger.class, args); - } - - /** - * Returns a collection of system messages. - * - * @return A collection of system messages. - */ - public MessageCollection getMessages() { - return getMessages(null); - } - - /** - * Returns a collection of system messages. - * - * @param args Collection arguments that specify the number of entities to - * return and how to sort them. See {@link CollectionArgs}. - * @return A collection of system messages. - */ - public MessageCollection getMessages(Args args) { - return new MessageCollection(this, args); - } - - /** - * Returns a collection of modular inputs. - * - * @return A collection of modular inputs. - */ - public ResourceCollection<ModularInputKind> getModularInputKinds() { - return getModularInputKinds(null); - } - - /** - * Returns a collection of modular inputs. - * - * @param args Collection arguments that specify the number of entities to - * return and how to sort them. See {@link CollectionArgs}. - * @return A collection of modular inputs. - */ - public ResourceCollection<ModularInputKind> getModularInputKinds(Args args) { - return new ResourceCollection<ModularInputKind>( - this, "data/modular-inputs", ModularInputKind.class, args); - } - - /** - * Returns global TCP output properties. - * - * @return Global TCP output properties. - */ - public OutputDefault getOutputDefault() { - return new OutputDefault(this); - } - - /** - * Returns a collection of output group configurations. - * - * @return A collection of output group configurations. - */ - public EntityCollection<OutputGroup> getOutputGroups() { - return getOutputGroups(null); - } - - /** - * Returns a collection of output group configurations. - * - * @param args Collection arguments that specify the number of entities to - * return and how to sort them. See {@link CollectionArgs}. - * @return A collection of output group configurations. - */ - public EntityCollection<OutputGroup> getOutputGroups(Args args) { - return new EntityCollection<OutputGroup>( - this, "data/outputs/tcp/group", OutputGroup.class, args); - } - - /** - * Returns a collection of data-forwarding configurations. - * - * @return A collection of data-forwarding configurations. - */ - public EntityCollection<OutputServer> getOutputServers() { - return getOutputServers(null); - } - - /** - * Returns a collection of data-forwarding configurations. - * - * @param args Collection arguments that specify the number of entities to - * return and how to sort them. See {@link CollectionArgs}. - * @return A collection of data-forwarding configurations. - */ - public EntityCollection<OutputServer> getOutputServers(Args args) { - return new EntityCollection<OutputServer>( - this, "data/outputs/tcp/server", OutputServer.class, args); - } - - /** - * Returns a collection of configurations for forwarding data in standard - * syslog format. - * - * @return A collection of syslog forwarders. - */ - public EntityCollection<OutputSyslog> getOutputSyslogs() { - return getOutputSyslogs(null); - } - - /** - * Returns a collection of configurations for forwarding data in standard - * syslog format. - * - * @param args Collection arguments that specify the number of entities to - * return and how to sort them. See {@link CollectionArgs}. - * @return A collection of syslog forwarders. - */ - public EntityCollection<OutputSyslog> getOutputSyslogs(Args args) { - return new EntityCollection<OutputSyslog>( - this, "data/outputs/tcp/syslog", OutputSyslog.class, args); - } - - /** - * Returns the current password that was used to authenticate the session. - * - * @return The current password. - */ - public String getPassword() { - return this.password; - } - - /** - * Returns a collection of passwords. This collection is used for managing - * secure credentials. - * - * @return A collection of passwords. - */ - public PasswordCollection getPasswords() { - return getPasswords(null); - } - - /** - * Returns a collection of passwords. This collection is used for managing - * secure credentials. - * - * @param args Collection arguments that specify the number of entities to - * return and how to sort them. See {@link CollectionArgs}. - * @return A collection of passwords. - */ - public PasswordCollection getPasswords(Args args) { - return new PasswordCollection(this, args); - } - - /** - * Returns the receiver object for the Splunk service. - * - * @return A Splunk receiver object. - */ - public Receiver getReceiver() { - return new Receiver(this); - } - - /** - * Returns a collection of Splunk user roles. - * - * @return A collection of user roles. - */ - public EntityCollection<Role> getRoles() { - return getRoles(null); - } - - /** - * Returns a collection of Splunk user roles. - * - * @param args Collection arguments that specify the number of entities to - * return and how to sort them. See {@link CollectionArgs}. - * @return A collection of user roles. - */ - public EntityCollection<Role> getRoles(Args args) { - return new EntityCollection<Role>( - this, "authorization/roles", Role.class, args); - } - - /** - * Returns a collection of saved searches. - * - * @return A collection of saved searches. - */ - public SavedSearchCollection getSavedSearches() { - return getSavedSearches((SavedSearchCollectionArgs)null); - } - - /** - * Returns a collection of saved searches. - * - * @param args Collection arguments that specify the number of entities to - * return and how to sort them. See {@link SavedSearchCollectionArgs}. - * @return A collection of saved searches. - */ - // NOTE: This overload exists primarily to provide better documentation - // for the "args" parameter. - public SavedSearchCollection getSavedSearches(SavedSearchCollectionArgs args) { - return getSavedSearches((Args)args); - } - - /** - * Returns a collection of saved searches. - * - * @param args Collection arguments that specify the number of entities to - * return and how to sort them. See {@link CollectionArgs}. - * @return A collection of saved searches. - */ - public SavedSearchCollection getSavedSearches(Args args) { - return new SavedSearchCollection(this, args); - } - - /** - * Returns a Saved Search by the provided title key. - * - * @param title The title for a job. - * @return A SavedSearch. - */ - public SavedSearch getSavedSearch(String title) { - return new SavedSearch(this, JobCollection.REST_PATH + "/" + title); - } - - /** - * Returns service configuration information for an instance of Splunk. - * - * @return Service configuration information. - */ - public Settings getSettings() { - return new Settings(this); - } - - /** - * Returns the current session token. Session tokens can be shared across - * multiple {@code Service} instances. - * - * @return The session token. - */ - public String getToken() { - return this.token; - } - - /** - * Returns a collection of in-progress oneshot uploads. - * - * @return A collection of in-progress oneshot uploads - */ - public EntityCollection<Upload> getUploads() { - return getUploads(null); - } - - /** - * Returns a collection of in-progress oneshot uploads. - * - * @param namespace This collection's namespace; there are no other - * optional arguments for this endpoint. - * @return A collection of in-progress oneshot uploads - */ - public EntityCollection<Upload> getUploads(Args namespace) { - return new EntityCollection<Upload>( - this, "data/inputs/oneshot", Upload.class, namespace); - } - - /** - * Returns the Splunk account username that was used to authenticate the - * current session. - * - * @return The current username. - */ - public String getUsername() { - return this.username; - } - - /** - * Returns a collection of Splunk users. - * - * @return A collection of users. - */ - public UserCollection getUsers() { - return getUsers(null); - } - - /** - * Returns a collection of Splunk users. - * - * @param args Collection arguments that specify the number of entities to - * return and how to sort them. See {@link CollectionArgs}. - * @return A collection of users. - */ - public UserCollection getUsers(Args args) { - return new UserCollection(this, args); - } - - /** - * Authenticates the {@code Service} instance with the username and password - * that were specified when the instance was created. - * - * Three cases: - * 1. If we have a cookie, but are missing username and/or password, login is noop - * 2. If we don't have a cookie, and are missing username and/or password we can't login - * 3. Otherwise login as usual - * - * @return The current {@code Service} instance. - */ - public Service login() { - if (this.cookieStore.hasSplunkAuthCookie() && (this.username == null || this.password == null)) { - return this; - } - else if (this.username == null || this.password == null) { - throw new IllegalStateException("Missing username or password."); - } - else { - return login(this.username, this.password); - } - } - - /** - * Authenticates the {@code Service} instance with a specified username and - * password. Note that these values override any previously-set values for - * username and password. - * - * @param username The Splunk account username. - * @param password The password for the username. - * @return The current {@code Service} instance. - */ - public Service login(String username, String password) { - this.username = username; - this.password = password; - - Args args = new Args(); - args.put("username", username); - args.put("password", password); - args.put("cookie", "1"); - ResponseMessage response = post("/services/auth/login", args); - String sessionKey = Xml.parse(response.getContent()) - .getElementsByTagName("sessionKey") - .item(0) - .getTextContent(); - this.token = "Splunk " + sessionKey; - ServiceInfo serviceInfoEntity = this.getInfo(); - this.version = serviceInfoEntity.getVersion(); - this.instanceType = serviceInfoEntity.getInstanceType(); - if (versionCompare("4.3") >= 0) - this.passwordEndPoint = "storage/passwords"; - - return this; - } - - /** - * Forgets the current session token. - * - * @return The current {@code Service} instance. - */ - public Service logout() { - this.token = null; - this.removeAllCookies(); - return this; - } - - /** - * Creates a oneshot synchronous search. - * - * @param query The search query. - * @return The search results. - */ - public InputStream oneshotSearch(String query) { - return oneshotSearch(query, null); - } - - /** - * Creates a oneshot synchronous search using search arguments. - * - * @param query The search query. - * @param args The search arguments:<ul> - * <li>"output_mode": Specifies the output format of the results (XML, JSON, - * or CSV).</li> - * <li>"earliest_time": Specifies the earliest time in the time range to - * search. The time string can be a UTC time (with fractional seconds), a - * relative time specifier (to now), or a formatted time string.</li> - * <li>"latest_time": Specifies the latest time in the time range to search. - * The time string can be a UTC time (with fractional seconds), a relative - * time specifier (to now), or a formatted time string.</li> - * <li>"rf": Specifies one or more fields to add to the search.</li></ul> - * @return The search results. - */ - public InputStream oneshotSearch(String query, Map args) { - args = Args.create(args); - args.put("search", query); - args.put("exec_mode", "oneshot"); - - // By default, don't highlight search terms in the search output. - if (!args.containsKey("segmentation")) { - args.put("segmentation", "none"); - } - - ResponseMessage response = post(JobCollection.REST_PATH, args); - return response.getContent(); - } - - /** - * Creates a oneshot synchronous search using search arguments. - * - * @param query The search query. - * @param args The search arguments:<ul> - * <li>"output_mode": Specifies the output format of the results (XML, JSON, - * or CSV).</li> - * <li>"earliest_time": Specifies the earliest time in the time range to - * search. The time string can be a UTC time (with fractional seconds), a - * relative time specifier (to now), or a formatted time string.</li> - * <li>"latest_time": Specifies the latest time in the time range to search. - * The time string can be a UTC time (with fractional seconds), a relative - * time specifier (to now), or a formatted time string.</li> - * <li>"rf": Specifies one or more fields to add to the search.</li></ul> - * @return The search results. - */ - public InputStream oneshotSearch(String query, Args args) { - return oneshotSearch(query, (Map<String, Object>)args); - } - - /** - * Opens a raw socket to this service. - * - * @param port The port to open. This port must already have been - * created as an allowable TCP input to the service. - * @return The socket. - * @throws java.io.IOException The IOException instance - */ - public Socket open(int port) throws IOException { - return new Socket(this.host, port); - } - - /** - * Parses a search query and returns a semantic map for the search in JSON - * format. - * - * @param query The search query. - * @return The parse response message. - */ - public ResponseMessage parse(String query) { - return parse(query, null); - } - - /** - * Parses a search query with additional arguments and returns a semantic - * map for the search in JSON format. - * - * @param query The search query. - * @param args Additional parse arguments. - * @return The parse response message. - */ - public ResponseMessage parse(String query, Map args) { - args = Args.create(args).add("q", query); - - if(enableV2SearchApi()) - return post("search/v2/parser", args); - else - return get("search/parser", args); - } - - /** - * Restarts the service. The service will be unavailable until it has - * successfully restarted. - * - * @return The restart response message. - */ - public ResponseMessage restart() { - return post("server/control/restart"); - } - - /** - * Creates an asynchronous search using the given query. Use this - * method for simple searches. - * - * @param query The search query. - * @return The search job. - */ - public Job search(String query) { - return search(query, null); - } - - /** - * Creates an asynchronous search job using the given query and - * search arguments. - * - * @param query The search query. - * @param args The search arguments. - * @return The search job. - */ - public Job search(String query, Map<String, Object> args) { - args = Args.create(args); - - return this.getJobs().create(query, args); - } - - /** - * Issues an HTTP request against the service using a request path and - * message. - * This method overrides the base {@code HttpService.send} method - * and applies the Splunk authorization header, which is required for - * authenticated interactions with the Splunk service. - * - * @param path The request path. - * @param request The request message. - * @return The HTTP response. - */ - @Override public ResponseMessage send(String path, RequestMessage request) { - // cookieStore is a protected member of HttpService - if (token != null && !cookieStore.hasSplunkAuthCookie() ) { - request.getHeader().put("Authorization", token); - } - ResponseMessage responseMessage = super.send(fullpath(path), request); - if(responseMessage.getStatus() == 401 && (this.autologin && this.username!= null && this.password != null)){ - // Executing re-login to renew the session token. - this.login(this.username, this.password); - responseMessage = super.send(fullpath(path), request); - }else if(responseMessage.getStatus() >= 400){ - //if autologin is not set to true or username/password is not set, throw HTTPException - throw HttpException.create(responseMessage); - } - return responseMessage; - } - - /** - * Provides a session token for use by this {@code Service} instance. - * Session tokens can be shared across multiple {@code Service} instances. - * - * @param value The session token, which is a basic authorization header in - * the format "Basic <i>sessiontoken</i>", where <i>sessiontoken</i> is the - * Base64-encoded "username:password" string. - */ - public void setToken(String value) { - this.token = value; - } - - /** - * Provides a session token having <b>Splunk</b> added before token. - * This method is specifically used when user just have token value. - * - * @param value The token value - */ - public void setSplunkToken(String value) { - this.token = value.contains("Splunk") ? value : "Splunk " + value; - } - - /** - * Provides a session token having <b>Bearer</b> added before token. - * This method is specifically used when user just have token value. - * - * @param value The token value - */ - public void setBearerToken(String value) { - this.token = value.contains("Splunk") || value.contains("Bearer") ? value : "Bearer " + value; - } - - - public boolean enableV2SearchApi(){ - if(null == this.instanceType){ - this.instanceType = this.getInfo().getInstanceType(); - } - if(this.instanceType.equalsIgnoreCase("cloud")) { - return versionIsAtLeast("9.0.2209"); - }else{ - return versionIsAtLeast("9.0.2"); - } - } - - /** - * Returns true if this Splunk instance's version is no earlier than - * the version specified in {@code version}. - * - * So when called on a Splunk 4.3.2 instance: - * * {@code versionIsAtLeast("4.3.2")} is {@code true}. - * * {@code versionIsAtLeast("4.1.0")} is {@code true}. - * * {@code versionIsAtLeast("5.0.0")} is {@code false}. - * - * @param version The version to compare this Splunk instance's version against. - * @return {@code true} if this Splunk instance's version is equal or - * greater than {@code version}; {@code false} otherwise. - */ - boolean versionIsAtLeast(String version) { - return versionCompare(version) >= 0; - } - - /** - * Returns true if this Splunk instance's version is earlier than - * the version specified in {@code version}. - * - * So when called on a Splunk 4.3.2 instance: - * * {@code versionIsEarlierThan("4.3.2")} is {@code false}. - * * {@code versionIsEarlierThan("4.1.0")} is {@code false}. - * * {@code versionIsEarlierThan("5.0.0")} is {@code true}. - * - * @param version The version to compare this Splunk instance's version against. - * @return {@code true} if this Splunk instance's version is less - * than {@code version}; {@code false} otherwise. - */ - boolean versionIsEarlierThan(String version) { - return versionCompare(version) < 0; - } - - /** - * Returns a value indicating how the version of this Splunk instance - * compares to a given version: - * <ul> - * <li>{@code -1 if this version < the given version}</li> - * <li>{@code 0 if this version = the given version}</li> - * <li>{@code 1 if this version > the given version}</li> - * </ul> - * - * @param otherVersion The other version to compare to. - * @return -1 if this version is less than, 0 if this version is equal to, - * or 1 if this version is greater than the given version. - */ - public int versionCompare(String otherVersion) { - if(null == this.version){ - this.version = this.getInfo().getVersion(); - } - String[] components1 = this.version.split("\\."); - String[] components2 = otherVersion.split("\\."); - int numComponents = Math.max(components1.length, components2.length); - - for (int i = 0; i < numComponents; i++) { - int c1 = (i < components1.length) - ? Integer.parseInt(components1[i], 10) : 0; - int c2 = (i < components2.length) - ? Integer.parseInt(components2[i], 10) : 0; - if (c1 < c2) { - return -1; - } else if (c1 > c2) { - return 1; - } - } - return 0; - } -} +/* + * 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.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * The {@code Service} class represents a Splunk service instance at a given + * address (host:port), accessed using the {@code http} or {@code https} + * protocol scheme. + * <p> + * A {@code Service} instance also captures an optional namespace context + * consisting of an optional owner name (or "-" wildcard) and optional app name + * (or "-" wildcard). + * <p> + * To access {@code Service} members, the {@code Service} instance must be + * authenticated by presenting credentials using the {@code login} method, or + * by constructing the {@code Service} instance using the {@code connect} + * method, which both creates and authenticates the instance. + */ +public class Service extends BaseService { + /** The current app context. */ + protected String app = null; + + /** The current session token. */ + protected String token = null; + + /** The current owner context. A value of "nobody" means that all users + * have access to the resource. + */ + protected String owner = null; + + /** The Splunk account username, which is used to authenticate the Splunk + * instance. */ + protected String username = null; + + /** The password, which is used to authenticate the Splunk instance. */ + protected String password = null; + + /** The default simple receiver endpoint. */ + protected String simpleReceiverEndPoint = "/services/receivers/simple"; + + /** The default password endpoint, can change over Splunk versions. */ + protected String passwordEndPoint = "admin/passwords"; + + /** The version of this Splunk instance, once logged in. */ + public String version = null; + + /** The type of this Splunk instance, once logged in. */ + public String instanceType = null; + + /** The default host name, which is used when a host name is not provided.*/ + public static String DEFAULT_HOST = "localhost"; + + /** The default port number, which is used when a port number is not + * provided. */ + public static int DEFAULT_PORT = 8089; + + /** The default scheme, which is used when a scheme is not provided. */ + public static String DEFAULT_SCHEME = "https"; + + /** Flag to notify SDK to try for re-login if the session has expired API call*/ + protected boolean autologin = false; + + /** + * Creates a new {@code Service} instance using a host. + * + * @param host The host name. + */ + public Service(String host) { + super(host); + } + + /** + * Creates a new {@code Service} instance using a host and port. + * + * @param host The host name. + * @param port The port number. + */ + public Service(String host, int port) { + super(host, port); + } + + /** + * Creates a new {@code Service} instance using a host, port, and + * scheme for accessing the service ({@code http} or {@code https}). + * + * @param host The host name. + * @param port The port number. + * @param scheme The scheme ({@code http} or {@code https}). + */ + public Service(String host, int port, String scheme) { + super(host, port, scheme); + } + + /** + * Constructs a new {@code Service} instance using the given host, + * port, and scheme, and instructing it to use the specified HTTPS handler. + * + * @param host The host name of the service. + * @param port The port number of the service. + * @param scheme Scheme for accessing the service ({@code http} or + * {@code https}). + * @param httpsHandler The URLStreamHandler instance + */ + public Service(String host, int port, String scheme, + URLStreamHandler httpsHandler) { + this.host = host; + this.port = port; + this.scheme = scheme; + this.httpsHandler = httpsHandler; + } + + /** + * Creates a new {@code Service} instance using a collection of arguments. + * + * @param args The {@code ServiceArgs} to initialize the service. + */ + // NOTE: This overload exists primarily to provide better documentation + // for the "args" parameter. + @SuppressWarnings("deprecation") + public Service(ServiceArgs args) { + super(); + // NOTE: Must read the deprecated fields for backward compatibility. + // (Consider the case where the fields are initialized directly, + // rather than using the new setters.) + // NOTE: Must also read the underlying dictionary for forward compatibility. + // (Consider the case where the user calls Map.put() directly, + // rather than using the new setters.) + this.app = Args.get(args, "app", args.app != null ? args.app : null); + this.host = Args.get(args, "host", args.host != null ? args.host : DEFAULT_HOST); + this.owner = Args.get(args, "owner", args.owner != null ? args.owner : null); + this.port = Args.<Integer>get(args, "port", args.port != null ? args.port : DEFAULT_PORT); + this.scheme = Args.get(args, "scheme", args.scheme != null ? args.scheme : DEFAULT_SCHEME); + this.token = Args.get(args, "token", args.token != null ? args.token : null); + this.username = (String)args.get("username"); + this.password = (String)args.get("password"); + this.autologin = Args.<Boolean>get(args, "autologin", false); + this.httpsHandler = Args.get(args, "httpsHandler", null); + this.setSslSecurityProtocol(Args.get(args, "SSLSecurityProtocol", Service.getSslSecurityProtocol())); + this.addCookie((String)args.get("cookie")); + this.setCustomHeaders((Map<String, String>) args.get("customHeaders")); + } + + /** + * Creates a new {@code Service} instance using a map of arguments. + * + * @param args A {@code Map} of arguments to initialize the service. + */ + public Service(Map<String, Object> args) { + super(); + this.app = Args.get(args, "app", null); + this.host = Args.get(args, "host", DEFAULT_HOST); + this.owner = Args.get(args, "owner", null); + this.port = Args.<Integer>get(args, "port", DEFAULT_PORT); + this.scheme = Args.get(args, "scheme", DEFAULT_SCHEME); + this.token = Args.get(args, "token", null); + this.username = (String)args.get("username"); + this.password = (String)args.get("password"); + this.autologin = Args.<Boolean>get(args, "autologin", false); + this.httpsHandler = Args.get(args, "httpsHandler", null); + this.setSslSecurityProtocol(Args.get(args, "SSLSecurityProtocol", Service.getSslSecurityProtocol())); + this.addCookie((String)args.get("cookie")); + this.connectTimeout = Args.<Integer>get(args, "connectTimeout", null); + this.readTimeout = Args.<Integer>get(args, "readTimeout", null); + } + + /** + * Establishes a connection to a Splunk service using a map of arguments. + * This member creates a new {@code Service} instance and authenticates + * the session using credentials passed in from the {@code args} map. + * + * @param args The {@code args} map. + * @return A new {@code Service} instance. + */ + public static Service connect(Map<String, Object> args) { + Service service = new Service(args); + if (args.containsKey("username")) { + service.login(); + } + return service; + } + + /** + * Runs an export search (using the {@code search/jobs/export} endpoint), + * and streams results back in an input stream. + * + * @param search The search query to run. + * @return The {@code InputStream} object that contains the search results. + */ + public InputStream export(String search) { + return export(search, null); + } + + /** + * Runs an export search with arguments (using the {@code search/jobs/export} + * endpoint), and streams results back in an input stream. + * + * @param search The search query to run. + * @param args Additional search arguments. + * For a list of possible parameters, see + * <a href="http://dev.splunk.com/view/SP-CAAAEHQ#savedsearchparams" + * target="_blank">Saved search parameters</a> on + * <a href="http://dev.splunk.com/view/SP-CAAAEHQ" + * target="_blank">dev.splunk.com</a>. + * @return The {@code InputStream} object that contains the search results. + */ + public InputStream export(String search, Map args) { + args = Args.create(args).add("search", search); + // By default don't highlight search terms in the output. + if (!args.containsKey("segmentation")) { + args.put("segmentation", "none"); + } + ResponseMessage response; + + if(enableV2SearchApi()) + response = post(JobCollection.REST_PATH_V2 + "/export", args); + else { + response = post(JobCollection.REST_PATH + "/export", args); + } + return new ExportResultsStream(response.getContent()); + } + + /** + * Runs an export search with arguments (using the {@code search/jobs/export} + * endpoint), and streams results back in an input stream. + * + * @param search The search query to run. + * @param args Additional search arguments (see {@code JobExportArgs}). + * @return The {@code InputStream} object that contains the search results. + */ + // NOTE: This overload exists primarily to provide better documentation + // for the "args" parameter. + public InputStream export(String search, JobExportArgs args) { + return export(search, (Map<String, Object>) args); + } + + /** + * Ensures that the given path is fully qualified, prepending a path + * prefix if necessary. The path prefix is constructed using the current + * owner and app context when available. + * + * @param path The path to verify. + * @return A fully-qualified resource path. + */ + String fullpath(String path) { + return fullpath(path, null); + } + + /** + * Ensures that a given path is fully qualified, prepending a path + * prefix if necessary. The path prefix is constructed using the + * current owner and app context when available. + * + * @param path The path to verify. + * @param namespace The namespace dictionary (<i>app, owner, sharing</i>). + * @return A fully-qualified resource path. + */ + public String fullpath(String path, Args namespace) { + + // if already fully qualified (i.e. root begins with /) then return + // the already qualified path. + if (path.startsWith("/")) + return path; + + // if no namespace at all, and no service instance of app, and no + // sharing, return base service endpoint + path. + if (namespace == null && app == null) { + return "/services/" + path; + } + + // base namespace values + String localApp = app; + String localOwner = owner; + String localSharing = ""; + + // override with invocation namespace if set. + try{ + if (namespace != null) { + // URL encode the owner and app. + if (namespace.containsKey("app")) { + localApp = URLEncoder.encode((String)namespace.get("app"), "UTF-8"); + } + if (namespace.containsKey("owner")) { + localOwner = URLEncoder.encode((String)namespace.get("owner"), "UTF-8"); + } + if (namespace.containsKey("sharing")) { + localSharing = (String)namespace.get("sharing"); + } + } + }catch (UnsupportedEncodingException e) { + // This is unreachable, since UTF-8 is always supported. + assert false; + } + + + // sharing, if set calls for special mapping, override here. + // "user" --> {user}/{app} + // "app" --> nobody/{app} + // "global" --> nobody/{app} + // "system" --> nobody/system + if (localSharing.equals("app") || localSharing.equals("global")) + localOwner = "nobody"; + else if (localSharing.equals("system")) { + localApp = "system"; + localOwner = "nobody"; + } + + return String.format("/servicesNS/%s/%s/%s", + localOwner == null ? "-" : localOwner, + localApp == null ? "-" : localApp, + path); + } + + /** + * Returns the app context for this {@code Service} instance. + * A {@code null} value indicates no app context, and a value of + * {@code "-"} indicates an app wildcard. + * + * @return The app context. + */ + public String getApp() { + return this.app; + } + + /** + * Returns the collection of applications. + * + * @return The application collection. + */ + public EntityCollection<Application> getApplications() { + return new EntityCollection<>( + this, "/services/apps/local", Application.class); + } + + /** + * Returns the collection of configurations. + * + * @return The configurations collection. + */ + public ConfCollection getConfs() { + return getConfs(null); + } + + /** + * Returns the collection of configurations. + * + * @param args Collection arguments that specify the number of entities to + * return and how to sort them. See {@link CollectionArgs}. + * @return The configurations collection. + */ + public ConfCollection getConfs(Args args) { + return new ConfCollection(this, args); + } + + /** + * Returns an array of system capabilities. + * + * @return An array of capabilities. + */ + public String[] getCapabilities() { + Entity caps = new Entity(this, "authorization/capabilities"); + return caps.getStringArray("capabilities"); + } + + /** + * Returns the collection of data models. + * @return DataModelCollection instance + */ + public DataModelCollection getDataModels() { + return new DataModelCollection(this); + } + + /** + * Returns the configuration and status of a deployment client. + * + * @return The configuration and status. + */ + public DeploymentClient getDeploymentClient() { + return new DeploymentClient(this); + } + + /** + * Returns the configuration of all deployment servers. + * + * @return The configuration of deployment servers. + */ + public EntityCollection<DeploymentServer> getDeploymentServers() { + return getDeploymentServers(null); + } + + /** + * Returns the collection of deployment servers. + * + * @param args Collection arguments that specify the number of entities to + * return and how to sort them. See {@link CollectionArgs}. + * @return The configuration of deployment servers. + */ + public EntityCollection<DeploymentServer> getDeploymentServers(Args args) { + String path; + if (versionIsEarlierThan("6.0.0")) { + path = "deployment/server"; + } else { + path = ""; // TODO: Find out what this should be and fix it. + } + return new EntityCollection<>( + this, "deployment/server", DeploymentServer.class, args); + } + + /** + * Returns a collection of class configurations for a deployment server. + * + * @return A collection of class configurations. + */ + public EntityCollection<DeploymentServerClass> getDeploymentServerClasses(){ + return getDeploymentServerClasses(null); + } + + /** + * Returns a collection of class configurations for a deployment server. + * + * @param args Collection arguments that specify the number of entities to + * return and how to sort them. See {@link CollectionArgs}. + * @return A collection of server class configurations. + */ + public EntityCollection<DeploymentServerClass> getDeploymentServerClasses( + Args args) { + String path; + if (versionIsEarlierThan("6.0.0")) { + path = "deployment/serverclass"; + } else { + path = "deployment/server/serverclasses"; + } + return new EntityCollection<>( + this, path, DeploymentServerClass.class, args); + } + + /** + * Returns a collection of multi-tenant configurations. + * + * @return A collection of multi-tenant configurations. + */ + public EntityCollection<DeploymentTenant> getDeploymentTenants() { + return getDeploymentTenants(null); + } + + /** + * Returns a collection of multi-tenant configurations. + * + * @param args Collection arguments that specify the number of entities to + * return and how to sort them. See {@link CollectionArgs}. + * @return A collection of multi-tenant configurations. + */ + public EntityCollection<DeploymentTenant> getDeploymentTenants(Args args) { + return new EntityCollection<>( + this, "deployment/tenants", DeploymentTenant.class, args); + } + + /** + * Returns information about distributed search options. + * + * @return Distributed search information. + */ + public DistributedConfiguration getDistributedConfiguration() { + return new DistributedConfiguration(this); + } + + /** + * Returns a collection of distributed search peers. A <i>search peer</i> + * is a Splunk server to which another Splunk server distributes searches. + * The Splunk server where the search originates is referred to as the + * <i>search head</i>. + * + * @return A collection of search peers. + */ + public EntityCollection<DistributedPeer> getDistributedPeers() { + return getDistributedPeers(null); + } + + /** + * Returns a collection of distributed search peers. A <i>search peer</i> + * is a Splunk server to which another Splunk server distributes searches. + * The Splunk server where the search originates is referred to as the + * <i>search head</i>. + * + * @param args Collection arguments that specify the number of entities to + * return and how to sort them. See {@link CollectionArgs}. + * @return A collection of search peers. + */ + public EntityCollection<DistributedPeer> getDistributedPeers(Args args) { + return new EntityCollection<>( + this, "search/distributed/peers", DistributedPeer.class, args); + } + + + /** + * Returns a collection of saved event types. + * + * @return A collection of saved event types. + */ + public EventTypeCollection getEventTypes() { + return getEventTypes(null); + } + + /** + * Returns a collection of saved event types. + * + * @param args Collection arguments that specify the number of entities to + * return and how to sort them. See {@link CollectionArgs}. + * @return A collection of saved event types. + */ + public EventTypeCollection getEventTypes(Args args) { + return new EventTypeCollection(this, args); + } + + /** + * Returns a collection of alerts that have been fired by the service. + * + * @return A collection of fired alerts. + */ + public FiredAlertGroupCollection getFiredAlertGroups() { + return getFiredAlertsGroups(null); + } + + /** + * Returns a collection of alerts that have been fired by the service. + * + * @param args Collection arguments that specify the number of entities to + * return and how to sort them. See {@link CollectionArgs}. + * @return A collection of fired alerts. + */ + public FiredAlertGroupCollection getFiredAlertsGroups(Args args) { + return new FiredAlertGroupCollection(this, args); + } + + /** + * Returns a collection of Splunk indexes. + * + * @return A collection of indexes. + */ + public IndexCollection getIndexes() { + return getIndexes((IndexCollectionArgs)null); + } + + /** + * Returns a collection of Splunk indexes. + * + * @param args Collection arguments that specify the number of entities to + * return and how to sort them. See {@link IndexCollectionArgs}. + * @return A collection of indexes. + */ + // NOTE: This overload exists primarily to provide better documentation + // for the "args" parameter. + public IndexCollection getIndexes(IndexCollectionArgs args) { + return getIndexes((Args)args); + } + + /** + * Returns a collection of Splunk indexes. + * + * @param args Collection arguments that specify the number of entities to + * return and how to sort them. See {@link IndexCollectionArgs}. + * @return A collection of indexes. + */ + public IndexCollection getIndexes(Args args) { + return new IndexCollection(this, args); + } + + /** + * Returns information about the Splunk service. + * + * @return Splunk service information. + */ + public ServiceInfo getInfo() { + return new ServiceInfo(this); + } + + /** + * Returns list of all applicable Cluster Master Hosts for the SearchHead Service. + * + * @return List of Cluster Master Host(s). + */ + public List<String> getClusterMasters(){ + Entity caps = new Entity(this, "cluster/config"); + List<String> hosts = new ArrayList<>(); + try { + String clusterMasterURIs = caps.getString("master_uri"); + URL clusterMasterUrl; + //for multi-cluster environment, there might be more than cluster master for the searchHead + if(clusterMasterURIs.contains(",")){ + String[] masterURIs = clusterMasterURIs.split(","); + for(String uri : masterURIs){ + clusterMasterUrl = new URL(uri); + hosts.add(clusterMasterUrl.getHost()); + } + }else { + clusterMasterUrl = new URL(clusterMasterURIs); + hosts.add(clusterMasterUrl.getHost()); + } + return hosts; + } catch (MalformedURLException e) { + e.printStackTrace(); + } + return hosts; + } + + /** + * Returns a collection of configured inputs. + * + * @return A collection of inputs. + */ + public InputCollection getInputs() { + return getInputs(null); + } + + /** + * Returns a collection of configured inputs. + * + * @param args Collection arguments that specify the number of entities to + * return and how to sort them. See {@link CollectionArgs}. + * @return A collection of inputs. + */ + public InputCollection getInputs(Args args) { + return new InputCollection(this, args); + } + + /** + * Returns a collection of current search jobs. + * + * @return A collection of search jobs. + */ + public JobCollection getJobs() { + return getJobs((CollectionArgs)null); + } + + /** + * Returns a collection of current search jobs. + * + * @param args Collection arguments that specify the number of entities to + * return and how to sort them. See {@link CollectionArgs}. + * @return A collection of search jobs. + */ + // NOTE: This overload exists primarily to provide better documentation + // for the "args" parameter. + public JobCollection getJobs(CollectionArgs args) { + return getJobs((Args)args); + } + + /** + * Returns a collection of current search jobs. + * + * @param args Collection arguments that specify the number of entities to + * return and how to sort them. See {@link CollectionArgs}. + * @return A collection of search jobs. + */ + public JobCollection getJobs(Args args) { + return new JobCollection(this, args); + } + + /** + * Returns a Job by the provided sid. + * + * @param sid The sid for a job. + * @return A Job. + */ + public Job getJob(String sid) { + return new Job(this, JobCollection.REST_PATH + "/" + sid); + } + + /** + * Returns a collection of license group configurations. + * + * @return A collection of license group configurations. + */ + public EntityCollection<LicenseGroup> getLicenseGroups() { + return getLicenseGroups(null); + } + + /** + * Returns a collection of license group configurations. + * + * @param args Collection arguments that specify the number of entities to + * return and how to sort them. See {@link CollectionArgs}. + * @return A collection of license group configurations. + */ + public EntityCollection<LicenseGroup> getLicenseGroups(Args args) { + return new EntityCollection<>( + this, "licenser/groups", LicenseGroup.class, args); + } + + /** + * Returns a collection of messages from the licenser. + * + * @return A collection of licenser messages. + */ + public EntityCollection<LicenseMessage> getLicenseMessages() { + return getLicenseMessages(null); + } + + /** + * Returns a collection of messages from the licenser. + * + * @param args Collection arguments that specify the number of entities to + * return and how to sort them. See {@link CollectionArgs}. + * @return A collection of licenser messages. + */ + public EntityCollection<LicenseMessage> getLicenseMessages(Args args) { + return new EntityCollection<>( + this, "licenser/messages", LicenseMessage.class, args); + } + + /** + * Returns the current owner context for this {@code Service} instance. + * A value of {@code "-"} indicates a wildcard, and a {@code null} value + * indicates no owner context. + * + * @return The current owner context. + */ + public String getOwner() { + return this.owner; + } + + /** + * Returns a collection of licenser pool configurations. + * + * @return A collection of licenser pool configurations. + */ + public LicensePoolCollection getLicensePools() { + return getLicensePools(null); + } + + /** + * Returns a collection of licenser pool configurations. + * + * @param args Collection arguments that specify the number of entities to + * return and how to sort them. See {@link CollectionArgs}. + * @return A collection of licenser pool configurations. + */ + public LicensePoolCollection getLicensePools(Args args) { + return new LicensePoolCollection(this, args); + } + + /** + * Returns a collection of slaves reporting to this license master. + * + * @return A collection of licenser slaves. + */ + public EntityCollection<LicenseSlave> getLicenseSlaves() { + return getLicenseSlaves(null); + } + + /** + * Returns a collection of slaves reporting to this license master. + * + * @param args Collection arguments that specify the number of entities to + * return and how to sort them. See {@link CollectionArgs}. + * @return A collection of licenser slaves. + */ + public EntityCollection<LicenseSlave> getLicenseSlaves(Args args) { + return new EntityCollection<>( + this, "licenser/slaves", LicenseSlave.class, args); + } + + /** + * Returns a collection of license stack configurations. + * + * @return A collection of license stack configurations. + */ + public EntityCollection<LicenseStack> getLicenseStacks() { + return getLicenseStacks(null); + } + + /** + * Returns a collection of license stack configurations. + * + * @param args Collection arguments that specify the number of entities to + * return and how to sort them. See {@link CollectionArgs}. + * @return A collection of license stack configurations. + */ + public EntityCollection<LicenseStack> getLicenseStacks(Args args) { + return new EntityCollection<>( + this, "licenser/stacks", LicenseStack.class, args); + } + + /** + * Returns a collection of licenses for this service. + * + * @return A collection of licenses. + */ + public EntityCollection<License> getLicenses() { + return getLicenses(null); + } + + /** + * Returns a collection of licenses for this service. + * + * @param args Collection arguments that specify the number of entities to + * return and how to sort them. See {@link CollectionArgs}. + * @return A collection of licenses. + */ + public EntityCollection<License> getLicenses(Args args) { + return new EntityCollection<>( + this, "licenser/licenses", License.class, args); + } + + /** + * Returns a collection of service logging categories and their status. + * + * @return A collection of logging categories. + */ + public EntityCollection<Logger> getLoggers() { + return getLoggers(null); + } + + /** + * Returns a collection of service logging categories and their status. + * + * @param args Collection arguments that specify the number of entities to + * return and how to sort them. See {@link CollectionArgs}. + * @return A collection of logging categories. + */ + public EntityCollection<Logger> getLoggers(Args args) { + return new EntityCollection<>( + this, "server/logger", Logger.class, args); + } + + /** + * Returns a collection of system messages. + * + * @return A collection of system messages. + */ + public MessageCollection getMessages() { + return getMessages(null); + } + + /** + * Returns a collection of system messages. + * + * @param args Collection arguments that specify the number of entities to + * return and how to sort them. See {@link CollectionArgs}. + * @return A collection of system messages. + */ + public MessageCollection getMessages(Args args) { + return new MessageCollection(this, args); + } + + /** + * Returns a collection of modular inputs. + * + * @return A collection of modular inputs. + */ + public ResourceCollection<ModularInputKind> getModularInputKinds() { + return getModularInputKinds(null); + } + + /** + * Returns a collection of modular inputs. + * + * @param args Collection arguments that specify the number of entities to + * return and how to sort them. See {@link CollectionArgs}. + * @return A collection of modular inputs. + */ + public ResourceCollection<ModularInputKind> getModularInputKinds(Args args) { + return new ResourceCollection<>( + this, "data/modular-inputs", ModularInputKind.class, args); + } + + /** + * Returns global TCP output properties. + * + * @return Global TCP output properties. + */ + public OutputDefault getOutputDefault() { + return new OutputDefault(this); + } + + /** + * Returns a collection of output group configurations. + * + * @return A collection of output group configurations. + */ + public EntityCollection<OutputGroup> getOutputGroups() { + return getOutputGroups(null); + } + + /** + * Returns a collection of output group configurations. + * + * @param args Collection arguments that specify the number of entities to + * return and how to sort them. See {@link CollectionArgs}. + * @return A collection of output group configurations. + */ + public EntityCollection<OutputGroup> getOutputGroups(Args args) { + return new EntityCollection<>( + this, "data/outputs/tcp/group", OutputGroup.class, args); + } + + /** + * Returns a collection of data-forwarding configurations. + * + * @return A collection of data-forwarding configurations. + */ + public EntityCollection<OutputServer> getOutputServers() { + return getOutputServers(null); + } + + /** + * Returns a collection of data-forwarding configurations. + * + * @param args Collection arguments that specify the number of entities to + * return and how to sort them. See {@link CollectionArgs}. + * @return A collection of data-forwarding configurations. + */ + public EntityCollection<OutputServer> getOutputServers(Args args) { + return new EntityCollection<>( + this, "data/outputs/tcp/server", OutputServer.class, args); + } + + /** + * Returns a collection of configurations for forwarding data in standard + * syslog format. + * + * @return A collection of syslog forwarders. + */ + public EntityCollection<OutputSyslog> getOutputSyslogs() { + return getOutputSyslogs(null); + } + + /** + * Returns a collection of configurations for forwarding data in standard + * syslog format. + * + * @param args Collection arguments that specify the number of entities to + * return and how to sort them. See {@link CollectionArgs}. + * @return A collection of syslog forwarders. + */ + public EntityCollection<OutputSyslog> getOutputSyslogs(Args args) { + return new EntityCollection<>( + this, "data/outputs/tcp/syslog", OutputSyslog.class, args); + } + + /** + * Returns the current password that was used to authenticate the session. + * + * @return The current password. + */ + public String getPassword() { + return this.password; + } + + /** + * Returns a collection of passwords. This collection is used for managing + * secure credentials. + * + * @return A collection of passwords. + */ + public PasswordCollection getPasswords() { + return getPasswords(null); + } + + /** + * Returns a collection of passwords. This collection is used for managing + * secure credentials. + * + * @param args Collection arguments that specify the number of entities to + * return and how to sort them. See {@link CollectionArgs}. + * @return A collection of passwords. + */ + public PasswordCollection getPasswords(Args args) { + return new PasswordCollection(this, args); + } + + /** + * Returns the receiver object for the Splunk service. + * + * @return A Splunk receiver object. + */ + public Receiver getReceiver() { + return new Receiver(this); + } + + /** + * Returns a collection of Splunk user roles. + * + * @return A collection of user roles. + */ + public EntityCollection<Role> getRoles() { + return getRoles(null); + } + + /** + * Returns a collection of Splunk user roles. + * + * @param args Collection arguments that specify the number of entities to + * return and how to sort them. See {@link CollectionArgs}. + * @return A collection of user roles. + */ + public EntityCollection<Role> getRoles(Args args) { + return new EntityCollection<>( + this, "authorization/roles", Role.class, args); + } + + /** + * Returns a collection of saved searches. + * + * @return A collection of saved searches. + */ + public SavedSearchCollection getSavedSearches() { + return getSavedSearches((SavedSearchCollectionArgs)null); + } + + /** + * Returns a collection of saved searches. + * + * @param args Collection arguments that specify the number of entities to + * return and how to sort them. See {@link SavedSearchCollectionArgs}. + * @return A collection of saved searches. + */ + // NOTE: This overload exists primarily to provide better documentation + // for the "args" parameter. + public SavedSearchCollection getSavedSearches(SavedSearchCollectionArgs args) { + return getSavedSearches((Args)args); + } + + /** + * Returns a collection of saved searches. + * + * @param args Collection arguments that specify the number of entities to + * return and how to sort them. See {@link CollectionArgs}. + * @return A collection of saved searches. + */ + public SavedSearchCollection getSavedSearches(Args args) { + return new SavedSearchCollection(this, args); + } + + /** + * Returns a Saved Search by the provided title key. + * + * @param title The title for a job. + * @return A SavedSearch. + */ + public SavedSearch getSavedSearch(String title) { + return new SavedSearch(this, JobCollection.REST_PATH + "/" + title); + } + + /** + * Returns service configuration information for an instance of Splunk. + * + * @return Service configuration information. + */ + public Settings getSettings() { + return new Settings(this); + } + + /** + * Returns the current session token. Session tokens can be shared across + * multiple {@code Service} instances. + * + * @return The session token. + */ + public String getToken() { + return this.token; + } + + /** + * Returns a collection of in-progress oneshot uploads. + * + * @return A collection of in-progress oneshot uploads + */ + public EntityCollection<Upload> getUploads() { + return getUploads(null); + } + + /** + * Returns a collection of in-progress oneshot uploads. + * + * @param namespace This collection's namespace; there are no other + * optional arguments for this endpoint. + * @return A collection of in-progress oneshot uploads + */ + public EntityCollection<Upload> getUploads(Args namespace) { + return new EntityCollection<>( + this, "data/inputs/oneshot", Upload.class, namespace); + } + + /** + * Returns the Splunk account username that was used to authenticate the + * current session. + * + * @return The current username. + */ + public String getUsername() { + return this.username; + } + + /** + * Returns a collection of Splunk users. + * + * @return A collection of users. + */ + public UserCollection getUsers() { + return getUsers(null); + } + + /** + * Returns a collection of Splunk users. + * + * @param args Collection arguments that specify the number of entities to + * return and how to sort them. See {@link CollectionArgs}. + * @return A collection of users. + */ + public UserCollection getUsers(Args args) { + return new UserCollection(this, args); + } + + /** + * Authenticates the {@code Service} instance with the username and password + * that were specified when the instance was created. + * + * Three cases: + * 1. If we have a cookie, but are missing username and/or password, login is noop + * 2. If we don't have a cookie, and are missing username and/or password we can't login + * 3. Otherwise login as usual + * + * @return The current {@code Service} instance. + */ + public Service login() { + if (this.cookieStore.hasSplunkAuthCookie() && (this.username == null || this.password == null)) { + return this; + } + else if (this.username == null || this.password == null) { + throw new IllegalStateException("Missing username or password."); + } + else { + return login(this.username, this.password); + } + } + + /** + * Authenticates the {@code Service} instance with a specified username and + * password. Note that these values override any previously-set values for + * username and password. + * + * @param username The Splunk account username. + * @param password The password for the username. + * @return The current {@code Service} instance. + */ + public Service login(String username, String password) { + this.username = username; + this.password = password; + + Args args = new Args(); + args.put("username", username); + args.put("password", password); + args.put("cookie", "1"); + ResponseMessage response = post("/services/auth/login", args); + String sessionKey = Xml.parse(response.getContent()) + .getElementsByTagName("sessionKey") + .item(0) + .getTextContent(); + this.token = "Splunk " + sessionKey; + ServiceInfo serviceInfoEntity = this.getInfo(); + this.version = serviceInfoEntity.getVersion(); + this.instanceType = serviceInfoEntity.getInstanceType(); + if (versionCompare("4.3") >= 0) + this.passwordEndPoint = "storage/passwords"; + + return this; + } + + /** + * Forgets the current session token. + * + * @return The current {@code Service} instance. + */ + public Service logout() { + this.token = null; + this.removeAllCookies(); + return this; + } + + /** + * Creates a oneshot synchronous search. + * + * @param query The search query. + * @return The search results. + */ + public InputStream oneshotSearch(String query) { + return oneshotSearch(query, null); + } + + /** + * Creates a oneshot synchronous search using search arguments. + * + * @param query The search query. + * @param args The search arguments:<ul> + * <li>"output_mode": Specifies the output format of the results (XML, JSON, + * or CSV).</li> + * <li>"earliest_time": Specifies the earliest time in the time range to + * search. The time string can be a UTC time (with fractional seconds), a + * relative time specifier (to now), or a formatted time string.</li> + * <li>"latest_time": Specifies the latest time in the time range to search. + * The time string can be a UTC time (with fractional seconds), a relative + * time specifier (to now), or a formatted time string.</li> + * <li>"rf": Specifies one or more fields to add to the search.</li></ul> + * @return The search results. + */ + public InputStream oneshotSearch(String query, Map args) { + args = Args.create(args); + args.put("search", query); + args.put("exec_mode", "oneshot"); + + // By default, don't highlight search terms in the search output. + if (!args.containsKey("segmentation")) { + args.put("segmentation", "none"); + } + + ResponseMessage response = post(JobCollection.REST_PATH, args); + return response.getContent(); + } + + /** + * Creates a oneshot synchronous search using search arguments. + * + * @param query The search query. + * @param args The search arguments:<ul> + * <li>"output_mode": Specifies the output format of the results (XML, JSON, + * or CSV).</li> + * <li>"earliest_time": Specifies the earliest time in the time range to + * search. The time string can be a UTC time (with fractional seconds), a + * relative time specifier (to now), or a formatted time string.</li> + * <li>"latest_time": Specifies the latest time in the time range to search. + * The time string can be a UTC time (with fractional seconds), a relative + * time specifier (to now), or a formatted time string.</li> + * <li>"rf": Specifies one or more fields to add to the search.</li></ul> + * @return The search results. + */ + public InputStream oneshotSearch(String query, Args args) { + return oneshotSearch(query, (Map<String, Object>)args); + } + + /** + * Opens a raw socket to this service. + * + * @param port The port to open. This port must already have been + * created as an allowable TCP input to the service. + * @return The socket. + * @throws java.io.IOException The IOException instance + */ + public Socket open(int port) throws IOException { + return new Socket(this.host, port); + } + + /** + * Parses a search query and returns a semantic map for the search in JSON + * format. + * + * @param query The search query. + * @return The parse response message. + */ + public ResponseMessage parse(String query) { + return parse(query, null); + } + + /** + * Parses a search query with additional arguments and returns a semantic + * map for the search in JSON format. + * + * @param query The search query. + * @param args Additional parse arguments. + * @return The parse response message. + */ + public ResponseMessage parse(String query, Map args) { + args = Args.create(args).add("q", query); + + if(enableV2SearchApi()) + return post("search/v2/parser", args); + else + return get("search/parser", args); + } + + /** + * Restarts the service. The service will be unavailable until it has + * successfully restarted. + * + * @return The restart response message. + */ + public ResponseMessage restart() { + return post("server/control/restart"); + } + + /** + * Creates an asynchronous search using the given query. Use this + * method for simple searches. + * + * @param query The search query. + * @return The search job. + */ + public Job search(String query) { + return search(query, null); + } + + /** + * Creates an asynchronous search job using the given query and + * search arguments. + * + * @param query The search query. + * @param args The search arguments. + * @return The search job. + */ + public Job search(String query, Map<String, Object> args) { + args = Args.create(args); + + return this.getJobs().create(query, args); + } + + /** + * Issues an HTTP request against the service using a request path and + * message. + * This method overrides the base {@code HttpService.send} method + * and applies the Splunk authorization header, which is required for + * authenticated interactions with the Splunk service. + * + * @param path The request path. + * @param request The request message. + * @return The HTTP response. + */ + @Override public ResponseMessage send(String path, RequestMessage request) { + // cookieStore is a protected member of HttpService + if (token != null && !cookieStore.hasSplunkAuthCookie() ) { + request.getHeader().put("Authorization", token); + } + ResponseMessage responseMessage = super.send(fullpath(path), request); + if(responseMessage.getStatus() == 401 && (this.autologin && this.username!= null && this.password != null)){ + // Executing re-login to renew the session token. + this.login(this.username, this.password); + responseMessage = super.send(fullpath(path), request); + }else if(responseMessage.getStatus() >= 400){ + //if autologin is not set to true or username/password is not set, throw HTTPException + throw HttpException.create(responseMessage); + } + return responseMessage; + } + + /** + * Provides a session token for use by this {@code Service} instance. + * Session tokens can be shared across multiple {@code Service} instances. + * + * @param value The session token, which is a basic authorization header in + * the format "Basic <i>sessiontoken</i>", where <i>sessiontoken</i> is the + * Base64-encoded "username:password" string. + */ + public void setToken(String value) { + this.token = value; + } + + /** + * Provides a session token having <b>Splunk</b> added before token. + * This method is specifically used when user just have token value. + * + * @param value The token value + */ + public void setSplunkToken(String value) { + this.token = value.contains("Splunk") ? value : "Splunk " + value; + } + + /** + * Provides a session token having <b>Bearer</b> added before token. + * This method is specifically used when user just have token value. + * + * @param value The token value + */ + public void setBearerToken(String value) { + this.token = value.contains("Splunk") || value.contains("Bearer") ? value : "Bearer " + value; + } + + + public boolean enableV2SearchApi(){ + if(null == this.instanceType){ + this.instanceType = this.getInfo().getInstanceType(); + } + if(this.instanceType.equalsIgnoreCase("cloud")) { + return versionIsAtLeast("9.0.2209"); + }else{ + return versionIsAtLeast("9.0.2"); + } + } + + /** + * Returns true if this Splunk instance's version is no earlier than + * the version specified in {@code version}. + * + * So when called on a Splunk 4.3.2 instance: + * * {@code versionIsAtLeast("4.3.2")} is {@code true}. + * * {@code versionIsAtLeast("4.1.0")} is {@code true}. + * * {@code versionIsAtLeast("5.0.0")} is {@code false}. + * + * @param version The version to compare this Splunk instance's version against. + * @return {@code true} if this Splunk instance's version is equal or + * greater than {@code version}; {@code false} otherwise. + */ + boolean versionIsAtLeast(String version) { + return versionCompare(version) >= 0; + } + + /** + * Returns true if this Splunk instance's version is earlier than + * the version specified in {@code version}. + * + * So when called on a Splunk 4.3.2 instance: + * * {@code versionIsEarlierThan("4.3.2")} is {@code false}. + * * {@code versionIsEarlierThan("4.1.0")} is {@code false}. + * * {@code versionIsEarlierThan("5.0.0")} is {@code true}. + * + * @param version The version to compare this Splunk instance's version against. + * @return {@code true} if this Splunk instance's version is less + * than {@code version}; {@code false} otherwise. + */ + boolean versionIsEarlierThan(String version) { + return versionCompare(version) < 0; + } + + /** + * Returns a value indicating how the version of this Splunk instance + * compares to a given version: + * <ul> + * <li>{@code -1 if this version < the given version}</li> + * <li>{@code 0 if this version = the given version}</li> + * <li>{@code 1 if this version > the given version}</li> + * </ul> + * + * @param otherVersion The other version to compare to. + * @return -1 if this version is less than, 0 if this version is equal to, + * or 1 if this version is greater than the given version. + */ + public int versionCompare(String otherVersion) { + if(null == this.version){ + this.version = this.getInfo().getVersion(); + } + String[] components1 = this.version.split("\\."); + String[] components2 = otherVersion.split("\\."); + int numComponents = Math.max(components1.length, components2.length); + + for (int i = 0; i < numComponents; i++) { + int c1 = (i < components1.length) + ? Integer.parseInt(components1[i], 10) : 0; + int c2 = (i < components2.length) + ? Integer.parseInt(components2[i], 10) : 0; + if (c1 < c2) { + return -1; + } else if (c1 > c2) { + return 1; + } + } + return 0; + } +} diff --git a/splunk/src/main/java/com/splunk/Settings.java b/splunk/src/main/java/com/splunk/Settings.java index 3cc28e55..979d3458 100644 --- a/splunk/src/main/java/com/splunk/Settings.java +++ b/splunk/src/main/java/com/splunk/Settings.java @@ -271,7 +271,7 @@ public void setTrustedIP(String trustedIP) { */ @Override public void update(Map<String, Object> args) { // Merge cached setters and live args together before updating. - HashMap<String, Object> mergedArgs = new HashMap<String, Object>(); + HashMap<String, Object> mergedArgs = new HashMap<>(); mergedArgs.putAll(toUpdate); mergedArgs.putAll(args); service.post(path + "/settings", mergedArgs); diff --git a/splunk/src/main/java/com/splunk/SimpleCookieStore.java b/splunk/src/main/java/com/splunk/SimpleCookieStore.java index 4fd60664..a4956f98 100644 --- a/splunk/src/main/java/com/splunk/SimpleCookieStore.java +++ b/splunk/src/main/java/com/splunk/SimpleCookieStore.java @@ -21,7 +21,6 @@ import java.net.HttpCookie; import java.util.Map; import java.util.HashMap; -import java.lang.StringBuilder; /** * The {@code SimpleCookieStore} class stores cookies for authentication. @@ -30,7 +29,7 @@ class SimpleCookieStore { public static final String SPLUNK_AUTH_COOKIE = "splunkd_"; - private Map<String, String> cookieJar = new HashMap<String, String>(); + private Map<String, String> cookieJar = new HashMap<>(); /** * Adds cookies from a "Set-Cookie" header to the cookie store. * diff --git a/splunk/src/main/java/com/splunk/StreamIterableBase.java b/splunk/src/main/java/com/splunk/StreamIterableBase.java index 8c423d3d..4bcb0617 100644 --- a/splunk/src/main/java/com/splunk/StreamIterableBase.java +++ b/splunk/src/main/java/com/splunk/StreamIterableBase.java @@ -1,94 +1,94 @@ -/* - * 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.io.IOException; -import java.util.Iterator; -import java.util.NoSuchElementException; - -/** - * Helper class for iterator over readers that only support a get operation - * with null return indicating the end. - * @param <T> Type of elements. - */ -abstract class StreamIterableBase<T> implements Iterable<T> { - private T cachedElement; - private boolean nextElementCached; - - public Iterator<T> iterator() { - - return new Iterator<T>() { - - public boolean hasNext() { - cacheNextElement(); - return cachedElement != null; - } - - public T next() { - cacheNextElement(); - // Once reaching the end, don't advance any more. - // Otherwise underlying reader may throw - // which can be confusing. - if (cachedElement == null) { - throw new NoSuchElementException(); - } - else { - nextElementCached = false; - } - return cachedElement; - } - - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } - - /** - * Get the next element. - * @return null if the end is reached. - * @throws IOException The IOException instance - */ - abstract T getNextElement() throws IOException; - - /** - * Interrupt the iteration by setting the iterator to - * either the initial state or the end state. - * @param hasMoreResults Whether or not there are more results. - */ - void resetIteration(boolean hasMoreResults) { - // Throw away any not-null cached element. - cachedElement = null; - // If there's no more results, i.e., the end is reached, - // set nextElementCached to true so that - // the iterator will not try to get the next element. - // Otherwise, if getNextElement is called by the iterator, - // the underlying reader may throw which can be confusing. - nextElementCached = !hasMoreResults; - } - - private void cacheNextElement() { - if (!nextElementCached) { - try { - cachedElement = getNextElement(); - } catch (IOException e) { - throw new RuntimeException(e); - } - nextElementCached = true; - } - } -} +/* + * 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.io.IOException; +import java.util.Iterator; +import java.util.NoSuchElementException; + +/** + * Helper class for iterator over readers that only support a get operation + * with null return indicating the end. + * @param <T> Type of elements. + */ +abstract class StreamIterableBase<T> implements Iterable<T> { + private T cachedElement; + private boolean nextElementCached; + + public Iterator<T> iterator() { + + return new Iterator<T>() { + + public boolean hasNext() { + cacheNextElement(); + return cachedElement != null; + } + + public T next() { + cacheNextElement(); + // Once reaching the end, don't advance any more. + // Otherwise underlying reader may throw + // which can be confusing. + if (cachedElement == null) { + throw new NoSuchElementException(); + } + else { + nextElementCached = false; + } + return cachedElement; + } + + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + + /** + * Get the next element. + * @return null if the end is reached. + * @throws IOException The IOException instance + */ + abstract T getNextElement() throws IOException; + + /** + * Interrupt the iteration by setting the iterator to + * either the initial state or the end state. + * @param hasMoreResults Whether or not there are more results. + */ + void resetIteration(boolean hasMoreResults) { + // Throw away any not-null cached element. + cachedElement = null; + // If there's no more results, i.e., the end is reached, + // set nextElementCached to true so that + // the iterator will not try to get the next element. + // Otherwise, if getNextElement is called by the iterator, + // the underlying reader may throw which can be confusing. + nextElementCached = !hasMoreResults; + } + + private void cacheNextElement() { + if (!nextElementCached) { + try { + cachedElement = getNextElement(); + } catch (IOException e) { + throw new RuntimeException(e); + } + nextElementCached = true; + } + } +} diff --git a/splunk/src/main/java/com/splunk/TcpInput.java b/splunk/src/main/java/com/splunk/TcpInput.java index 29faa6b5..741a52da 100644 --- a/splunk/src/main/java/com/splunk/TcpInput.java +++ b/splunk/src/main/java/com/splunk/TcpInput.java @@ -61,16 +61,10 @@ public Socket attach() throws IOException { * @throws IOException The IOException instance */ public void attachWith(ReceiverBehavior behavior) throws IOException { - Socket socket = null; - OutputStream output = null; - try { - socket = attach(); - output = socket.getOutputStream(); + try (Socket socket = attach(); + OutputStream output = socket.getOutputStream();) { behavior.run(output); output.flush(); - } finally { - if (output != null) { output.close(); } - if (socket != null) { socket.close(); } } } @@ -256,18 +250,10 @@ public void setIndex(String index) { * @throws IOException The IOException instance */ public void submit(String eventBody) throws IOException { - Socket socket = null; - OutputStream output = null; - try { - socket = attach(); - output = socket.getOutputStream(); + try (Socket socket = attach(); + OutputStream output = socket.getOutputStream();) { output.write(eventBody.getBytes("UTF-8")); output.flush(); - output.close(); - socket.close(); - } finally { - if (output != null) { output.close(); } - if (socket != null) { socket.close(); } } } diff --git a/splunk/src/main/java/com/splunk/TimestampBinning.java b/splunk/src/main/java/com/splunk/TimestampBinning.java index de3cfe04..d0dbc55f 100644 --- a/splunk/src/main/java/com/splunk/TimestampBinning.java +++ b/splunk/src/main/java/com/splunk/TimestampBinning.java @@ -40,4 +40,4 @@ public enum TimestampBinning { SECOND { public String toString() { return "second"; } } -}; +} diff --git a/splunk/src/main/java/com/splunk/UdpInput.java b/splunk/src/main/java/com/splunk/UdpInput.java index baa6ff7d..1b5b440c 100644 --- a/splunk/src/main/java/com/splunk/UdpInput.java +++ b/splunk/src/main/java/com/splunk/UdpInput.java @@ -260,12 +260,12 @@ public void setSourceType(String sourcetype) { * @throws IOException The IOException instance */ public void submit(String eventBody) throws IOException { - DatagramSocket socket = new DatagramSocket(); - InetAddress address = InetAddress.getByName(this.service.getHost()); - int port = this.getPort(); - byte[] buffer = eventBody.getBytes("UTF-8"); - DatagramPacket packet = new DatagramPacket(buffer, buffer.length, address, port); - socket.send(packet); - socket.close(); + try(DatagramSocket socket = new DatagramSocket()){ + InetAddress address = InetAddress.getByName(this.service.getHost()); + int port = this.getPort(); + byte[] buffer = eventBody.getBytes("UTF-8"); + DatagramPacket packet = new DatagramPacket(buffer, buffer.length, address, port); + socket.send(packet); + } } } diff --git a/splunk/src/main/java/com/splunk/Util.java b/splunk/src/main/java/com/splunk/Util.java index dc9b9d10..f11c6bc1 100644 --- a/splunk/src/main/java/com/splunk/Util.java +++ b/splunk/src/main/java/com/splunk/Util.java @@ -16,7 +16,6 @@ package com.splunk; -import java.io.File; import java.util.Arrays; import java.util.List; diff --git a/splunk/src/main/java/com/splunk/Value.java b/splunk/src/main/java/com/splunk/Value.java index 812bfcad..a4c2d333 100644 --- a/splunk/src/main/java/com/splunk/Value.java +++ b/splunk/src/main/java/com/splunk/Value.java @@ -39,9 +39,9 @@ static boolean toBoolean(String value) { return false; if (value.equals("1")) return true; - if (value.toLowerCase().equals("false")) + if (value.equalsIgnoreCase("false")) return false; - if (value.toLowerCase().equals("true")) + if (value.equalsIgnoreCase("true")) return true; String message = String.format("Value error: '%s'", value); throw new RuntimeException(message); diff --git a/splunk/src/main/java/com/splunk/modularinput/Argument.java b/splunk/src/main/java/com/splunk/modularinput/Argument.java index 1a171a60..88b4b776 100755 --- a/splunk/src/main/java/com/splunk/modularinput/Argument.java +++ b/splunk/src/main/java/com/splunk/modularinput/Argument.java @@ -31,7 +31,7 @@ public class Argument { private static DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); - public enum DataType { BOOLEAN, NUMBER, STRING }; + public enum DataType { BOOLEAN, NUMBER, STRING } // Name used to identify this argument in Splunk. protected String name; diff --git a/splunk/src/main/java/com/splunk/modularinput/EventWriter.java b/splunk/src/main/java/com/splunk/modularinput/EventWriter.java index c6ce3425..3a8f9449 100755 --- a/splunk/src/main/java/com/splunk/modularinput/EventWriter.java +++ b/splunk/src/main/java/com/splunk/modularinput/EventWriter.java @@ -21,11 +21,13 @@ import javax.xml.stream.XMLOutputFactory; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamWriter; -import javax.xml.transform.*; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import java.io.*; -import java.util.logging.Level; /** * The {@code EventWriter} class encapsulates writing events and error messages to Splunk from a modular input. diff --git a/splunk/src/main/java/com/splunk/modularinput/InputDefinition.java b/splunk/src/main/java/com/splunk/modularinput/InputDefinition.java old mode 100755 new mode 100644 index f7431e78..e18bdfae --- a/splunk/src/main/java/com/splunk/modularinput/InputDefinition.java +++ b/splunk/src/main/java/com/splunk/modularinput/InputDefinition.java @@ -49,8 +49,8 @@ public class InputDefinition { // Package private on purpose InputDefinition() { - inputs = new HashMap<String, Map<String, Parameter>>(); - metadata = new HashMap<String, String>(); + inputs = new HashMap<>(); + metadata = new HashMap<>(); } /** @@ -144,7 +144,7 @@ public String getSessionKey() { * @param parameters A collection of {@code Parameter} objects giving the settings for this input. */ public void addInput(String name, Collection<Parameter> parameters) { - Map<String, Parameter> paramMap = new HashMap<String, Parameter>(); + Map<String, Parameter> paramMap = new HashMap<>(); for (Parameter p : parameters) { paramMap.put(p.getName(), p); @@ -211,10 +211,9 @@ public static InputDefinition parseDefinition(InputStream stream) throws ParserC @Override public boolean equals(Object other) { - if (!(other instanceof InputDefinition)) { + if (!(other instanceof InputDefinition that)) { return false; } - InputDefinition that = (InputDefinition)other; return this.metadata.equals(that.metadata) && this.inputs.equals(that.inputs); } diff --git a/splunk/src/main/java/com/splunk/modularinput/MultiValueParameter.java b/splunk/src/main/java/com/splunk/modularinput/MultiValueParameter.java old mode 100755 new mode 100644 index 39c3ce57..6d86ff4e --- a/splunk/src/main/java/com/splunk/modularinput/MultiValueParameter.java +++ b/splunk/src/main/java/com/splunk/modularinput/MultiValueParameter.java @@ -39,7 +39,7 @@ public class MultiValueParameter extends Parameter { // Note: package private constructor by design so parameters cannot be instantiated by the user. MultiValueParameter(String name) { this.name = name; - this.values = new ArrayList<String>(); + this.values = new ArrayList<>(); } /** @@ -67,10 +67,9 @@ void appendValue(String value) { @Override public boolean equals(Object other) { - if (!(other instanceof MultiValueParameter)) { + if (!(other instanceof MultiValueParameter that)) { return false; } else { - MultiValueParameter that = (MultiValueParameter)other; return this.values.equals(that.values) && this.name.equals(that.name); } } diff --git a/splunk/src/main/java/com/splunk/modularinput/Parameter.java b/splunk/src/main/java/com/splunk/modularinput/Parameter.java old mode 100755 new mode 100644 index 23cb8585..1d711bca --- a/splunk/src/main/java/com/splunk/modularinput/Parameter.java +++ b/splunk/src/main/java/com/splunk/modularinput/Parameter.java @@ -60,7 +60,7 @@ public abstract class Parameter { * @throws com.splunk.modularinput.MalformedDataException If the XML does not specify a valid parameter list. */ public static List<Parameter> nodeToParameterList(Node node) throws MalformedDataException { - List<Parameter> parameters = new ArrayList<Parameter>(); + List<Parameter> parameters = new ArrayList<>(); for (Node child = node.getFirstChild(); child != null; child = child.getNextSibling()) { if (child.getNodeType() == Node.TEXT_NODE) { diff --git a/splunk/src/main/java/com/splunk/modularinput/Scheme.java b/splunk/src/main/java/com/splunk/modularinput/Scheme.java old mode 100755 new mode 100644 index b160c22a..1ef388b1 --- a/splunk/src/main/java/com/splunk/modularinput/Scheme.java +++ b/splunk/src/main/java/com/splunk/modularinput/Scheme.java @@ -37,7 +37,7 @@ public class Scheme { private static DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); - public enum StreamingMode { SIMPLE, XML }; + public enum StreamingMode { SIMPLE, XML } // Name of this module input kind. <tt>title</tt> will be used as the URL scheme when // specifying particular modular inputs. For example, if <tt>title</tt> is <tt>"abc"</tt>, @@ -63,7 +63,7 @@ public enum StreamingMode { SIMPLE, XML }; public Scheme(String title) { this.title = title; - this.arguments = new ArrayList<Argument>(); + this.arguments = new ArrayList<>(); } /** @@ -182,7 +182,7 @@ public List<Argument> getArguments() { * list of arguments. */ public void setArguments(List<Argument> arguments) { - this.arguments = new ArrayList<Argument>(arguments); + this.arguments = new ArrayList<>(arguments); } /** diff --git a/splunk/src/main/java/com/splunk/modularinput/Script.java b/splunk/src/main/java/com/splunk/modularinput/Script.java index 96447c73..ac470816 100755 --- a/splunk/src/main/java/com/splunk/modularinput/Script.java +++ b/splunk/src/main/java/com/splunk/modularinput/Script.java @@ -66,7 +66,7 @@ public int run(String[] args, EventWriter eventWriter, InputStream in) { streamEvents(inputDefinition, eventWriter); eventWriter.close(); return 0; - } else if (args[0].toLowerCase().equals("--scheme")) { + } else if (args[0].equalsIgnoreCase("--scheme")) { // Splunk has requested XML specifying the scheme for this modular input. Return it and exit. Scheme scheme = getScheme(); if (scheme == null) { @@ -76,7 +76,7 @@ public int run(String[] args, EventWriter eventWriter, InputStream in) { eventWriter.writeXmlDocument(scheme.toXml()); return 0; } - } else if (args[0].toLowerCase().equals("--validate-arguments")) { + } else if (args[0].equalsIgnoreCase("--validate-arguments")) { NonblockingInputStream stream = new NonblockingInputStream(in); ValidationDefinition validationDefinition = ValidationDefinition.parseDefinition(stream); diff --git a/splunk/src/main/java/com/splunk/modularinput/SingleValueParameter.java b/splunk/src/main/java/com/splunk/modularinput/SingleValueParameter.java old mode 100755 new mode 100644 index 1874a32e..6a33c831 --- a/splunk/src/main/java/com/splunk/modularinput/SingleValueParameter.java +++ b/splunk/src/main/java/com/splunk/modularinput/SingleValueParameter.java @@ -105,10 +105,9 @@ public double getDouble() { @Override public boolean equals(Object other) { - if (!(other instanceof SingleValueParameter)) { + if (!(other instanceof SingleValueParameter that)) { return false; } else { - SingleValueParameter that = (SingleValueParameter)other; return this.getValue().equals(that.getValue()) && this.getName().equals(that.getName()); } } diff --git a/splunk/src/main/java/com/splunk/modularinput/ValidationDefinition.java b/splunk/src/main/java/com/splunk/modularinput/ValidationDefinition.java old mode 100755 new mode 100644 index 3ce60106..72b1be29 --- a/splunk/src/main/java/com/splunk/modularinput/ValidationDefinition.java +++ b/splunk/src/main/java/com/splunk/modularinput/ValidationDefinition.java @@ -38,16 +38,16 @@ public class ValidationDefinition { private Map<String, Parameter> parameters; - private final String serverHostField = "server_host"; - private final String serverUriField = "server_uri"; - private final String checkpointDirField = "checkpoint_dir"; - private final String sessionKeyField = "session_key"; - private final String nameField = "name"; + private static final String serverHostField = "server_host"; + private static final String serverUriField = "server_uri"; + private static final String checkpointDirField = "checkpoint_dir"; + private static final String sessionKeyField = "session_key"; + private static final String nameField = "name"; // Package private on purpose. ValidationDefinition() { super(); - metadata = new HashMap<String, String>(); + metadata = new HashMap<>(); } /** @@ -146,7 +146,7 @@ public String getName() { * @param parameters A list of {@code Parameter} objects giving the proposed configuration. */ public void setParameters(Collection<Parameter> parameters) { - Map<String, Parameter> paramMap = new HashMap<String, Parameter>(); + Map<String, Parameter> paramMap = new HashMap<>(); for (Parameter p : parameters) { paramMap.put(p.getName(), p); } @@ -224,10 +224,9 @@ public static ValidationDefinition parseDefinition(InputStream stream) throws Pa @Override public boolean equals(Object other) { - if (!(other instanceof ValidationDefinition)) { + if (!(other instanceof ValidationDefinition that)) { return false; } - ValidationDefinition that = (ValidationDefinition)other; return this.metadata.equals(that.metadata) && this.parameters.equals(that.parameters); } diff --git a/splunk/src/test/java/com/splunk/ApplicationTest.java b/splunk/src/test/java/com/splunk/ApplicationTest.java index df8afe2a..293e5f81 100644 --- a/splunk/src/test/java/com/splunk/ApplicationTest.java +++ b/splunk/src/test/java/com/splunk/ApplicationTest.java @@ -1,235 +1,234 @@ -/* - * 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 org.junit.*; -import org.w3c.dom.Document; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import javax.xml.parsers.DocumentBuilderFactory; -import java.io.*; - -public class ApplicationTest extends SDKTestCase { - private String applicationName; - private Application application; - - @Before - @Override - public void setUp() throws Exception { - super.setUp(); - - removeTestApplications(); - - applicationName = createTemporaryName(); - application = service.getApplications().create(applicationName); - } - - - @After - @Override - public void tearDown() throws Exception { - removeTestApplications(); - - // Clear the restart message that deleting apps causes in splunkd. - // It's fine to keep going despite it. - clearRestartMessage(); - - super.tearDown(); - } - - private void removeTestApplications() { - final EntityCollection<Application> apps = service.getApplications(); - for (Application app : apps.values()) { - final String appName = app.getName(); - if (appName.startsWith("delete-me")) { - app.remove(); - assertEventuallyTrue(new EventuallyTrueBehavior() { - @Override - public boolean predicate() { - apps.refresh(); - return !apps.containsKey(appName); - } - }); - } - } - } - - @Test - public void testForEmptySetup() { - final String setupXml = application.setup().getSetupXml(); - // Newly created applications now has a setup stub. - Assert.assertTrue(setupXml.contains("stub")); - } - - @Test - public void testForSetupPresent() throws Exception { - if (!hasTestData()) { - System.out.println("WARNING: sdk-app-collection not installed in Splunk; skipping test."); - return; - } - installApplicationFromTestData("has_setup_xml"); - Assert.assertTrue(service.getApplications().containsKey("has_setup_xml")); - Application applicationWithSetupXml = service.getApplications().get("has_setup_xml"); - - ApplicationSetup applicationSetup = applicationWithSetupXml.setup(); - Assert.assertEquals("has_setup_xml", applicationSetup.getName()); - Assert.assertFalse(applicationSetup.getRefresh()); - - String setupXml = applicationSetup.getSetupXml(); - Document parsedSetupXml = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse( - new ByteArrayInputStream(setupXml.getBytes("UTF-8"))); - parsedSetupXml.getDocumentElement().normalize(); - - Assert.assertEquals(parsedSetupXml.getDocumentElement().getNodeName(), "SetupInfo"); - - NodeList blocks = parsedSetupXml.getDocumentElement().getElementsByTagName("block"); - Assert.assertEquals(1, blocks.getLength()); - Node block = blocks.item(0); - Assert.assertEquals("block", block.getNodeName()); - } - - @Test - public void testArchive() { - ApplicationArchive archive = application.archive(); - Assert.assertEquals(applicationName, archive.getAppName()); - { - String filePath = archive.getFilePath(); - Assert.assertTrue(filePath.contains("/") || filePath.contains("\\")); - Assert.assertTrue(filePath.endsWith(applicationName + ".spl")); - } - Assert.assertFalse(archive.getRefresh()); - Assert.assertTrue(archive.getUrl() != null); - } - - @Test - public void testFields() { - // Initially, should be empty. - Assert.assertEquals(null, application.getAuthor()); - Assert.assertTrue(application.getCheckForUpdates()); - Assert.assertFalse(application.isConfigured()); - Assert.assertTrue(application.isVisible()); - Assert.assertFalse(application.stateChangeRequiresRestart()); - Assert.assertFalse(application.getRefresh()); - - String authorString = "Boris the mad baboon"; - application.setAuthor(authorString); - application.setCheckForUpdates(false); - String descriptionString = "Meep the nudebranch!"; - application.setDescription(descriptionString); - String labelString = "Hugga wugga"; - application.setLabel(labelString); - String versionString = "VII"; - application.setVersion(versionString); - application.setConfigured(true); - application.setVisible(false); - - application.update(); - application.refresh(); - - Assert.assertEquals(authorString, application.getAuthor()); - Assert.assertFalse(application.getCheckForUpdates()); - Assert.assertEquals(descriptionString, application.getDescription()); - Assert.assertEquals(labelString, application.getLabel()); - Assert.assertEquals(versionString, application.getVersion()); - Assert.assertTrue(application.isConfigured()); - Assert.assertFalse(application.isVisible()); - } - - @Test - public void testUpdate() { - if (service.getApplications().get("wc") == null) { - System.out.println("WARNING: Must have app wc installed on splunkd to run ApplicationTest.testUpdate"); - return; - } - - // Set the version of wc to something small, - // then wait for splunkd to pull its update information from splunkbase. - - Application gettingStarted = service.getApplications().get("wc"); - String originalVersion = gettingStarted.getVersion(); - try { - // Decrease the app's version - gettingStarted.setVersion("0.1"); - gettingStarted.update(); - - // The easiest way to force Splunk to check for new versions of apps - // is to restart it. Otherwise who knows how long it will be... - uncheckedSplunkRestart(); - gettingStarted = service.getApplications().get("wc"); - - // Wait until Splunk sees that an update for the app is available - // NOTE: This typically takes about 15s - final Application gettingStartedReference = gettingStarted; - assertEventuallyTrue(new EventuallyTrueBehavior() { - { tries = 100; } - @Override - public boolean predicate() { - return gettingStartedReference.getUpdate().getChecksum() != null; - } - }); - - // Verify expected properties of the update - ApplicationUpdate update = gettingStarted.getUpdate(); - Assert.assertEquals("315d8e92a0227aa75bbca1b8f33b4970", update.getChecksum()); - Assert.assertEquals("md5", update.getChecksumType()); - Assert.assertEquals("https://apps.splunk.com/app/1541/", update.getHomepage()); - Assert.assertEquals(39879, update.getSize()); - Assert.assertEquals("wc - word count", update.getUpdateName()); - Assert.assertEquals( - "https://apps.splunk.com/app/1541/package/1.0/none/", - update.getAppUrl() - ); - Assert.assertEquals("1.0", update.getVersion()); - Assert.assertFalse(update.isImplicitIdRequired()); - } finally { - // Restore the app's original version - gettingStarted.setVersion(originalVersion); - gettingStarted.update(); - } - } - - @Test - public void testEmptyUpdate() { - ApplicationUpdate update = application.getUpdate(); - Assert.assertNull(update.getChecksum()); - Assert.assertNull(update.getChecksumType()); - Assert.assertNull(update.getHomepage()); - Assert.assertEquals(-1, update.getSize()); - Assert.assertNull(update.getUpdateName()); - Assert.assertNull(update.getAppUrl()); - Assert.assertNull(update.getVersion()); - Assert.assertFalse(update.isImplicitIdRequired()); - } - - @Test - public void testListApplications() { - boolean found = false; - for (Application app : service.getApplications().values()) { - if (app.getName().equals(applicationName)) { - found = true; - } - } - Assert.assertTrue(found); - } - - @Test - public void testContains() { - Assert.assertTrue(service.getApplications().containsKey(applicationName)); - } - -} +/* + * 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 org.junit.*; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import javax.xml.parsers.DocumentBuilderFactory; +import java.io.*; + +public class ApplicationTest extends SDKTestCase { + private String applicationName; + private Application application; + + @Before + @Override + public void setUp() throws Exception { + super.setUp(); + removeTestApplications(); + + applicationName = createTemporaryName(); + application = service.getApplications().create(applicationName); + } + + + @After + @Override + public void tearDown() throws Exception { + removeTestApplications(); + + // Clear the restart message that deleting apps causes in splunkd. + // It's fine to keep going despite it. + clearRestartMessage(); + + super.tearDown(); + } + + private void removeTestApplications() { + final EntityCollection<Application> apps = service.getApplications(); + for (Application app : apps.values()) { + final String appName = app.getName(); + if (appName.startsWith("delete-me")) { + app.remove(); + assertEventuallyTrue(new EventuallyTrueBehavior() { + @Override + public boolean predicate() { + apps.refresh(); + return !apps.containsKey(appName); + } + }); + } + } + } + + @Test + public void testForEmptySetup() { + final String setupXml = application.setup().getSetupXml(); + // Newly created applications now has a setup stub. + Assert.assertTrue(setupXml.contains("stub")); + } + + @Test + public void testForSetupPresent() throws Exception { + if (!hasTestData()) { + System.out.println("WARNING: sdk-app-collection not installed in Splunk; skipping test."); + return; + } + installApplicationFromTestData("has_setup_xml"); + Assert.assertTrue(service.getApplications().containsKey("has_setup_xml")); + Application applicationWithSetupXml = service.getApplications().get("has_setup_xml"); + + ApplicationSetup applicationSetup = applicationWithSetupXml.setup(); + Assert.assertEquals("has_setup_xml", applicationSetup.getName()); + Assert.assertFalse(applicationSetup.getRefresh()); + + String setupXml = applicationSetup.getSetupXml(); + Document parsedSetupXml = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse( + new ByteArrayInputStream(setupXml.getBytes("UTF-8"))); + parsedSetupXml.getDocumentElement().normalize(); + + Assert.assertEquals("SetupInfo", parsedSetupXml.getDocumentElement().getNodeName()); + + NodeList blocks = parsedSetupXml.getDocumentElement().getElementsByTagName("block"); + Assert.assertEquals(1, blocks.getLength()); + Node block = blocks.item(0); + Assert.assertEquals("block", block.getNodeName()); + } + + @Test + public void testArchive() { + ApplicationArchive archive = application.archive(); + Assert.assertEquals(applicationName, archive.getAppName()); + { + String filePath = archive.getFilePath(); + Assert.assertTrue(filePath.contains("/") || filePath.contains("\\")); + Assert.assertTrue(filePath.endsWith(applicationName + ".spl")); + } + Assert.assertFalse(archive.getRefresh()); + Assert.assertNotNull(archive.getUrl()); + } + + @Test + public void testFields() { + // Initially, should be empty. + Assert.assertEquals(null, application.getAuthor()); + Assert.assertTrue(application.getCheckForUpdates()); + Assert.assertFalse(application.isConfigured()); + Assert.assertTrue(application.isVisible()); + Assert.assertFalse(application.stateChangeRequiresRestart()); + Assert.assertFalse(application.getRefresh()); + + String authorString = "Boris the mad baboon"; + application.setAuthor(authorString); + application.setCheckForUpdates(false); + String descriptionString = "Meep the nudebranch!"; + application.setDescription(descriptionString); + String labelString = "Hugga wugga"; + application.setLabel(labelString); + String versionString = "VII"; + application.setVersion(versionString); + application.setConfigured(true); + application.setVisible(false); + + application.update(); + application.refresh(); + + Assert.assertEquals(authorString, application.getAuthor()); + Assert.assertFalse(application.getCheckForUpdates()); + Assert.assertEquals(descriptionString, application.getDescription()); + Assert.assertEquals(labelString, application.getLabel()); + Assert.assertEquals(versionString, application.getVersion()); + Assert.assertTrue(application.isConfigured()); + Assert.assertFalse(application.isVisible()); + } + + @Test + public void testUpdate() { + if (service.getApplications().get("wc") == null) { + System.out.println("WARNING: Must have app wc installed on splunkd to run ApplicationTest.testUpdate"); + return; + } + + // Set the version of wc to something small, + // then wait for splunkd to pull its update information from splunkbase. + + Application gettingStarted = service.getApplications().get("wc"); + String originalVersion = gettingStarted.getVersion(); + try { + // Decrease the app's version + gettingStarted.setVersion("0.1"); + gettingStarted.update(); + + // The easiest way to force Splunk to check for new versions of apps + // is to restart it. Otherwise who knows how long it will be... + uncheckedSplunkRestart(); + gettingStarted = service.getApplications().get("wc"); + + // Wait until Splunk sees that an update for the app is available + // NOTE: This typically takes about 15s + final Application gettingStartedReference = gettingStarted; + assertEventuallyTrue(new EventuallyTrueBehavior() { + { tries = 100; } + @Override + public boolean predicate() { + return gettingStartedReference.getUpdate().getChecksum() != null; + } + }); + + // Verify expected properties of the update + ApplicationUpdate update = gettingStarted.getUpdate(); + Assert.assertEquals("315d8e92a0227aa75bbca1b8f33b4970", update.getChecksum()); + Assert.assertEquals("md5", update.getChecksumType()); + Assert.assertEquals("https://apps.splunk.com/app/1541/", update.getHomepage()); + Assert.assertEquals(39879, update.getSize()); + Assert.assertEquals("wc - word count", update.getUpdateName()); + Assert.assertEquals( + "https://apps.splunk.com/app/1541/package/1.0/none/", + update.getAppUrl() + ); + Assert.assertEquals("1.0", update.getVersion()); + Assert.assertFalse(update.isImplicitIdRequired()); + } finally { + // Restore the app's original version + gettingStarted.setVersion(originalVersion); + gettingStarted.update(); + } + } + + @Test + public void testEmptyUpdate() { + ApplicationUpdate update = application.getUpdate(); + Assert.assertNull(update.getChecksum()); + Assert.assertNull(update.getChecksumType()); + Assert.assertNull(update.getHomepage()); + Assert.assertEquals(-1, update.getSize()); + Assert.assertNull(update.getUpdateName()); + Assert.assertNull(update.getAppUrl()); + Assert.assertNull(update.getVersion()); + Assert.assertFalse(update.isImplicitIdRequired()); + } + + @Test + public void testListApplications() { + boolean found = false; + for (Application app : service.getApplications().values()) { + if (app.getName().equals(applicationName)) { + found = true; + } + } + Assert.assertTrue(found); + } + + @Test + public void testContains() { + Assert.assertTrue(service.getApplications().containsKey(applicationName)); + } + +} diff --git a/splunk/src/test/java/com/splunk/AtomFeedTest.java b/splunk/src/test/java/com/splunk/AtomFeedTest.java index e534e21a..e334794d 100644 --- a/splunk/src/test/java/com/splunk/AtomFeedTest.java +++ b/splunk/src/test/java/com/splunk/AtomFeedTest.java @@ -90,8 +90,8 @@ public void testAtomFeed() { @Parameterized.Parameters(name="{0}") public static Collection<Object[]> testCases() { - Collection<Object[]> cases = new ArrayList<Object[]>(); - for (String key : (Set<String>)expectedData.keySet()) { + Collection<Object[]> cases = new ArrayList<>(); + for (String key : expectedData.keySet()) { cases.add(new Object[] { key }); } return cases; diff --git a/splunk/src/test/java/com/splunk/CookieTest.java b/splunk/src/test/java/com/splunk/CookieTest.java index d11cda76..d23f3baf 100644 --- a/splunk/src/test/java/com/splunk/CookieTest.java +++ b/splunk/src/test/java/com/splunk/CookieTest.java @@ -224,7 +224,7 @@ public void testHttpServiceWithNoCookie() { } private Map<String, Object> getStandardArgs() { - Map<String, Object> args = new HashMap<String, Object>(); + Map<String, Object> args = new HashMap<>(); args.put("host", (String)command.opts.get("host")); args.put("port", (Integer) command.opts.get("port")); diff --git a/splunk/src/test/java/com/splunk/DataModelTest.java b/splunk/src/test/java/com/splunk/DataModelTest.java index 2a8585e8..4a16ee2b 100644 --- a/splunk/src/test/java/com/splunk/DataModelTest.java +++ b/splunk/src/test/java/com/splunk/DataModelTest.java @@ -443,7 +443,7 @@ public void testCalculations() { Assert.assertEquals("", lc.getComment()); Assert.assertEquals(true, lc.isEditable()); List<LookupDataModelCalculation.LookupFieldMapping> expectedFieldMappings = - new ArrayList<LookupDataModelCalculation.LookupFieldMapping>(); + new ArrayList<>(); expectedFieldMappings.add(new LookupDataModelCalculation.LookupFieldMapping() {{ inputField = "host"; lookupField = "a_lookup_field"; diff --git a/splunk/src/test/java/com/splunk/DeploymentServerTest.java b/splunk/src/test/java/com/splunk/DeploymentServerTest.java index ba75489f..ee8850a6 100644 --- a/splunk/src/test/java/com/splunk/DeploymentServerTest.java +++ b/splunk/src/test/java/com/splunk/DeploymentServerTest.java @@ -29,7 +29,7 @@ public void testDeploymentServer() throws Exception { EntityCollection<DeploymentServer> deploymentServers = service.getDeploymentServers(); - if (deploymentServers.values().size() == 0) { + if (deploymentServers.values().isEmpty()) { System.out.println("WARNING: No DeploymentServer entities to test"); return; } diff --git a/splunk/src/test/java/com/splunk/DeploymentTenantTest.java b/splunk/src/test/java/com/splunk/DeploymentTenantTest.java index 153b1064..c900bf8a 100644 --- a/splunk/src/test/java/com/splunk/DeploymentTenantTest.java +++ b/splunk/src/test/java/com/splunk/DeploymentTenantTest.java @@ -29,7 +29,7 @@ public void testDeploymentTenant() throws Exception { EntityCollection<DeploymentTenant> deploymentTenants = service.getDeploymentTenants(); - if (deploymentTenants.values().size() == 0) { + if (deploymentTenants.values().isEmpty()) { System.out.println("WARNING: No DeploymentTenant entities to test"); return; } diff --git a/splunk/src/test/java/com/splunk/EntityTest.java b/splunk/src/test/java/com/splunk/EntityTest.java index 4760685f..5eaa2063 100644 --- a/splunk/src/test/java/com/splunk/EntityTest.java +++ b/splunk/src/test/java/com/splunk/EntityTest.java @@ -112,6 +112,6 @@ public void testResourceCollection() { Assert.assertTrue(indexes.equals(indexes.items)); Assert.assertTrue(indexes.hashCode() != 0); Assert.assertTrue(indexes.keySet().contains("main")); - Assert.assertTrue(indexes.valueSize("main") == 1); + Assert.assertEquals(1, indexes.valueSize("main")); } } diff --git a/splunk/src/test/java/com/splunk/EventTypesTest.java b/splunk/src/test/java/com/splunk/EventTypesTest.java index 5e98e860..81e16bc7 100644 --- a/splunk/src/test/java/com/splunk/EventTypesTest.java +++ b/splunk/src/test/java/com/splunk/EventTypesTest.java @@ -54,7 +54,7 @@ public void tearDown() throws Exception { @Test public void testList() { EntityCollection<EventType> eventTypes = service.getEventTypes(); - Assert.assertFalse("No event types in system.", eventTypes.size() == 0); + Assert.assertFalse("No event types in system.", eventTypes.isEmpty()); for (EventType eventType : eventTypes.values()) { eventType.getDescription(); diff --git a/splunk/src/test/java/com/splunk/ExportResultsReaderTest.java b/splunk/src/test/java/com/splunk/ExportResultsReaderTest.java index 0c460372..b3367aae 100644 --- a/splunk/src/test/java/com/splunk/ExportResultsReaderTest.java +++ b/splunk/src/test/java/com/splunk/ExportResultsReaderTest.java @@ -52,8 +52,8 @@ public ExportResultsReaderTest(String version) { @Parameterized.Parameters(name="from version {0}") public static Collection<Object[]> testCases() { - Collection<Object[]> cases = new ArrayList<Object[]>(); - for (String version : (Set<String>)expectedData.keySet()) { + Collection<Object[]> cases = new ArrayList<>(); + for (String version : expectedData.keySet()) { cases.add(new Object[] {version}); } return cases; diff --git a/splunk/src/test/java/com/splunk/HttpServiceTest.java b/splunk/src/test/java/com/splunk/HttpServiceTest.java index 283f1b99..231d4842 100644 --- a/splunk/src/test/java/com/splunk/HttpServiceTest.java +++ b/splunk/src/test/java/com/splunk/HttpServiceTest.java @@ -85,7 +85,7 @@ public void testRequestMessage() { Assert.assertTrue(request.checkMethod(request.getMethod())); request.setMethod("POST"); Assert.assertTrue(request.checkMethod(request.getMethod())); - Assert.assertEquals(request.getMethod(), "POST"); + Assert.assertEquals("POST", request.getMethod()); ByteArrayOutputStream stream = new ByteArrayOutputStream(); try { @@ -102,8 +102,8 @@ public void testRequestMessage() { @Test public void testResponseMessage() { ResponseMessage response = new ResponseMessage(200); - Assert.assertEquals(response.getStatus(), 200); - Assert.assertTrue(response.getHeader() != null); + Assert.assertEquals(200, response.getStatus()); + Assert.assertNotNull(response.getHeader()); } @Test(expected = IllegalArgumentException.class) @@ -117,9 +117,10 @@ public void testSSLSocketFactorySetNull(){ public void testSSLSocketFactory() { try { SSLSocketFactory factory = Service.getSSLSocketFactory(); - SSLSocket socket = (SSLSocket) factory.createSocket((String)command.opts.get("host"), 8089); - String[] protocols = socket.getEnabledProtocols(); - Assert.assertTrue(protocols.length > 0); + try (SSLSocket socket = (SSLSocket) factory.createSocket((String)command.opts.get("host"), 8089)) { + String[] protocols = socket.getEnabledProtocols(); + Assert.assertTrue(protocols.length > 0); + } } catch (Exception e) { Assert.assertNull(e); diff --git a/splunk/src/test/java/com/splunk/IndexTest.java b/splunk/src/test/java/com/splunk/IndexTest.java index 56d6670a..00e9696f 100644 --- a/splunk/src/test/java/com/splunk/IndexTest.java +++ b/splunk/src/test/java/com/splunk/IndexTest.java @@ -478,7 +478,7 @@ public boolean predicate() { @Test public void testSubmitOneWithNamespacedService() { - Map<String, Object> opts = new HashMap<String, Object>(command.opts); + Map<String, Object> opts = new HashMap<>(command.opts); opts.put("app", "search"); final Service service = Service.connect(opts); Assert.assertNotNull(service); @@ -757,7 +757,7 @@ public void testUploadArgsFailure() throws Exception{ Assert.fail("Uploading to an index with an index argument? No need for redundancy!"); } catch(Exception e){ - Assert.assertEquals(e.getMessage(), "The 'index' parameter cannot be passed to an index's oneshot upload."); + Assert.assertEquals("The 'index' parameter cannot be passed to an index's oneshot upload.", e.getMessage()); } } @@ -859,8 +859,7 @@ private int getResultCountOfIndex(Service s) { } private int getResultCountOfIndex(Service s, String indexName) { - InputStream results = s.oneshotSearch("search index=" + indexName); - try { + try (InputStream results = s.oneshotSearch("search index=" + indexName)) { ResultsReaderXml resultsReader = new ResultsReaderXml(results); int numEvents = 0; diff --git a/splunk/src/test/java/com/splunk/InputCrudTest.java b/splunk/src/test/java/com/splunk/InputCrudTest.java index d0d3a1f7..79d7a0b0 100644 --- a/splunk/src/test/java/com/splunk/InputCrudTest.java +++ b/splunk/src/test/java/com/splunk/InputCrudTest.java @@ -521,7 +521,7 @@ public void testWindowsPerfmonInputCrud() { Assert.assertEquals(1, windowsPerfmonInput.getCounters().length); Assert.assertTrue(contains(windowsPerfmonInput.getCounters(), "% Privileged Time")); - Assert.assertEquals(windowsPerfmonInput.getIndex(), "main"); + Assert.assertEquals("main", windowsPerfmonInput.getIndex()); Assert.assertTrue(contains(windowsPerfmonInput.getInstances(), "wininit")); Assert.assertEquals(1200, windowsPerfmonInput.getInterval()); Assert.assertEquals("Process", windowsPerfmonInput.getObject()); diff --git a/splunk/src/test/java/com/splunk/LicenseMessageTest.java b/splunk/src/test/java/com/splunk/LicenseMessageTest.java index 3614e0ac..629973a2 100644 --- a/splunk/src/test/java/com/splunk/LicenseMessageTest.java +++ b/splunk/src/test/java/com/splunk/LicenseMessageTest.java @@ -28,7 +28,7 @@ public void testLicenseMessage() throws Exception { EntityCollection<LicenseMessage> licenseMessages = service.getLicenseMessages(); - if (licenseMessages.values().size() == 0) { + if (licenseMessages.values().isEmpty()) { System.out.println("WARNING: No license messages found to test."); return; } diff --git a/splunk/src/test/java/com/splunk/ModularInputKindsTest.java b/splunk/src/test/java/com/splunk/ModularInputKindsTest.java index 8c7d7fff..434f374c 100644 --- a/splunk/src/test/java/com/splunk/ModularInputKindsTest.java +++ b/splunk/src/test/java/com/splunk/ModularInputKindsTest.java @@ -115,7 +115,7 @@ public void testArgDescription() { ModularInputKindArgument arg; - Map<String,String> expectedValues = new HashMap<String,String>(); + Map<String,String> expectedValues = new HashMap<>(); expectedValues.put("key_id", "The key of the system"); expectedValues.put("no_description", null); expectedValues.put("empty_description", null); @@ -143,7 +143,7 @@ public void testArgDataType() { ModularInputKindArgument arg; Map<String,ModularInputKindArgument.Type> expectedValues = - new HashMap<String,ModularInputKindArgument.Type>(); + new HashMap<>(); expectedValues.put("number_field", ModularInputKindArgument.Type.NUMBER); expectedValues.put("boolean_field", ModularInputKindArgument.Type.BOOLEAN); expectedValues.put("string_field", ModularInputKindArgument.Type.STRING); @@ -168,7 +168,7 @@ public void testRequiredOnCreate() { ModularInputKindArgument arg; - Map<String,Boolean> expectedValues = new HashMap<String,Boolean>(); + Map<String,Boolean> expectedValues = new HashMap<>(); expectedValues.put("required_on_create", true); expectedValues.put("not_required_on_create", false); @@ -192,7 +192,7 @@ public void testRequiredOnEdit() { ModularInputKindArgument arg; - Map<String,Boolean> expectedValues = new HashMap<String,Boolean>(); + Map<String,Boolean> expectedValues = new HashMap<>(); expectedValues.put("arg_required_on_edit", true); expectedValues.put("not_required_on_edit", false); @@ -215,7 +215,7 @@ public void testGetArguments() { ModularInputKind test1 = inputKinds.get("test1"); Map<String, ModularInputKindArgument> args = test1.getArguments(); - Set<String> expectedKeys = new HashSet<String>(); + Set<String> expectedKeys = new HashSet<>(); expectedKeys.add("name"); expectedKeys.add("resname"); expectedKeys.add("key_id"); diff --git a/splunk/src/test/java/com/splunk/NamespaceTest.java b/splunk/src/test/java/com/splunk/NamespaceTest.java index 16a332ad..86f653e2 100644 --- a/splunk/src/test/java/com/splunk/NamespaceTest.java +++ b/splunk/src/test/java/com/splunk/NamespaceTest.java @@ -264,12 +264,10 @@ public void testNamespaceConflicts() { Assert.assertEquals(query1, service.getSavedSearches(namespace1).get(savedSearchName).getSearch()); Assert.assertEquals(query2, service.getSavedSearches(namespace2).get(savedSearchName).getSearch()); - try { - service.getSavedSearches(wildcardNamespace).get(savedSearchName).getSearch(); - Assert.fail("Expected SplunkException about multiple keys."); - } catch (SplunkException e) { - - } + service.getSavedSearches(wildcardNamespace).get(savedSearchName).getSearch(); + Assert.fail("Expected SplunkException about multiple keys not Throwns"); + } catch (SplunkException SE){ + Assert.assertNotNull(SE); } finally { if (service.getSavedSearches(namespace1).containsKey(savedSearchName)) { service.getSavedSearches(namespace1).remove(savedSearchName); diff --git a/splunk/src/test/java/com/splunk/OutputDefaultTest.java b/splunk/src/test/java/com/splunk/OutputDefaultTest.java index 55f28389..93b3bb4f 100644 --- a/splunk/src/test/java/com/splunk/OutputDefaultTest.java +++ b/splunk/src/test/java/com/splunk/OutputDefaultTest.java @@ -45,7 +45,7 @@ public void testOutputDefault() throws Exception { // Probe { outputDefault.setMaxQueueSize("1MB"); - Assert.assertEquals(outputDefault.getMaxQueueSize(), "1MB"); + Assert.assertEquals("1MB", outputDefault.getMaxQueueSize()); outputDefault.setMaxQueueSize(maxQueueSize); Assert.assertEquals(outputDefault.getMaxQueueSize(), maxQueueSize); diff --git a/splunk/src/test/java/com/splunk/OutputGroupTest.java b/splunk/src/test/java/com/splunk/OutputGroupTest.java index e850dd13..3ea25e11 100644 --- a/splunk/src/test/java/com/splunk/OutputGroupTest.java +++ b/splunk/src/test/java/com/splunk/OutputGroupTest.java @@ -24,7 +24,7 @@ public class OutputGroupTest extends SDKTestCase { public void testOutputGroup() throws Exception { EntityCollection<OutputGroup> outputGroups = service.getOutputGroups(); - if (outputGroups.values().size() == 0) { + if (outputGroups.values().isEmpty()) { System.out.println("WARNING: No OutputGroups to test"); return; } diff --git a/splunk/src/test/java/com/splunk/OutputServerTest.java b/splunk/src/test/java/com/splunk/OutputServerTest.java index 24fb6aa2..03fe0ef3 100644 --- a/splunk/src/test/java/com/splunk/OutputServerTest.java +++ b/splunk/src/test/java/com/splunk/OutputServerTest.java @@ -24,7 +24,7 @@ public void testOutputServer() throws Exception { EntityCollection<OutputServer> outputServers = service.getOutputServers(); - if (outputServers.values().size() == 0) { + if (outputServers.values().isEmpty()) { System.out.println("WARNING: No OutputServers to test"); return; } diff --git a/splunk/src/test/java/com/splunk/OutputSyslogTest.java b/splunk/src/test/java/com/splunk/OutputSyslogTest.java index 1ca28adb..e0b5df28 100644 --- a/splunk/src/test/java/com/splunk/OutputSyslogTest.java +++ b/splunk/src/test/java/com/splunk/OutputSyslogTest.java @@ -24,7 +24,7 @@ public class OutputSyslogTest extends SDKTestCase { public void testOutputSyslog() throws Exception { EntityCollection<OutputSyslog> dos = service.getOutputSyslogs(); - if (dos.values().size() == 0) { + if (dos.values().isEmpty()) { System.out.println("WARNING: No OutputSyslogs to test"); return; } diff --git a/splunk/src/test/java/com/splunk/PasswordTest.java b/splunk/src/test/java/com/splunk/PasswordTest.java index 3d32d393..5bb46ae7 100644 --- a/splunk/src/test/java/com/splunk/PasswordTest.java +++ b/splunk/src/test/java/com/splunk/PasswordTest.java @@ -133,7 +133,7 @@ public void testPasswordsCompatibleGetByName() { } @Test public void testPasswordsWithWildCards(){ - HashMap<String, Object> args = new HashMap<String, Object>(); + HashMap<String, Object> args = new HashMap<>(); args = Command.defaultValues; args.put("owner", "-"); args.put("app", "-"); @@ -141,7 +141,7 @@ public void testPasswordsWithWildCards(){ args.put("password", "changed!"); Service service = Service.connect(args); PasswordCollection passwords = service.getPasswords(); - Assert.assertEquals(passwords.size(),0); + Assert.assertEquals(0, passwords.size()); String name = "no-owner"; String value = "sdk-test-password"; @@ -171,6 +171,6 @@ public void testPasswordsWithWildCards(){ Assert.assertEquals("app context must be specified when removing a password.", e.getMessage()); } passwords = service.getPasswords(); - Assert.assertEquals(passwords.size(),0); + Assert.assertEquals(0, passwords.size()); } } diff --git a/splunk/src/test/java/com/splunk/ReceiverTest.java b/splunk/src/test/java/com/splunk/ReceiverTest.java index e171b9d1..6852f8c3 100644 --- a/splunk/src/test/java/com/splunk/ReceiverTest.java +++ b/splunk/src/test/java/com/splunk/ReceiverTest.java @@ -70,30 +70,22 @@ public void testReceiver(Service passedService) { final int versionCompare = passedService.versionCompare("6.0.0"); final String osName = passedService.getInfo().getOsName(); - try { - Socket socket1 = receiver.attach(); - OutputStream stream = socket1.getOutputStream(); - + try ( + Socket socket1 = receiver.attach(); + OutputStream stream = socket1.getOutputStream(); + ) { String s = createTimestamp() + " Boris the mad baboon1!\r\n"; stream.write(s.getBytes("UTF-8")); - // Splunk won't deterministically index these events until the socket is closed or greater than 1MB - // has been written. - stream.close(); - socket1.close(); } catch (IOException e) { Assert.fail("Exception on attach"); } - try { - Socket socket1 = receiver.attach(Args.create("sourcetype", "mysourcetype")); - OutputStream stream = socket1.getOutputStream(); - + try ( + Socket socket1 = receiver.attach(Args.create("sourcetype", "mysourcetype")); + OutputStream stream = socket1.getOutputStream(); + ) { String s = createTimestamp() + " Boris the mad baboon2!\r\n"; stream.write(s.getBytes("UTF-8")); - // Splunk won't deterministically index these events until the socket is closed or greater than 1MB - // has been written. - stream.close(); - socket1.close(); } catch (IOException e) { Assert.fail("Exception on attach"); } diff --git a/splunk/src/test/java/com/splunk/ResultsReaderTest.java b/splunk/src/test/java/com/splunk/ResultsReaderTest.java index 71ebe42d..b0e69c4f 100644 --- a/splunk/src/test/java/com/splunk/ResultsReaderTest.java +++ b/splunk/src/test/java/com/splunk/ResultsReaderTest.java @@ -41,7 +41,7 @@ public void testReadCsv() throws Exception { Assert.assertEquals("sum(kb)", fields[0]); Assert.assertEquals("series", fields[1]); - Map<String, String> expected = new HashMap<String, String>(); + Map<String, String> expected = new HashMap<>(); expected.put("series", "twitter"); expected.put("sum(kb)", "14372242.758775"); @@ -65,7 +65,7 @@ public void testReadCsvFromOneshot() throws Exception { "search index=_internal | head 1 | stats count", Args.create("output_mode", "csv")); ResultsReaderCsv reader = new ResultsReaderCsv(input); - Map<String, String> expected = new HashMap<String, String>(); + Map<String, String> expected = new HashMap<>(); expected.put("count", "1"); assertNextEventEquals(expected, reader); @@ -124,7 +124,7 @@ private MultiResultsReader getExportStreamXml() throws IOException { public void testReadJsonOnSplunk4() throws Exception { InputStream input = openResource("/results4.json"); ResultsReaderJson reader = new ResultsReaderJson(input); - Map<String, String> expected = new HashMap<String, String>(); + Map<String, String> expected = new HashMap<>(); expected.put("series", "twitter"); expected.put("sum(kb)", "14372242.758775"); @@ -148,7 +148,7 @@ public void testReadJsonOnSplunk5() throws Exception { // from Splunk 4.3. InputStream input = openResource("/results5.json"); ResultsReaderJson reader = new ResultsReaderJson(input); - Map<String, String> expected = new HashMap<String, String>(); + Map<String, String> expected = new HashMap<>(); expected.put("series", "twitter"); expected.put("sum(kb)", "14372242.758775"); @@ -341,7 +341,7 @@ private void testPreviewSingleReaderXml(boolean useIter) throws Exception { String[] fieldNameArray = new String[0]; fieldNameArray = reader.getFields().toArray(fieldNameArray); Assert.assertEquals(101, fieldNameArray.length); - Assert.assertEquals(fieldNameArray[99], "useragent"); + Assert.assertEquals("useragent", fieldNameArray[99]); int index = 0; Event lastEvent = null; @@ -456,13 +456,13 @@ private void testExportMultiReader( switch (indexResultSet) { case 0: - Assert.assertEquals(indexEvent, 1); + Assert.assertEquals(1, indexEvent); break; case 1: - Assert.assertEquals(indexEvent, 3); + Assert.assertEquals(3, indexEvent); break; default: - Assert.assertEquals(indexEvent, 5); + Assert.assertEquals(5, indexEvent); break; } indexResultSet++; diff --git a/splunk/src/test/java/com/splunk/ResultsReaderTestFromExpectedFile.java b/splunk/src/test/java/com/splunk/ResultsReaderTestFromExpectedFile.java index ecfa0d14..8c527eee 100644 --- a/splunk/src/test/java/com/splunk/ResultsReaderTestFromExpectedFile.java +++ b/splunk/src/test/java/com/splunk/ResultsReaderTestFromExpectedFile.java @@ -75,11 +75,11 @@ public ResultsReaderTestFromExpectedFile(String version, String testName) { @Parameterized.Parameters(name="{1} from version {0}") public static Collection<Object[]> testCases() { - Collection<Object[]> cases = new ArrayList<Object[]>(); - for (String version : (Set<String>)expectedData.keySet()) { + Collection<Object[]> cases = new ArrayList<>(); + for (String version : expectedData.keySet()) { Map<String, Object> casesForThisVersion = (Map<String, Object>)expectedData.get(version); - for (String testName : (Set<String>)casesForThisVersion.keySet()) { + for (String testName : casesForThisVersion.keySet()) { cases.add(new Object[] {version, testName}); } } @@ -141,9 +141,9 @@ static void verifyResultsReader( assertEquals(expectedKeys, foundEvent.keySet()); for (String key : expectedFields.keySet()) { assertTrue(foundEvent.containsKey(key)); - if (expectedFields.get(key) instanceof List) { + if (expectedFields.get(key) instanceof List value) { assertEquals( - expectedFields.get(key), + value, Arrays.asList(foundEvent.getArray(key))); } else { assertEquals(expectedFields.get(key), foundEvent.get(key)); diff --git a/splunk/src/test/java/com/splunk/SDKTestCase.java b/splunk/src/test/java/com/splunk/SDKTestCase.java index c2c623fa..349e5929 100644 --- a/splunk/src/test/java/com/splunk/SDKTestCase.java +++ b/splunk/src/test/java/com/splunk/SDKTestCase.java @@ -51,7 +51,7 @@ public abstract class SDKTestCase { protected Command command; - public static String streamToString(java.io.InputStream is) { + public static String streamToString(InputStream is) { Reader r = null; try { r = new InputStreamReader(is, "UTF-8"); @@ -114,7 +114,7 @@ public void setUp() throws Exception { splunkRestart(); System.out.println("Restart complete."); } - installedApps = new ArrayList<String>(); + installedApps = new ArrayList<>(); } @After @@ -349,8 +349,7 @@ protected int findNextUnusedPort(int startingPort) { } public boolean isPortInUse(int port) { - try { - Socket pingSocket = new Socket(); + try (Socket pingSocket = new Socket()) { // On Windows, the firewall doesn't respond at all if you connect to an unbound port, so we need to // take lack of a connection as an empty port. Timeout is 1000ms. try { @@ -358,7 +357,6 @@ public boolean isPortInUse(int port) { } catch (SocketTimeoutException ste) { return false; } - pingSocket.close(); if (VERBOSE_PORT_SCAN) { System.out.println("IN-USE(" + port + ")"); } @@ -414,20 +412,20 @@ else if (osName.equals("Darwin")) { } protected boolean firstLineIsXmlDtd(InputStream stream) { - InputStreamReader reader; - try { - reader = new InputStreamReader(stream, "UTF-8"); + try (InputStreamReader reader = new InputStreamReader(stream, "UTF-8"); + BufferedReader lineReader = new BufferedReader(reader)) { + try { + return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>".equals( + lineReader.readLine() + ); + } catch (IOException e) { + Assert.fail(e.toString()); + return false; + } } catch (UnsupportedEncodingException e) { throw new Error(e); - } - BufferedReader lineReader = new BufferedReader(reader); - try { - return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>".equals( - lineReader.readLine() - ); } catch (IOException e) { - Assert.fail(e.toString()); - return false; + throw new RuntimeException(e); } } } diff --git a/splunk/src/test/java/com/splunk/SavedSearchTest.java b/splunk/src/test/java/com/splunk/SavedSearchTest.java index e62a6294..a96f5d46 100644 --- a/splunk/src/test/java/com/splunk/SavedSearchTest.java +++ b/splunk/src/test/java/com/splunk/SavedSearchTest.java @@ -246,7 +246,7 @@ public void testUpdate() { boolean isPre620 = service.versionIsEarlierThan("6.2.0"); try { - Assert.assertEquals(savedSearch.isEmbedEnabled(), false); + Assert.assertEquals(false, savedSearch.isEmbedEnabled()); Assert.assertNull(savedSearch.getEmbedToken()); if (isPre620) Assert.fail("Expected UnsupportedOperationException"); @@ -373,8 +373,8 @@ public void testACLUpdates(){ args.add("perms.read","admin, nobody"); savedSearch.aclUpdate(args); aclInfo = savedSearch.getMetadata().getEaiAcl(); - Assert.assertEquals(aclInfo.getString("sharing"), "app"); - Assert.assertEquals(aclInfo.getString("owner"), "nobody"); + Assert.assertEquals("app", aclInfo.getString("sharing")); + Assert.assertEquals("nobody", aclInfo.getString("owner")); Assert.assertNotNull(aclInfo.get("perms")); } @@ -480,7 +480,7 @@ public void testHistoryWithArgs(){ Assert.assertEquals(30, savedSearch.history().length); //history with argument 'count' set to '0' i.e it returns the whole history - HashMap<String, Object> args = new HashMap<String, Object>(); + HashMap<String, Object> args = new HashMap<>(); args.put("count", 0); Assert.assertEquals(31, savedSearch.history(args).length); diff --git a/splunk/src/test/java/com/splunk/SearchJobTest.java b/splunk/src/test/java/com/splunk/SearchJobTest.java index fbb7cbce..74434390 100644 --- a/splunk/src/test/java/com/splunk/SearchJobTest.java +++ b/splunk/src/test/java/com/splunk/SearchJobTest.java @@ -231,7 +231,7 @@ public void testJobHasNoSgByDefault() throws IOException { public void testJobCanEnableSg() throws IOException { Job job = service.getJobs().create("search index=_internal GET | head 3"); waitUntilDone(job); - Map<String, String> args = new HashMap<String, String>(); + Map<String, String> args = new HashMap<>(); args.put("segmentation", "raw"); String data = streamToString(job.getResults(args)); Assert.assertTrue(data.contains("<sg")); @@ -340,7 +340,7 @@ public void testEventArgs(Job job) throws IOException, InterruptedException { while(true) { HashMap<String, String> found = reader.getNextEvent(); if (found != null) { - Assert.assertEquals(found.get("_raw").split("\n").length, 1); + Assert.assertEquals(1, found.get("_raw").split("\n").length); Assert.assertFalse(found.containsKey("date_month")); Assert.assertEquals(Integer.parseInt(found.get("_serial")), count + 2); count++; @@ -367,7 +367,7 @@ public void testResultArgs(Job job) throws IOException, InterruptedException { while(true) { HashMap<String, String> found = reader.getNextEvent(); if (found != null) { - Assert.assertEquals(found.get("_raw").split("\n").length, 1); + Assert.assertEquals(1, found.get("_raw").split("\n").length); Assert.assertFalse(found.containsKey("date_month")); Assert.assertEquals(Integer.parseInt(found.get("_serial")), count + 2); count++; @@ -390,7 +390,7 @@ public void testResultArgs(Job job) throws IOException, InterruptedException { while(true) { HashMap<String, String> found = reader2.getNextEvent(); if (found != null) { - Assert.assertEquals(found.get("count"), "10"); + Assert.assertEquals("10", found.get("count")); count2++; } else { @@ -415,7 +415,7 @@ public void testPreviewArgs(Job job) throws IOException, InterruptedException { while (true) { HashMap<String, String> found = reader.getNextEvent(); if (found != null) { - Assert.assertEquals(found.get("_raw").split("\n").length, 1); + Assert.assertEquals(1, found.get("_raw").split("\n").length); Assert.assertFalse(found.containsKey("date_month")); Assert.assertEquals(Integer.parseInt(found.get("_serial")), count + 2); count++; @@ -438,7 +438,7 @@ public void testPreviewArgs(Job job) throws IOException, InterruptedException { while(true) { HashMap<String, String> found = reader2.getNextEvent(); if (found != null) { - Assert.assertEquals(found.get("count"), "10"); + Assert.assertEquals("10", found.get("count")); count2++; } else { @@ -1031,15 +1031,14 @@ public boolean predicate() { private String inputStreamToString(InputStream stream) { try { StringBuilder b = new StringBuilder(); - BufferedReader reader = new BufferedReader( - new InputStreamReader(stream, "UTF-8") - ); - String tmp; - while ((tmp = reader.readLine()) != null) { - b.append(tmp + "\n"); + try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream, "UTF-8"));) { + String tmp; + while ((tmp = reader.readLine()) != null) { + b.append(tmp + "\n"); + } + return b.toString(); } - return b.toString(); } catch (IOException e) { Assert.fail(e.toString()); return null; diff --git a/splunk/src/test/java/com/splunk/ServiceTest.java b/splunk/src/test/java/com/splunk/ServiceTest.java index ac8076ad..d9efa699 100644 --- a/splunk/src/test/java/com/splunk/ServiceTest.java +++ b/splunk/src/test/java/com/splunk/ServiceTest.java @@ -155,12 +155,12 @@ public void testServiceWithCustomHeaders() { args.setScheme((String) command.opts.get("scheme")); args.setUsername((String) command.opts.get("username")); args.setPassword((String) command.opts.get("password")); - args.setHttpHeaders(new HashMap<String, String>() {{ + args.setHttpHeaders(new HashMap<>() {{ put("some header key", "some value"); }}); Service service = new Service(args); Map<String, String> customHeaders = service.getCustomHeaders(); - Assert.assertEquals(customHeaders.get("some header key"), "some value"); + Assert.assertEquals("some value", customHeaders.get("some header key")); } @Test @@ -522,7 +522,7 @@ public void testNewServiceArgs() { args.setToken("Splunk MY_SESSION_KEY"); Assert.assertEquals("Arg setters didn't replicate value to deprecated fields.", - args.app, "myapp"); + "myapp", args.app); Service service = new Service(args); Assert.assertEquals(args.app, service.getApp()); @@ -706,7 +706,7 @@ public void testDelete() { @Test public void testPost() { - HashMap<String, Object> args = new HashMap<String, Object>(); + HashMap<String, Object> args = new HashMap<>(); args.put("foo", "bar"); ResponseMessage response; diff --git a/splunk/src/test/java/com/splunk/UtilTest.java b/splunk/src/test/java/com/splunk/UtilTest.java index a4a582e4..5f245bb8 100644 --- a/splunk/src/test/java/com/splunk/UtilTest.java +++ b/splunk/src/test/java/com/splunk/UtilTest.java @@ -25,14 +25,14 @@ public class UtilTest extends SDKTestCase { @Test public void testJoin() { - List<String> emptyList = new ArrayList<String>(); + List<String> emptyList = new ArrayList<>(); Assert.assertEquals("", Util.join("/", emptyList)); - List<String> oneElementList = new ArrayList<String>(); + List<String> oneElementList = new ArrayList<>(); oneElementList.add("abcd"); Assert.assertEquals("abcd", Util.join("/", oneElementList)); - List<String> fullList = new ArrayList<String>(); + List<String> fullList = new ArrayList<>(); fullList.add("abcd"); fullList.add("defg"); Assert.assertEquals( @@ -75,7 +75,7 @@ public void testSubstringAfterFails() { @Test public void testArgs() { Args args = Args.create(); - Assert.assertTrue(args != null); + Assert.assertNotNull(args); Assert.assertTrue(args instanceof Args); Assert.assertTrue(Args.encode((String) null).equals("")); diff --git a/splunk/src/test/java/com/splunk/modularinput/InputDefinitionTest.java b/splunk/src/test/java/com/splunk/modularinput/InputDefinitionTest.java index aa9fe324..60131230 100644 --- a/splunk/src/test/java/com/splunk/modularinput/InputDefinitionTest.java +++ b/splunk/src/test/java/com/splunk/modularinput/InputDefinitionTest.java @@ -45,14 +45,14 @@ public void testParseStreamWithThreeInputs() throws ParserConfigurationException expectedDefinition.setCheckpointDir("/some/dir"); expectedDefinition.setSessionKey("123102983109283019283"); - List<Parameter> parameters = new ArrayList<Parameter>(); + List<Parameter> parameters = new ArrayList<>(); parameters.add(new SingleValueParameter("param1", "value1")); parameters.add(new SingleValueParameter("param2", "value2")); parameters.add(new SingleValueParameter("disabled", "0")); parameters.add(new SingleValueParameter("index", "default")); expectedDefinition.addInput("foobar://aaa", parameters); - parameters = new ArrayList<Parameter>(); + parameters = new ArrayList<>(); parameters.add(new SingleValueParameter("param1", "value11")); parameters.add(new SingleValueParameter("param2", "value22")); parameters.add(new SingleValueParameter("disabled", "0")); @@ -78,8 +78,7 @@ public void testParseStreamWithThreeInputs() throws ParserConfigurationException */ @Test public void testParseMalformedInputDefinition() throws ParserConfigurationException, SAXException, IOException { - try { - InputStream stream = SDKTestCase.openResource("/modularinput/data/conf_with_invalid_inputs.xml"); + try (InputStream stream = SDKTestCase.openResource("/modularinput/data/conf_with_invalid_inputs.xml")) { InputDefinition foundDefinition = InputDefinition.parseDefinition(stream); } catch (MalformedDataException e) { Assert.assertTrue(true); diff --git a/splunk/src/test/java/com/splunk/modularinput/ModularInputTestCase.java b/splunk/src/test/java/com/splunk/modularinput/ModularInputTestCase.java index ef0a7c92..b8abfd9d 100644 --- a/splunk/src/test/java/com/splunk/modularinput/ModularInputTestCase.java +++ b/splunk/src/test/java/com/splunk/modularinput/ModularInputTestCase.java @@ -33,11 +33,11 @@ public static void removeBlankTextNodes(Element node) { // Iterate backwards through the collection since we're going to be removing elements for (int i = children.getLength() - 1; i >= 0; i--) { Node child = children.item(i); - if (child instanceof Text && ((Text)child).getData().trim().length() == 0) { + if (child instanceof Text txt && txt.getData().isBlank()) { node.removeChild(child); } - else if (child instanceof Element) { - removeBlankTextNodes((Element) child); + else if (child instanceof Element elem) { + removeBlankTextNodes(elem); } } } @@ -48,8 +48,8 @@ else if (child instanceof Element) { * * @param expected an org.w3c.dom.Node object containing the expected XML document. * @param found an org.w3c.dom.Node object containing the XML document actually produced. - * @throws javax.xml.transform.TransformerException - * @throws javax.xml.parsers.ParserConfigurationException + * @throws TransformerException + * @throws ParserConfigurationException */ public void assertXmlEqual(Node expected, Node found) throws TransformerException, ParserConfigurationException { try { @@ -79,8 +79,8 @@ public void assertXmlEqual(Node expected, Node found) throws TransformerExceptio * * @param expected an org.w3c.dom.Document object containing the expected XML document. * @param found an org.w3c.dom.Document object containing the XML document actually produced. - * @throws javax.xml.transform.TransformerException - * @throws javax.xml.parsers.ParserConfigurationException + * @throws TransformerException + * @throws ParserConfigurationException */ public void assertXmlEqual(Document expected, Document found) throws TransformerException, ParserConfigurationException { removeBlankTextNodes(expected.getDocumentElement()); @@ -107,8 +107,7 @@ public Document resourceToXmlDocument(String path) { throw new AssertionError("Parser configuration failed: " + e.toString()); } - InputStream resource = SDKTestCase.openResource(path); - try { + try (InputStream resource = SDKTestCase.openResource(path)) { Document doc = documentBuilder.parse(resource); return doc; } catch (SAXException e) { diff --git a/splunk/src/test/java/com/splunk/modularinput/ValidationDefinitionTest.java b/splunk/src/test/java/com/splunk/modularinput/ValidationDefinitionTest.java index 6110c04e..a515a13e 100644 --- a/splunk/src/test/java/com/splunk/modularinput/ValidationDefinitionTest.java +++ b/splunk/src/test/java/com/splunk/modularinput/ValidationDefinitionTest.java @@ -30,7 +30,7 @@ public void testParseValidationDefinition() throws ParserConfigurationException, expected.setCheckpointDir("/opt/splunk/var/lib/splunk/modinputs"); expected.setSessionKey("123102983109283019283"); expected.setName("aaa"); - List<Parameter> parameters = new ArrayList<Parameter>(); + List<Parameter> parameters = new ArrayList<>(); parameters.add(new SingleValueParameter("param1", "value1")); parameters.add(new SingleValueParameter("param2", "value2")); parameters.add(new SingleValueParameter("disabled", "0"));