package org.stagemonitor.web.servlet.useragent;

import net.sf.uadetector.ReadableUserAgent;
import net.sf.uadetector.UserAgentStringParser;
import net.sf.uadetector.service.UADetectorServiceFactory;

import java.util.LinkedHashMap;
import java.util.Map;

import io.opentracing.Span;

/**
 * The uadetector library is discontinued as the underlying database is now commercial.
 * <p>
 * Consider using the Elasticsearch ingest user agent plugin: https://www.elastic.co/guide/en/elasticsearch/plugins/master/ingest-user-agent.html
 */
@Deprecated
public class UserAgentParser {

	private static final int MAX_ELEMENTS = 100;

	// prevents reDOS attacks like described in https://github.com/before/uadetector/issues/130
	private static final int MAX_USERAGENT_LENGTH = 256;
	private final UserAgentStringParser parser;
	private final Map<String, ReadableUserAgent> userAgentCache;

	public UserAgentParser() {
		this(UADetectorServiceFactory.getResourceModuleParser(),
				new LinkedHashMap<String, ReadableUserAgent>(MAX_ELEMENTS + 1, 0.75f, true) {
					@Override
					protected boolean removeEldestEntry(Map.Entry eldest) {
						return size() > MAX_ELEMENTS;
					}
				});
	}

	public UserAgentParser(UserAgentStringParser parser, Map<String, ReadableUserAgent> userAgentCache) {
		this.parser = parser;
		this.userAgentCache = userAgentCache;
	}

	public void setUserAgentInformation(final Span span, final String userAgentHeader) {
		if (userAgentHeader != null && userAgentHeader.length() < MAX_USERAGENT_LENGTH) {
			final ReadableUserAgent userAgent = parse(userAgentHeader);
			span.setTag("user_agent.type", userAgent.getTypeName());
			span.setTag("user_agent.device", userAgent.getDeviceCategory().getName());
			span.setTag("user_agent.os", userAgent.getOperatingSystem().getName());
			span.setTag("user_agent.os_family", userAgent.getOperatingSystem().getFamilyName());
			span.setTag("user_agent.os_version", userAgent.getOperatingSystem().getVersionNumber().toVersionString());
			span.setTag("user_agent.browser", userAgent.getName());
			span.setTag("user_agent.browser_version", userAgent.getVersionNumber().toVersionString());
		}
	}

	private ReadableUserAgent parse(String userAgentHeader) {
		ReadableUserAgent readableUserAgent = userAgentCache.get(userAgentHeader);
		if (readableUserAgent == null) {
			readableUserAgent = parser.parse(userAgentHeader);
			userAgentCache.put(userAgentHeader, readableUserAgent);
		}
		return readableUserAgent;
	}

}

@@ -194,16 +194,46 @@
 ctory;%0A%0A
+import java.util.Collections;%0A
 import j
@@ -256,16 +256,16 @@
 ashMap;%0A
-
 import j
@@ -645,16 +645,17 @@
 TS = 100
+0
 ;%0A%0A%09// p
@@ -995,16 +995,44 @@
 (),%0A%09%09%09%09
+Collections.synchronizedMap(
 new Link
@@ -1224,14 +1224,15 @@
 %09%09%7D%0A
-
 %09%09%09%09%7D)
+)
 ;%0A%09%7D

Fix livelock in unsychronized map in UserAgentParser