This is an automated email from the ASF dual-hosted git repository. shuber pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/unomi.git
The following commit(s) were added to refs/heads/master by this push: new 9901d95 [UNOMI-228] Replace user agent detector library 9901d95 is described below commit 9901d95898c515942f754255ba2bd3d6fcbdbbf3 Author: Francois Papon <fpa...@apache.org> AuthorDate: Sat Apr 20 19:53:20 2019 +0400 [UNOMI-228] Replace user agent detector library --- itests/pom.xml | 33 +------ .../test/java/org/apache/unomi/itests/BaseIT.java | 40 +------- package/pom.xml | 13 +-- performance-tests/pom.xml | 36 +------ .../apache/unomi/performancetests/BasicTest.java | 52 ++--------- plugins/request/pom.xml | 86 ++++++++++++++--- .../request/actions/SetRemoteHostInfoAction.java | 52 ++++++----- .../unomi/plugins/request/useragent/UserAgent.java | 86 +++++++++++++++++ .../useragent/UserAgentDetectorServiceImpl.java | 76 +++++++++++++++ .../resources/OSGI-INF/blueprint/blueprint.xml | 6 ++ .../request/actions/UserAgentDetectorTest.java | 104 +++++++++++++++++++++ pom.xml | 34 ++++++- services/pom.xml | 14 +++ .../resources/OSGI-INF/blueprint/blueprint.xml | 1 - 14 files changed, 439 insertions(+), 194 deletions(-) diff --git a/itests/pom.xml b/itests/pom.xml index fad2656..5f04b9a 100644 --- a/itests/pom.xml +++ b/itests/pom.xml @@ -30,10 +30,9 @@ <dependencies> <dependency> <groupId>org.apache.unomi</groupId> - <artifactId>unomi-kar</artifactId> - <classifier>features</classifier> + <artifactId>unomi</artifactId> <version>${project.version}</version> - <type>xml</type> + <type>tar.gz</type> <scope>test</scope> </dependency> <dependency> @@ -64,34 +63,6 @@ </dependency> <dependency> - <groupId>org.apache.karaf.features</groupId> - <artifactId>standard</artifactId> - <classifier>features</classifier> - <type>xml</type> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.apache.karaf.cellar</groupId> - <artifactId>apache-karaf-cellar</artifactId> - <classifier>features</classifier> - <type>xml</type> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.ops4j.pax.web</groupId> - <artifactId>pax-web-features</artifactId> - <classifier>features</classifier> - <type>xml</type> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.apache.cxf.karaf</groupId> - <artifactId>apache-cxf</artifactId> - <classifier>features</classifier> - <type>xml</type> - <scope>test</scope> - </dependency> - <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <scope>provided</scope> diff --git a/itests/src/test/java/org/apache/unomi/itests/BaseIT.java b/itests/src/test/java/org/apache/unomi/itests/BaseIT.java index eede503..039fb51 100644 --- a/itests/src/test/java/org/apache/unomi/itests/BaseIT.java +++ b/itests/src/test/java/org/apache/unomi/itests/BaseIT.java @@ -47,42 +47,13 @@ public abstract class BaseIT { @Configuration public Option[] config() throws InterruptedException { - MavenArtifactUrlReference karafUrl = maven() - .groupId("org.apache.karaf") - .artifactId("apache-karaf") - .version("4.1.5") - .type("tar.gz"); - MavenUrlReference karafStandardRepo = maven() - .groupId("org.apache.karaf.features") - .artifactId("standard") - .classifier("features") - .type("xml") - .versionAsInProject(); - MavenUrlReference karafCellarRepo = maven() - .groupId("org.apache.karaf.cellar") - .artifactId("apache-karaf-cellar") - .classifier("features") - .type("xml") - .versionAsInProject(); - MavenUrlReference karafPaxWebRepo = maven() - .groupId("org.ops4j.pax.web") - .artifactId("pax-web-features") - .classifier("features") - .type("xml") - .versionAsInProject(); - MavenUrlReference karafCxfRepo = maven() - .groupId("org.apache.cxf.karaf") - .artifactId("apache-cxf") - .classifier("features") - .type("xml") - .versionAsInProject(); - MavenUrlReference contextServerRepo = maven() + MavenArtifactUrlReference karafUrl = maven() .groupId("org.apache.unomi") - .artifactId("unomi-kar") - .classifier("features") - .type("xml") + .artifactId("unomi") + .type("tar.gz") .versionAsInProject(); + MavenUrlReference routerRepo = maven() .groupId("org.apache.unomi") .artifactId("unomi-router-karaf-feature") @@ -132,9 +103,6 @@ public abstract class BaseIT { systemProperty("org.apache.unomi.hazelcast.tcp-ip.members").value("127.0.0.1"), systemProperty("org.apache.unomi.hazelcast.tcp-ip.interface").value("127.0.0.1"), systemProperty("unomi.autoStart").value("true"), - features(karafCxfRepo, "cxf"), - features(karafCellarRepo, "cellar"), - features(contextServerRepo, "unomi-kar"), features(routerRepo, "unomi-router-karaf-feature"), CoreOptions.bundleStartLevel(100), CoreOptions.frameworkStartLevel(100) diff --git a/package/pom.xml b/package/pom.xml index 9dad3f6..1cb567a 100644 --- a/package/pom.xml +++ b/package/pom.xml @@ -345,6 +345,7 @@ <library>mvn:org.apache.servicemix.specs/org.apache.servicemix.specs.stax-api-1.2/${servicemix.specs.version};type:=endorsed;export:=true</library> <library>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.xalan/${xalan.bundle.version};type:=endorsed;export:=true</library> <library>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.xalan-serializer/${xalan-serializer.bundle.version};type:=endorsed;export:=true</library> + <library>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.jsr305/${jsr305.bundle.version};type:=endorsed;export:=true</library> <library>mvn:javax.annotation/javax.annotation-api/1.2;type:=endorsed;export:=true</library> <library>mvn:org.apache.servicemix.specs/org.apache.servicemix.specs.activator/${servicemix.specs.version};type:=default;export:=true</library> @@ -361,18 +362,6 @@ <profiles> <profile> - <id>integration-tests</id> - <dependencies> - <dependency> - <groupId>org.apache.unomi</groupId> - <artifactId>unomi-itests</artifactId> - <version>${project.version}</version> - <classifier>features</classifier> - <scope>test</scope> - </dependency> - </dependencies> - </profile> - <profile> <id>src</id> <build> <plugins> diff --git a/performance-tests/pom.xml b/performance-tests/pom.xml index 9371753..b844b39 100644 --- a/performance-tests/pom.xml +++ b/performance-tests/pom.xml @@ -34,41 +34,11 @@ <scope>test</scope> </dependency> <dependency> - <groupId>org.apache.karaf.features</groupId> - <artifactId>standard</artifactId> - <classifier>features</classifier> - <type>xml</type> - </dependency> - <dependency> - <groupId>org.ops4j.pax.web</groupId> - <artifactId>pax-web-features</artifactId> - <classifier>features</classifier> - <type>xml</type> - </dependency> - <dependency> - <groupId>org.apache.karaf.features</groupId> - <artifactId>enterprise</artifactId> - <classifier>features</classifier> - <type>xml</type> - </dependency> - <dependency> - <groupId>org.apache.karaf.features</groupId> - <artifactId>spring</artifactId> - <classifier>features</classifier> - <type>xml</type> - </dependency> - <dependency> - <groupId>org.apache.cxf.karaf</groupId> - <artifactId>apache-cxf</artifactId> - <classifier>features</classifier> - <type>xml</type> - </dependency> - <dependency> <groupId>org.apache.unomi</groupId> - <artifactId>unomi-kar</artifactId> - <classifier>features</classifier> + <artifactId>unomi</artifactId> <version>${project.version}</version> - <type>xml</type> + <type>tar.gz</type> + <scope>test</scope> </dependency> <dependency> <groupId>org.slf4j</groupId> diff --git a/performance-tests/src/test/java/org/apache/unomi/performancetests/BasicTest.java b/performance-tests/src/test/java/org/apache/unomi/performancetests/BasicTest.java index f260109..be3d7fe 100644 --- a/performance-tests/src/test/java/org/apache/unomi/performancetests/BasicTest.java +++ b/performance-tests/src/test/java/org/apache/unomi/performancetests/BasicTest.java @@ -80,59 +80,25 @@ public class BasicTest { @Configuration public Option[] config() { MavenArtifactUrlReference karafUrl = maven() - .groupId("org.apache.karaf") - .artifactId("apache-karaf") - .version("4.1.5") - .type("tar.gz"); - - MavenUrlReference karafStandardRepo = maven() - .groupId("org.apache.karaf.features") - .artifactId("standard") - .classifier("features") - .type("xml") - .versionAsInProject(); - MavenUrlReference karafPaxWebRepo = maven() - .groupId("org.ops4j.pax.web") - .artifactId("pax-web-features") - .classifier("features") - .type("xml") - .versionAsInProject(); - MavenUrlReference karafSpringRepo = maven() - .groupId("org.apache.karaf.features") - .artifactId("spring") - .classifier("features") - .type("xml") - .versionAsInProject(); - MavenUrlReference karafCxfRepo = maven() - .groupId("org.apache.cxf.karaf") - .artifactId("apache-cxf") - .classifier("features") - .type("xml") - .versionAsInProject(); - MavenUrlReference karafEnterpriseRepo = maven() - .groupId("org.apache.karaf.features") - .artifactId("enterprise") - .classifier("features") - .type("xml") - .versionAsInProject(); - MavenUrlReference contextServerRepo = maven() .groupId("org.apache.unomi") - .artifactId("unomi-kar") - .classifier("features") - .type("xml") + .artifactId("unomi") + .type("tar.gz") .versionAsInProject(); + String localRepository = System.getProperty("org.ops4j.pax.url.mvn.localRepository"); + if (localRepository == null) { + localRepository = ""; + } + return new Option[]{ KarafDistributionOption.debugConfiguration("5005", false), + KarafDistributionOption.logLevel(LogLevel.INFO), + KarafDistributionOption.editConfigurationFilePut("etc/org.ops4j.pax.url.mvn.cfg", "org.ops4j.pax.url.mvn.localRepository", localRepository), karafDistributionConfiguration() .frameworkUrl(karafUrl) .unpackDirectory(new File("target/exam")) .useDeployFolder(false), keepRuntimeFolder(), - KarafDistributionOption.features(karafStandardRepo, "wrap") - KarafDistributionOption.features(karafPaxWebRepo, "war"), - KarafDistributionOption.features(karafCxfRepo, "cxf"), - KarafDistributionOption.features(contextServerRepo, "unomi-kar"), // we need to wrap the HttpComponents libraries ourselves since the OSGi bundles provided by the project are incorrect wrappedBundle(mavenBundle("org.apache.httpcomponents", "httpcore").versionAsInProject()), diff --git a/plugins/request/pom.xml b/plugins/request/pom.xml index 6c91d13..9fde026 100644 --- a/plugins/request/pom.xml +++ b/plugins/request/pom.xml @@ -30,6 +30,14 @@ <description>Request reading actions plugin for the Apache Unomi Context Server</description> <packaging>bundle</packaging> + <properties> + <yauaa.version>5.9</yauaa.version> + <kryo.version>2.24.0</kryo.version> + <minlog.version>1.3.1</minlog.version> + <prefixmap>1.1</prefixmap> + <objenesis.version>2.1</objenesis.version> + </properties> + <dependencies> <dependency> <groupId>javax.servlet</groupId> @@ -43,18 +51,6 @@ </dependency> <dependency> - <groupId>net.sf.uadetector</groupId> - <artifactId>uadetector-resources</artifactId> - <version>2014.11-jahia1</version> - </dependency> - - <dependency> - <groupId>net.sf.uadetector</groupId> - <artifactId>uadetector-core</artifactId> - <version>0.9.23-jahia1</version> - </dependency> - - <dependency> <groupId>net.sf.qualitycheck</groupId> <artifactId>quality-check</artifactId> <version>1.3</version> @@ -104,6 +100,66 @@ <version>1.3</version> </dependency> + <dependency> + <groupId>nl.basjes.parse.useragent</groupId> + <artifactId>yauaa</artifactId> + <version>${yauaa.version}</version> + </dependency> + + <dependency> + <groupId>com.esotericsoftware.kryo</groupId> + <artifactId>kryo</artifactId> + <version>${kryo.version}</version> + </dependency> + + <dependency> + <groupId>com.esotericsoftware</groupId> + <artifactId>minlog</artifactId> + <version>${minlog.version}</version> + </dependency> + + <dependency> + <groupId>nl.basjes.collections</groupId> + <artifactId>prefixmap</artifactId> + <version>1.1</version> + </dependency> + + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-text</artifactId> + <version>1.6</version> + </dependency> + + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-collections4</artifactId> + <version>4.3</version> + </dependency> + + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-lang3</artifactId> + </dependency> + + <dependency> + <groupId>org.objenesis</groupId> + <artifactId>objenesis</artifactId> + <version>${objenesis.version}</version> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.11</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-simple</artifactId> + <version>1.6.6</version> + <scope>test</scope> + </dependency> + </dependencies> <build> @@ -120,6 +176,12 @@ org.apache.log;resolution:=optional, org.apache.log4j;resolution:=optional, sun.misc;resolution:=optional, + sun.nio.ch;resolution:=optional, + kotlin.reflect;resolution:=optional, + kotlin.reflect.jvm;resolution:=optional, + nl.basjes.shaded.com.google.errorprone.annotations;resolution:=optional, + nl.basjes.shaded.com.google.errorprone.annotations.concurrent;resolution:=optional, + org.checkerframework.checker.nullness.qual;resolution:=optional, * </Import-Package> </instructions> diff --git a/plugins/request/src/main/java/org/apache/unomi/plugins/request/actions/SetRemoteHostInfoAction.java b/plugins/request/src/main/java/org/apache/unomi/plugins/request/actions/SetRemoteHostInfoAction.java index 05687e8..cc1c5ae 100644 --- a/plugins/request/src/main/java/org/apache/unomi/plugins/request/actions/SetRemoteHostInfoAction.java +++ b/plugins/request/src/main/java/org/apache/unomi/plugins/request/actions/SetRemoteHostInfoAction.java @@ -20,20 +20,6 @@ package org.apache.unomi.plugins.request.actions; import com.maxmind.geoip2.DatabaseReader; import com.maxmind.geoip2.exception.GeoIp2Exception; import com.maxmind.geoip2.model.CityResponse; -import net.sf.uadetector.ReadableUserAgent; -import net.sf.uadetector.UserAgentStringParser; -import net.sf.uadetector.service.UADetectorServiceFactory; -import org.apache.http.conn.util.InetAddressUtils; -import org.apache.unomi.api.Event; -import org.apache.unomi.api.Session; -import org.apache.unomi.api.actions.Action; -import org.apache.unomi.api.actions.ActionExecutor; -import org.apache.unomi.api.services.EventService; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.annotation.PostConstruct; -import javax.servlet.http.HttpServletRequest; import java.io.File; import java.io.IOException; import java.net.InetAddress; @@ -42,10 +28,24 @@ import java.net.SocketException; import java.net.UnknownHostException; import java.util.HashMap; import java.util.Map; +import javax.annotation.PostConstruct; +import javax.servlet.http.HttpServletRequest; +import org.apache.http.conn.util.InetAddressUtils; +import org.apache.unomi.api.Event; +import org.apache.unomi.api.Session; +import org.apache.unomi.api.actions.Action; +import org.apache.unomi.api.actions.ActionExecutor; +import org.apache.unomi.api.services.EventService; +import org.apache.unomi.plugins.request.useragent.UserAgent; +import org.apache.unomi.plugins.request.useragent.UserAgentDetectorServiceImpl; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class SetRemoteHostInfoAction implements ActionExecutor { private static final Logger logger = LoggerFactory.getLogger(SetRemoteHostInfoAction.class.getName()); + private UserAgentDetectorServiceImpl userAgentDetectorService; + private DatabaseReader databaseReader; private String pathToGeoLocationDatabase; @@ -58,6 +58,14 @@ public class SetRemoteHostInfoAction implements ActionExecutor { private double defaultLatitude = 46.1884341; private double defaultLongitude = 6.1282508; + public UserAgentDetectorServiceImpl getUserAgentDetectorService() { + return userAgentDetectorService; + } + + public void setUserAgentDetectorService(UserAgentDetectorServiceImpl userAgentDetectorService) { + this.userAgentDetectorService = userAgentDetectorService; + } + public void setPathToGeoLocationDatabase(String pathToGeoLocationDatabase) { this.pathToGeoLocationDatabase = pathToGeoLocationDatabase; } @@ -150,14 +158,14 @@ public class SetRemoteHostInfoAction implements ActionExecutor { logger.error("Cannot lookup IP", e); } - UserAgentStringParser parser = UADetectorServiceFactory.getResourceModuleParser(); - ReadableUserAgent agent = parser.parse(httpServletRequest.getHeader("User-Agent")); - session.setProperty("operatingSystemFamily", agent.getOperatingSystem().getFamilyName()); - session.setProperty("operatingSystemName", agent.getOperatingSystem().getName()); - session.setProperty("userAgentName", agent.getName()); - session.setProperty("userAgentVersion", agent.getVersionNumber().toVersionString()); - session.setProperty("userAgentNameAndVersion", session.getProperty("userAgentName") + "@@" + session.getProperty("userAgentVersion")); - session.setProperty("deviceCategory", agent.getDeviceCategory().getName()); + + UserAgent agent =userAgentDetectorService.parseUserAgent(httpServletRequest.getHeader("User-Agent")); + session.setProperty("operatingSystemFamily", agent.getOperatingSystemFamily()); + session.setProperty("operatingSystemName", agent.getOperatingSystemName()); + session.setProperty("userAgentName", agent.getUserAgentName()); + session.setProperty("userAgentVersion", agent.getUserAgentVersion()); + session.setProperty("userAgentNameAndVersion", agent.getUserAgentNameAndVersion()); + session.setProperty("deviceCategory", agent.getDeviceCategory()); return EventService.SESSION_UPDATED; } diff --git a/plugins/request/src/main/java/org/apache/unomi/plugins/request/useragent/UserAgent.java b/plugins/request/src/main/java/org/apache/unomi/plugins/request/useragent/UserAgent.java new file mode 100644 index 0000000..69f83b8 --- /dev/null +++ b/plugins/request/src/main/java/org/apache/unomi/plugins/request/useragent/UserAgent.java @@ -0,0 +1,86 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.unomi.plugins.request.useragent; + +/** + * Basic information about a User Agent + */ +public class UserAgent { + + private String operatingSystemFamily; + private String operatingSystemName; + private String userAgentName; + private String userAgentVersion; + private String deviceCategory; + + public String getOperatingSystemFamily() { + return operatingSystemFamily; + } + + public void setOperatingSystemFamily(String operatingSystemFamily) { + this.operatingSystemFamily = operatingSystemFamily; + } + + public String getOperatingSystemName() { + return operatingSystemName; + } + + public void setOperatingSystemName(String operatingSystemName) { + this.operatingSystemName = operatingSystemName; + } + + public String getUserAgentName() { + return userAgentName; + } + + public void setUserAgentName(String userAgentName) { + this.userAgentName = userAgentName; + } + + public String getUserAgentVersion() { + return userAgentVersion; + } + + public void setUserAgentVersion(String userAgentVersion) { + this.userAgentVersion = userAgentVersion; + } + + public String getDeviceCategory() { + return deviceCategory; + } + + public void setDeviceCategory(String deviceCategory) { + this.deviceCategory = deviceCategory; + } + + public String getUserAgentNameAndVersion() { + return this.userAgentName + "@@" + this.userAgentVersion; + } + + @Override + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("User-Agent { \n"); + sb.append("agent.name: " + this.getUserAgentName() + ",\n"); + sb.append("agent.version: " + this.getUserAgentVersion() + ",\n"); + sb.append("operatingsystem.family: " + this.getOperatingSystemFamily() + ",\n"); + sb.append("operatingsystem.name: " + this.getOperatingSystemName() + ",\n"); + sb.append("device.category: " + this.getDeviceCategory() + " \n}"); + return super.toString(); + } +} diff --git a/plugins/request/src/main/java/org/apache/unomi/plugins/request/useragent/UserAgentDetectorServiceImpl.java b/plugins/request/src/main/java/org/apache/unomi/plugins/request/useragent/UserAgentDetectorServiceImpl.java new file mode 100644 index 0000000..cba6a3f --- /dev/null +++ b/plugins/request/src/main/java/org/apache/unomi/plugins/request/useragent/UserAgentDetectorServiceImpl.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.unomi.plugins.request.useragent; + +import nl.basjes.parse.useragent.UserAgentAnalyzer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author fpa...@apache.org + */ +public class UserAgentDetectorServiceImpl { + + private static final Logger logger = LoggerFactory.getLogger(UserAgentDetectorServiceImpl.class.getName()); + + private UserAgentAnalyzer userAgentAnalyzer; + + public void postConstruct() { + ClassLoader tccl = Thread.currentThread().getContextClassLoader(); + try { + Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); + this.userAgentAnalyzer = UserAgentAnalyzer + .newBuilder() + .hideMatcherLoadStats() + .withCache(10000) + .withField(nl.basjes.parse.useragent.UserAgent.OPERATING_SYSTEM_CLASS) + .withField(nl.basjes.parse.useragent.UserAgent.OPERATING_SYSTEM_NAME) + .withField(nl.basjes.parse.useragent.UserAgent.AGENT_NAME) + .withField(nl.basjes.parse.useragent.UserAgent.AGENT_VERSION) + .withField(nl.basjes.parse.useragent.UserAgent.DEVICE_CLASS) + .build(); + this.userAgentAnalyzer.immediateInitialization(); + this.userAgentAnalyzer.initializeMatchers(); + } finally { + Thread.currentThread().setContextClassLoader(tccl); + } + logger.info("UserAgentDetector service initialized."); + } + + public void preDestroy() { + userAgentAnalyzer = null; + logger.info("UserAgentDetector service shutdown."); + } + + public UserAgent parseUserAgent(String header) { + nl.basjes.parse.useragent.UserAgent yauaaAgent = userAgentAnalyzer.parse(header); + + UserAgent userAgent = new UserAgent(); + userAgent.setDeviceCategory(yauaaAgent.getValue(nl.basjes.parse.useragent.UserAgent.DEVICE_CLASS)); + userAgent.setOperatingSystemFamily(yauaaAgent.getValue(nl.basjes.parse.useragent.UserAgent.OPERATING_SYSTEM_CLASS)); + userAgent.setOperatingSystemName(yauaaAgent.getValue(nl.basjes.parse.useragent.UserAgent.OPERATING_SYSTEM_NAME)); + userAgent.setUserAgentName(yauaaAgent.getValue(nl.basjes.parse.useragent.UserAgent.AGENT_NAME)); + userAgent.setUserAgentVersion(yauaaAgent.getValue(nl.basjes.parse.useragent.UserAgent.AGENT_VERSION)); + + if (logger.isDebugEnabled()) { + logger.debug(userAgent.toString()); + } + + return userAgent; + } +} diff --git a/plugins/request/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/plugins/request/src/main/resources/OSGI-INF/blueprint/blueprint.xml index 7411399..9b48229 100644 --- a/plugins/request/src/main/resources/OSGI-INF/blueprint/blueprint.xml +++ b/plugins/request/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -67,6 +67,8 @@ </service-properties> <bean class="org.apache.unomi.plugins.request.actions.SetRemoteHostInfoAction" init-method="postConstruct"> + <property name="userAgentDetectorService" ref="userAgentDetectorServiceImpl"/> + <property name="pathToGeoLocationDatabase" value="${request.ipDatabase.location}"/> <property name="defaultSessionCountryCode" value="${defaultSessionCountryCode}"/> @@ -81,4 +83,8 @@ </bean> </service> + <bean id="userAgentDetectorServiceImpl" class="org.apache.unomi.plugins.request.useragent.UserAgentDetectorServiceImpl" + init-method="postConstruct" destroy-method="preDestroy"> + </bean> + </blueprint> diff --git a/plugins/request/src/test/java/org/apache/unomi/plugins/request/actions/UserAgentDetectorTest.java b/plugins/request/src/test/java/org/apache/unomi/plugins/request/actions/UserAgentDetectorTest.java new file mode 100644 index 0000000..4733c4e --- /dev/null +++ b/plugins/request/src/test/java/org/apache/unomi/plugins/request/actions/UserAgentDetectorTest.java @@ -0,0 +1,104 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.unomi.plugins.request.actions; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import org.apache.unomi.plugins.request.useragent.UserAgent; +import org.apache.unomi.plugins.request.useragent.UserAgentDetectorServiceImpl; +import org.junit.After; +import org.junit.Before; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class UserAgentDetectorTest { + + private static final Logger logger = LoggerFactory.getLogger(UserAgentDetectorTest.class); + + private UserAgentDetectorServiceImpl userAgentDetectorService; + + @Before + public void init() { + long start = System.currentTimeMillis(); + this.userAgentDetectorService = new UserAgentDetectorServiceImpl(); + this.userAgentDetectorService.postConstruct(); + long end = System.currentTimeMillis(); + logger.info("Duration starting user agent (in msec) > {}", (end - start)); + } + + @After + public void end() { + this.userAgentDetectorService.preDestroy(); + } + + @Test + public void testFirstUserAgentDetection() { + String header = "Mozilla/5.0 (Linux; Android 7.0; Nexus 6 Build/NBD90Z) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.124 Mobile Safari/537.36"; + + long start = System.currentTimeMillis(); + UserAgent agent = this.userAgentDetectorService.parseUserAgent(header); + long end = System.currentTimeMillis(); + logger.info("Duration user agent parsing (in msec) > {}", (end - start)); + logger.info(agent.toString()); + } + + @Test + public void testUserAgentDetectionPerformance() throws InterruptedException { + int workerCount = 5000000; + ExecutorService executorService = Executors.newFixedThreadPool(3000); + + for (int cpt = 1; cpt < 6; cpt++) { + logger.info("Execution " + cpt + "/5"); + executeWorker(executorService, workerCount); + } + } + + private void executeWorker(ExecutorService executorService, int workerCount) throws InterruptedException { + List<Callable<Object>> callables = new ArrayList<>(workerCount); + long startTime = System.currentTimeMillis(); + for (int i = 0; i < workerCount; i++) { + callables.add(new AgentWorker(this.userAgentDetectorService)); + } + executorService.invokeAll(callables); + long totalTime = System.currentTimeMillis() - startTime; + logger.info("AgentWorker workers completed execution in " + totalTime + "ms"); + } + + private class AgentWorker implements Callable<Object> { + + String header = "Mozilla/5.0 (Linux; Android 7.0; Nexus 6 Build/NBD90Z) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.124 Mobile Safari/537.36"; + UserAgentDetectorServiceImpl service; + + public AgentWorker(UserAgentDetectorServiceImpl userAgentDetectorService) { + this.service = userAgentDetectorService; + } + + @Override + public Object call() { + this.service.parseUserAgent(header); + return null; + } + } + +} diff --git a/pom.xml b/pom.xml index 8ba671b..67f51f5 100644 --- a/pom.xml +++ b/pom.xml @@ -83,6 +83,7 @@ <!-- Librairies for Karaf packaging --> <xerces.version>2.11.0_1</xerces.version> <servicemix.specs.version>2.9.0</servicemix.specs.version> + <jsr305.bundle.version>3.0.2_1</jsr305.bundle.version> <xalan.bundle.version>2.7.2_3</xalan.bundle.version> <xalan-serializer.bundle.version>2.7.2_1</xalan-serializer.bundle.version> <jna.version>4.5.0</jna.version> @@ -281,10 +282,6 @@ <name>Apache ServiceMix M2</name> <url>http://svn.apache.org/repos/asf/servicemix/m2-repo/</url> </repository> - <repository> - <id>jahia.3rdparty</id> - <url>https://devtools.jahia.com/nexus/content/repositories/thirdparty-releases/</url> - </repository> <!-- Apache snapshots --> <repository> <id>apache-snapshots</id> @@ -323,6 +320,35 @@ </profile> <profile> + <id>ci-build-itests</id> + <activation> + <property> + <name>maven.repo.local</name> + </property> + </activation> + <modules> + <module>itests</module> + </modules> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <configuration> + <excludes> + <exclude>MavenTest</exclude> + </excludes> + <systemPropertyVariables> + <org.ops4j.pax.url.mvn.localRepository>${maven.repo.local}</org.ops4j.pax.url.mvn.localRepository> + <org.ops4j.pax.logging.DefaultServiceLog.level>INFO</org.ops4j.pax.logging.DefaultServiceLog.level> + </systemPropertyVariables> + </configuration> + </plugin> + </plugins> + </build> + </profile> + + <profile> <id>performance-tests</id> <activation> <activeByDefault>false</activeByDefault> diff --git a/services/pom.xml b/services/pom.xml index 7c494ef..fa6e67d 100644 --- a/services/pom.xml +++ b/services/pom.xml @@ -139,6 +139,20 @@ <version>4.3.0</version> </dependency> + <!-- Unit tests --> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.11</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-simple</artifactId> + <version>1.6.6</version> + <scope>test</scope> + </dependency> + </dependencies> <build> diff --git a/services/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/services/src/main/resources/OSGI-INF/blueprint/blueprint.xml index 9569e67..e09a38b 100644 --- a/services/src/main/resources/OSGI-INF/blueprint/blueprint.xml +++ b/services/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -382,5 +382,4 @@ </service-properties> </service> - </blueprint>