org.elasticsearch.plugin.ingest.yauaa.YauaaProcessor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of yauaa-elasticsearch-8 Show documentation
Show all versions of yauaa-elasticsearch-8 Show documentation
A parsing and analyzing library to get information from a useragent string.
The newest version!
/*
* Yet Another UserAgent Analyzer
* Copyright (C) 2013-2024 Niels Basjes
*
* 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
*
* https://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 org.elasticsearch.plugin.ingest.yauaa;
import nl.basjes.parse.useragent.UserAgent;
import nl.basjes.parse.useragent.UserAgentAnalyzer;
import nl.basjes.parse.useragent.UserAgentAnalyzer.UserAgentAnalyzerBuilder;
import org.elasticsearch.ingest.AbstractProcessor;
import org.elasticsearch.ingest.IngestDocument;
import org.elasticsearch.ingest.Processor;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import static nl.basjes.parse.useragent.UserAgent.USERAGENT_FIELDNAME;
import static nl.basjes.parse.useragent.UserAgent.USERAGENT_HEADER;
import static org.elasticsearch.ingest.ConfigurationUtils.readIntProperty;
import static org.elasticsearch.ingest.ConfigurationUtils.readOptionalList;
import static org.elasticsearch.ingest.ConfigurationUtils.readOptionalMap;
import static org.elasticsearch.ingest.ConfigurationUtils.readOptionalStringProperty;
import static org.elasticsearch.ingest.ConfigurationUtils.readStringProperty;
public class YauaaProcessor extends AbstractProcessor {
public static final String TYPE = "yauaa";
private final Map fieldToHeaderMapping;
private final String targetField;
private final UserAgentAnalyzer uaa;
YauaaProcessor(String tag,
String description,
Map fieldToHeaderMapping,
String targetField,
UserAgentAnalyzer uaa) {
super(tag, description);
this.fieldToHeaderMapping = fieldToHeaderMapping;
this.targetField = targetField;
this.uaa = uaa;
}
@Override
public IngestDocument execute(IngestDocument ingestDocument) {
Map headers = new TreeMap<>();
for (Map.Entry entry : fieldToHeaderMapping.entrySet()) {
String content = ingestDocument.getFieldValue(entry.getKey(), String.class);
if (content != null) {
headers.put(entry.getValue(), content);
}
}
UserAgent userAgent = uaa.parse(headers);
Map resultMap = userAgent.toMap();
resultMap.remove(USERAGENT_FIELDNAME);
ingestDocument.setFieldValue(targetField, resultMap);
return ingestDocument;
}
@Override
public String getType() {
return TYPE;
}
public static final class Factory implements Processor.Factory {
@Override
public Processor create(Map processorFactories, String tag, String description, Map config) {
String field = readOptionalStringProperty(TYPE, tag, config, "field"); // Deprecated
Map fieldToHeaderMappingConfig = readOptionalMap(TYPE, tag, config, "field_to_header_mapping");
String targetField = readStringProperty(TYPE, tag, config, "target_field", "user_agent");
List fieldNames = readOptionalList(TYPE, tag, config, "fieldNames");
Integer cacheSize = readIntProperty(TYPE, tag, config, "cacheSize", -1);
Integer preheat = readIntProperty(TYPE, tag, config, "preheat", -1);
String extraRules = readOptionalStringProperty(TYPE, tag, config, "extraRules");
UserAgentAnalyzerBuilder builder = UserAgentAnalyzer
.newBuilder()
.dropTests()
.immediateInitialization()
// With the default Caffeine based cache an exception occurs at startup:
// Caused by: java.security.AccessControlException: access denied ("java.lang.reflect.ReflectPermission" "suppressAccessChecks")
// at java.base/java.security.AccessControlContext.checkPermission(AccessControlContext.java:485)
// at java.base/java.security.AccessController.checkPermission(AccessController.java:1068)
// at java.base/java.lang.SecurityManager.checkPermission(SecurityManager.java:416)
// at java.base/java.lang.invoke.MethodHandles.privateLookupIn(MethodHandles.java:233)
// at com.github.benmanes.caffeine.cache.BaseMpscLinkedArrayQueue.(MpscGrowableArrayQueue.java:662)
// ...
.useJava8CompatibleCaching();
if (cacheSize >= 0) {
builder.withCache(cacheSize);
}
if (preheat >= 0) {
builder.preheat(preheat);
}
if (extraRules != null) {
builder.addYamlRule(extraRules);
}
if (fieldNames != null && !fieldNames.isEmpty()) {
builder.withFields(fieldNames);
}
UserAgentAnalyzer userAgentAnalyzer = builder.build();
List supportedHeaders = new ArrayList<>(userAgentAnalyzer.supportedClientHintHeaders());
supportedHeaders.add(USERAGENT_HEADER);
Map fieldToHeaderMapping = new TreeMap<>();
if (fieldToHeaderMappingConfig != null) {
for (Map.Entry entry : fieldToHeaderMappingConfig.entrySet()) {
boolean supportedHeaderName = false;
String wantedHeader = entry.getValue();
for (String allowedHeader : supportedHeaders) {
if (allowedHeader.equalsIgnoreCase(wantedHeader)) {
supportedHeaderName = true;
break;
}
}
if (!supportedHeaderName) {
throw new IllegalArgumentException("The provided header name \"" + wantedHeader + "\"is not allowed." +
"Allowed header names are: " + supportedHeaders);
}
fieldToHeaderMapping.put(entry.getKey(), entry.getValue());
}
}
if (field != null) {
fieldToHeaderMapping.put(field, USERAGENT_HEADER);
}
return new YauaaProcessor(tag, description, fieldToHeaderMapping, targetField, userAgentAnalyzer);
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy