Author: wkeil Date: Sat Dec 19 14:29:10 2015 New Revision: 1720931 URL: http://svn.apache.org/viewvc?rev=1720931&view=rev Log: DMAP-117: Results differ from OS version in UA
Task-Url: https://issues.apache.org/jira/browse/DMAP-117 Added: devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/data/UserAgent.java Modified: devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/DeviceMapClient.java devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/data/DeviceType.java devicemap/trunk/clients/1.0/java/client/src/test/java/org/apache/devicemap/DeviceMapClientUnitTest.java devicemap/trunk/clients/1.0/java/console/src/main/java/org/apache/devicemap/console/Main.java Modified: devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/DeviceMapClient.java URL: http://svn.apache.org/viewvc/devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/DeviceMapClient.java?rev=1720931&r1=1720930&r2=1720931&view=diff ============================================================================== --- devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/DeviceMapClient.java (original) +++ devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/DeviceMapClient.java Sat Dec 19 14:29:10 2015 @@ -27,6 +27,7 @@ import org.apache.devicemap.data.Device; import org.apache.devicemap.loader.LoaderOption; import org.apache.devicemap.data.DeviceType; import org.apache.devicemap.data.Pattern; +import org.apache.devicemap.data.UserAgent; import org.apache.devicemap.loader.LoaderFactory; public class DeviceMapClient { @@ -109,7 +110,7 @@ public class DeviceMapClient { DeviceType winner = null; Pattern winnerPattern = null; - LOG.log(Level.FINE, "classify: ''{0}''", text); + LOG.log(Level.INFO, "classify: ''{0}''", text); // TODO set back to FINE List<String> parts = split(text); @@ -145,13 +146,51 @@ public class DeviceMapClient { } if (winner != null) { - LOG.log(Level.FINE, "Result: {0}", winner); - return winner.getAttributes(); + LOG.log(Level.INFO, "Result: {0}", winner); // TODO set back to FINE + + UserAgent userAgent = UserAgent.of(text); + LOG.log(Level.INFO, "User Agent: {0}", userAgent); + //fixFromUserAgent(winner, userAgent); + return fixFromUserAgent(winner, userAgent).getAttributes(); } else { return null; } } + private static final String DEVICE_OS_VERSION = "device_os_version"; + private static final String ANDROID = "Android"; + + private DeviceType fixFromUserAgent(final DeviceType device, final UserAgent userAgent) { + String pattern = userAgent.getPatternElementsInside(); + if (pattern != null && pattern.contains(";")) { + Map<String, String> attributes; + if (device.isLocked()) { + // clone map + attributes = new HashMap<String, String>(); + + attributes.putAll(device.getAttributes()); + } else { + attributes = device.getAttributes(); + } + String[] parts = pattern.split(";"); + + for (String part : parts) { + if (part.trim().startsWith(ANDROID)) { + final String versionPart = part.trim().substring(ANDROID.length()).trim(); + final String versionExisting = attributes.get(DEVICE_OS_VERSION); + if (!versionPart.equals(versionExisting)) { + LOG.fine("Fixing '" + versionExisting +"' to '" + versionPart + "'" ); + attributes.put(DEVICE_OS_VERSION, versionPart); + device.setAttributes(attributes); + } + } + } + } +// } +// logger.info("Device: " + device.getId() + " - " + device.getPropertiesMap()); + return device; + } + private static List<String> split(String text) { String[] parts = TEXT_SPLIT_PATTERN.split(text); List<String> nonemptyParts = new ArrayList<String>(); Modified: devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/data/DeviceType.java URL: http://svn.apache.org/viewvc/devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/data/DeviceType.java?rev=1720931&r1=1720930&r2=1720931&view=diff ============================================================================== --- devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/data/DeviceType.java (original) +++ devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/data/DeviceType.java Sat Dec 19 14:29:10 2015 @@ -32,6 +32,8 @@ public class DeviceType { private Map<String, String> attributes; + private boolean locked; + public DeviceType() { pattern = new PatternSet(); } @@ -76,9 +78,15 @@ public class DeviceType { public void setAttributes(Map<String, String> attributes) { this.attributes = attributes; + this.locked = false; } public void lockAttributes() { attributes = Collections.unmodifiableMap(attributes); + locked = true; + } + + public boolean isLocked() { + return locked; } } Added: devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/data/UserAgent.java URL: http://svn.apache.org/viewvc/devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/data/UserAgent.java?rev=1720931&view=auto ============================================================================== --- devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/data/UserAgent.java (added) +++ devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/data/UserAgent.java Sat Dec 19 14:29:10 2015 @@ -0,0 +1,192 @@ +/** + * 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.devicemap.data; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class UserAgent { + private static final String ANDROID = "Android"; + + public static final String MOZILLA_AND_OPERA_PATTERN = "(.*?)((?:Mozilla)|(?:Opera))[/ ](\\d+\\.\\d+).*?\\(((?:.*?)(?:.*?\\(.*?\\))*(?:.*?))\\)(.*)"; + public static final int INDEX_MOZILLA_PATTERN_GROUP_PRE = 1; + public static final int INDEX_MOZILLA_PATTERN_GROUP_INSIDE = 4; + public static final int INDEX_MOZILLA_PATTERN_GROUP_POST = 5; + public static final int INDEX_MOZILLA_PATTERN_GROUP_MOZ_VER = 3; + public static final int INDEX_OPERA_OR_MOZILLA = 2; + private static Pattern mozillaPatternCompiled = + Pattern.compile(MOZILLA_AND_OPERA_PATTERN); + private static Pattern versionPatternCompiled = + Pattern.compile(".*Version/(\\d+.\\d+).*"); + private String completeUserAgent; + private boolean mozillaPattern; + private boolean operaPattern; + private String mozillaVersion; + private String operaVersion; + private boolean containsAndroid; + private boolean containsBlackBerryOrRim; + private boolean containsIOSDevices; + private boolean containsMSIE; + private boolean containsSymbian; + private boolean containsWindowsPhone; + private String[] patternElements; + + UserAgent(String userAgent) { + if (userAgent == null) { + throw new IllegalArgumentException("userAgent can not be null"); + } + completeUserAgent = userAgent; + + Matcher result = mozillaPatternCompiled.matcher(userAgent); + + if (result.matches()) { + patternElements = new String[]{ + result.group(INDEX_MOZILLA_PATTERN_GROUP_PRE), + result.group(INDEX_MOZILLA_PATTERN_GROUP_INSIDE), + result.group(INDEX_MOZILLA_PATTERN_GROUP_POST) + }; + String version = result.group(INDEX_MOZILLA_PATTERN_GROUP_MOZ_VER); + if (result.group(INDEX_OPERA_OR_MOZILLA).contains("Opera")) { + mozillaPattern = false; + operaPattern = true; + operaVersion = version; + + if (operaVersion.equals("9.80") && patternElements[2] != null) { + Matcher result2 = versionPatternCompiled.matcher(patternElements[2]); + + if (result2.matches()) { + operaVersion = result2.group(1); + } + } + + } else { + mozillaPattern = true; + mozillaVersion = version; + } + + } else { + mozillaPattern = false; + operaPattern = false; + patternElements = new String[]{ + null, + null, + null}; + mozillaVersion = null; + operaVersion = null; + } + + if (userAgent.contains(ANDROID)) { + containsAndroid = true; + + } else { + containsAndroid = false; + if (userAgent.matches(".*(?!like).iPad.*") || userAgent.matches(".*(?!like).iPod.*") || userAgent.matches(".*(?!like).iPhone.*")) { + containsIOSDevices = true; + + } else { + containsIOSDevices = false; + if (userAgent.matches(".*[Bb]lack.?[Bb]erry.*|.*RIM.?Tablet.?OS.*")) { + containsBlackBerryOrRim = true; + + } else { + containsBlackBerryOrRim = false; + if (userAgent.matches(".*Symbian.*|.*SymbOS.*|.*Series.?60.*")) { + containsSymbian = true; + + } else { + containsSymbian = false; + if (userAgent.matches(".*Windows.?(?:(?:CE)|(?:Phone)|(?:NT)|(?:Mobile)).*")) { + containsWindowsPhone = true; + + } else { + containsWindowsPhone = false; + } + + if (userAgent.matches(".*MSIE.([0-9\\.b]+).*")) { + containsMSIE = true; + + } else { + containsMSIE = false; + } + } + } + } + } + } + + public String getCompleteUserAgent() { + return completeUserAgent; + } + + public boolean containsAndroid() { + return containsAndroid; + } + + public boolean containsBlackBerryOrRim() { + return containsBlackBerryOrRim; + } + + public boolean containsIOSDevices() { + return containsIOSDevices; + } + + public boolean containsMSIE() { + return containsMSIE; + } + + public boolean containsSymbian() { + return containsSymbian; + } + + public boolean containsWindowsPhone() { + return containsWindowsPhone; + } + + public boolean hasMozillaPattern() { + return mozillaPattern; + } + + public boolean hasOperaPattern() { + return operaPattern; + } + + public String getPatternElementsPre() { + return patternElements[0]; + } + + public String getPatternElementsInside() { + return patternElements[1]; + } + + public String getPatternElementsPost() { + return patternElements[2]; + } + + public String getMozillaVersion() { + return mozillaVersion; + } + + public String getOperaVersion() { + return operaVersion; + } + + public static UserAgent of(String realUserAgent) { + return new UserAgent(realUserAgent); + } +} Modified: devicemap/trunk/clients/1.0/java/client/src/test/java/org/apache/devicemap/DeviceMapClientUnitTest.java URL: http://svn.apache.org/viewvc/devicemap/trunk/clients/1.0/java/client/src/test/java/org/apache/devicemap/DeviceMapClientUnitTest.java?rev=1720931&r1=1720930&r2=1720931&view=diff ============================================================================== --- devicemap/trunk/clients/1.0/java/client/src/test/java/org/apache/devicemap/DeviceMapClientUnitTest.java (original) +++ devicemap/trunk/clients/1.0/java/client/src/test/java/org/apache/devicemap/DeviceMapClientUnitTest.java Sat Dec 19 14:29:10 2015 @@ -19,6 +19,7 @@ package org.apache.devicemap; import org.junit.Assert; +import org.junit.Ignore; import org.junit.Test; import org.apache.devicemap.data.Device; @@ -49,6 +50,7 @@ public class DeviceMapClientUnitTest { } @Test + @Ignore("Fixing attributes requires updating the map as of now") public void deviceMapClientMutateTest() throws Exception { String test = "Mozilla/5.0 (Linux; U; Android 2.2; en; HTC Aria A6380 Build/ERE27) AppleWebKit/540.13+ (KHTML, like Gecko) Version/3.1 Mobile Safari/524.15.0"; Modified: devicemap/trunk/clients/1.0/java/console/src/main/java/org/apache/devicemap/console/Main.java URL: http://svn.apache.org/viewvc/devicemap/trunk/clients/1.0/java/console/src/main/java/org/apache/devicemap/console/Main.java?rev=1720931&r1=1720930&r2=1720931&view=diff ============================================================================== --- devicemap/trunk/clients/1.0/java/console/src/main/java/org/apache/devicemap/console/Main.java (original) +++ devicemap/trunk/clients/1.0/java/console/src/main/java/org/apache/devicemap/console/Main.java Sat Dec 19 14:29:10 2015 @@ -78,6 +78,7 @@ public class Main { } //[test string] | [test file] else if(!args[i].isEmpty()) { parameter = args[i]; + System.out.println(parameter); } }
