it = en.getData().iterator();
390 | deviceRegMapTmp.put(convertPerlToJavaRegex(it.next()), Long.parseLong(it.next()));
391 | }
392 | deviceRegMap = deviceRegMapTmp;
393 | }
394 | }
395 | preCompileRegExes();
396 | }
397 |
398 | /**
399 | * Converts a PERL style regex into the Java style. That means in removes the leading and the last / and removes the modifiers
400 | *
401 | * @param regex
402 | * @return
403 | */
404 | protected String convertPerlToJavaRegex(String regex) {
405 | regex = regex.substring(1);
406 | int lastIndex = regex.lastIndexOf('/');
407 | regex = regex.substring(0, lastIndex);
408 | return regex;
409 | }
410 |
411 | }
412 |
--------------------------------------------------------------------------------
/src/main/java/cz/mallat/uasparser/UserAgentInfo.java:
--------------------------------------------------------------------------------
1 | package cz.mallat.uasparser;
2 |
3 | /**
4 | * Encapsulates all information pertaining to a User Agent. Returned by calling
5 | * {@link UASparser#parse(String)}.
6 | *
7 | * Note that all information comes from the database provided at
8 | * user-agent-string.info. If you have problems with
9 | * or questions about the data returned, please contact the maintainer of the database directly.
10 | *
11 | * @author oli
12 | * @author Felix Siegrist, Inventage AG
13 | *
14 | */
15 | public class UserAgentInfo {
16 |
17 | public static final String UNKNOWN = "unknown";
18 |
19 | private String type;
20 | private String browserVersionInfo;
21 |
22 | private RobotEntry robotEntry;
23 | private BrowserEntry browserEntry;
24 | private OsEntry osEntry;
25 | private DeviceEntry deviceEntry;
26 |
27 | public UserAgentInfo() {
28 | this.type = UNKNOWN;
29 | }
30 |
31 | /**
32 | * Returns true if this represents a Robot
33 | * @return
34 | */
35 | public boolean isRobot() {
36 | return UASparser.ROBOT.equals(type);
37 | }
38 |
39 | public boolean hasOsInfo() {
40 | return osEntry != null;
41 | }
42 |
43 | public boolean hasDeviceInfo() {
44 | return deviceEntry != null;
45 | }
46 |
47 | /**
48 | * Retrieve the type of UA. Can be one of the following:
49 | *
50 | *
51 | * - "Browser"
52 | *
- "Offline Browser"
53 | *
- "Mobile Browser"
54 | *
- "Email client"
55 | *
- "Library"
56 | *
- "Wap Browser"
57 | *
- "Validator"
58 | *
- "Feed Reader"
59 | *
- "Multimedia Player"
60 | *
- "Other"
61 | *
- "Useragent Anonymizer"
62 | *
- "Robot"
63 | *
64 | *
65 | * @return {@link String} type
66 | */
67 | public String getType() {
68 | if (type == null) {
69 | return UNKNOWN;
70 | }
71 | return type;
72 | }
73 |
74 | public void setType(String type) {
75 | this.type = type;
76 | }
77 |
78 | /**
79 | * Retrieve the product family; i.e., given the UA:
80 | *
81 | * "Mozilla/5.0 (Windows; U; Windows NT 6.1; pt-BR; rv:1.9.1.1) Gecko/20090715 Firefox/3.5.1"
82 | *
83 | * it would return "Firefox"
84 | *
85 | * @return {@link String} URL
86 | */
87 | public String getUaFamily() {
88 | if (browserEntry != null) {
89 | return browserEntry.getFamily();
90 | }
91 | if (robotEntry != null) {
92 | return robotEntry.getFamily();
93 | }
94 | return UNKNOWN;
95 | }
96 |
97 | /**
98 | * Retrieve the UA name and version; i.e., given the UA:
99 | *
100 | * "Mozilla/5.0 (Windows; U; Windows NT 6.1; pt-BR; rv:1.9.1.1) Gecko/20090715 Firefox/3.5.1"
101 | *
102 | * it would return "Firefox 3.5.1"
103 | *
104 | * @return {@link String} UA name
105 | */
106 | public String getUaName() {
107 | if (browserEntry != null) {
108 | if (browserVersionInfo != null && !browserVersionInfo.isEmpty()) {
109 | return getUaFamily() + " " + browserVersionInfo;
110 | }
111 | return getUaFamily();
112 | }
113 | if (robotEntry != null) {
114 | return robotEntry.getName();
115 | }
116 | return UNKNOWN;
117 | }
118 |
119 | /**
120 | * Retrieve the URL of the UA's product page; i.e., given the UA:
121 | *
122 | * "Mozilla/5.0 (Windows; U; Windows NT 6.1; pt-BR; rv:1.9.1.1) Gecko/20090715 Firefox/3.5.1"
123 | *
124 | * it would return "http://www.firefox.com/"
125 | *
126 | * @return {@link String} URL
127 | */
128 | public String getUaUrl() {
129 | if (browserEntry != null) {
130 | return browserEntry.getUrl();
131 | }
132 | if (robotEntry != null) {
133 | return robotEntry.getUrl();
134 | }
135 | return UNKNOWN;
136 | }
137 |
138 | /**
139 | * Retrieve the URL path for the given UA on user-agent-string.info; i.e., given the UA:
140 | *
141 | * "Mozilla/5.0 (Windows; U; Windows NT 6.1; pt-BR; rv:1.9.1.1) Gecko/20090715 Firefox/3.5.1"
142 | *
143 | * it would return "/list-of-ua/browser-detail?browser=Firefox" which could then be accessed
144 | * at http://user-agent-string.info/list-of-ua/browser-detail?browser=Firefox
145 | *
146 | * @return {@link String} URL path
147 | */
148 | public String getUaInfoUrl() {
149 | if (browserEntry != null) {
150 | return UASparser.INFO_URL + browserEntry.getInfoUrl();
151 | }
152 | if (robotEntry != null) {
153 | return UASparser.INFO_URL + robotEntry.getInfoUrl();
154 | }
155 | return UNKNOWN;
156 | }
157 |
158 | /**
159 | * Retrieve the name of the company which developed the given UA; i.e., given the UA:
160 | *
161 | * "Mozilla/5.0 (Windows; U; Windows NT 6.1; pt-BR; rv:1.9.1.1) Gecko/20090715 Firefox/3.5.1"
162 | *
163 | * it would return "Mozilla Foundation"
164 | *
165 | * @return {@link String} URL
166 | */
167 | public String getUaCompany() {
168 | if (browserEntry != null) {
169 | return browserEntry.getCompany();
170 | }
171 | if (robotEntry != null) {
172 | return robotEntry.getCompany();
173 | }
174 | return UNKNOWN;
175 | }
176 |
177 | /**
178 | * Retrieve the URL of the company which developed the given UA; i.e., given the UA:
179 | *
180 | * "Mozilla/5.0 (Windows; U; Windows NT 6.1; pt-BR; rv:1.9.1.1) Gecko/20090715 Firefox/3.5.1"
181 | *
182 | * it would return "http://www.mozilla.org/"
183 | *
184 | * @return {@link String} URL
185 | */
186 | public String getUaCompanyUrl() {
187 | if (browserEntry != null) {
188 | return browserEntry.getCompanyUrl();
189 | }
190 | if (robotEntry != null) {
191 | return robotEntry.getCompanyUrl();
192 | }
193 | return UNKNOWN;
194 | }
195 |
196 | /**
197 | * Retrieve the icon filename, if available; i.e., given the UA:
198 | *
199 | * "Mozilla/5.0 (Windows; U; Windows NT 6.1; pt-BR; rv:1.9.1.1) Gecko/20090715 Firefox/3.5.1"
200 | *
201 | * it would return "firefox.png"
202 | *
203 | * @return {@link String} URL
204 | * @see http://user-agent-string.info/download
205 | */
206 | public String getUaIcon() {
207 | if (browserEntry != null) {
208 | return browserEntry.getIco();
209 | }
210 | if (robotEntry != null) {
211 | return robotEntry.getIco();
212 | }
213 | return UNKNOWN;
214 | }
215 |
216 | /**
217 | * Retrieve the OS family name
218 | * @return
219 | */
220 | public String getOsFamily() {
221 | if (osEntry != null) {
222 | return osEntry.getFamily();
223 | }
224 | return UNKNOWN;
225 | }
226 |
227 | /**
228 | * Retrieve the OS name
229 | * @return
230 | */
231 | public String getOsName() {
232 | if (osEntry != null) {
233 | return osEntry.getName();
234 | }
235 | return UNKNOWN;
236 | }
237 |
238 | /**
239 | * Retrieve the URL to the OS vendor's product page
240 | * @return
241 | */
242 | public String getOsUrl() {
243 | if (osEntry != null) {
244 | return osEntry.getUrl();
245 | }
246 | return UNKNOWN;
247 | }
248 |
249 | /**
250 | * Retrieve the name of the OS vendor
251 | * @return
252 | */
253 | public String getOsCompany() {
254 | if (osEntry != null) {
255 | return osEntry.getCompany();
256 | }
257 | return UNKNOWN;
258 | }
259 |
260 | /**
261 | * Retrieve the URL to the OS vendor's homepage
262 | * @return
263 | */
264 | public String getOsCompanyUrl() {
265 | if (osEntry != null) {
266 | return osEntry.getCompanyUrl();
267 | }
268 | return UNKNOWN;
269 | }
270 |
271 | /**
272 | * Retrieve the filename of the OS icon
273 | * @return
274 | * @see http://user-agent-string.info/download
275 | */
276 | public String getOsIcon() {
277 | if (osEntry != null) {
278 | return osEntry.getIco();
279 | }
280 | return UNKNOWN;
281 | }
282 |
283 | /**
284 | * Retrieve the UA version number; i.e., given the UA:
285 | *
286 | * "Mozilla/5.0 (Windows; U; Windows NT 6.1; pt-BR; rv:1.9.1.1) Gecko/20090715 Firefox/3.5.1"
287 | *
288 | * it would return "3.5.1"
289 | *
290 | * @return {@link String} version number
291 | */
292 | public String getBrowserVersionInfo() {
293 | return browserVersionInfo;
294 | }
295 |
296 | /**
297 | * Retrieve the type of the device, if available. Can be one of the following:
298 | *
299 | *
300 | * - "Personal computer"
301 | *
- "Smartphone"
302 | *
- "Tablet"
303 | *
- "Game console"
304 | *
- "Smart TV"
305 | *
- "Other"
306 | *
307 | *
308 | * @return {@link String} type
309 | */
310 | public String getDeviceType() {
311 | return deviceEntry != null ? deviceEntry.getType() : UNKNOWN;
312 | }
313 |
314 | /**
315 | * Retrieve the icon filename, if available; i.e., given the UA:
316 | *
317 | * "Mozilla/5.0 (Linux; U; Android 2.3.5; de-ch; HTC_DesireHD_A9191 Build/GRJ90) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"
318 | *
319 | * it would return "phone.png"
320 | *
321 | * @return {@link String} URL
322 | * @see http://user-agent-string.info/download
323 | */
324 | public String getDeviceIcon() {
325 | return deviceEntry != null ? deviceEntry.getIco() : UNKNOWN;
326 | }
327 |
328 | /**
329 | * Retrieve the URL path for the given UA on user-agent-string.info; i.e., given the UA:
330 | *
331 | * "Mozilla/5.0 (Linux; U; Android 2.3.5; de-ch; HTC_DesireHD_A9191 Build/GRJ90) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"
332 | *
333 | * it would return "http://user-agent-string.info/list-of-ua/device-detail?device=Smartphone".
334 | *
335 | * @return {@link String} URL path
336 | */
337 | public String getDeviceInfoUrl() {
338 | return deviceEntry != null ? UASparser.INFO_URL + deviceEntry.getInfoUrl() : UNKNOWN;
339 | }
340 |
341 |
342 | // setters
343 |
344 | public void setBrowserEntry(BrowserEntry browserEntry) {
345 | this.browserEntry = browserEntry;
346 | }
347 |
348 | public void setBrowserVersionInfo(String browserVersionInfo) {
349 | this.browserVersionInfo = browserVersionInfo;
350 | }
351 |
352 | public void setOsEntry(OsEntry osEntry) {
353 | this.osEntry = osEntry;
354 | }
355 |
356 | public void setRobotEntry(RobotEntry robotEntry) {
357 | this.robotEntry = robotEntry;
358 | }
359 |
360 | public void setDeviceEntry(DeviceEntry deviceEntry) {
361 | this.deviceEntry = deviceEntry;
362 | }
363 |
364 | @Override
365 | public String toString() {
366 | StringBuilder sb = new StringBuilder();
367 |
368 | sb.append("Name: " + getUaName() + "\n");
369 | sb.append("Type: " + getType() + "\n");
370 |
371 | if (robotEntry != null) {
372 | sb.append(robotEntry + "\n");
373 | } else {
374 | sb.append("Robot: no\n");
375 | }
376 |
377 | if (browserEntry != null) {
378 | sb.append(browserEntry + "\n");
379 | } else {
380 | sb.append("Browser: no\n");
381 | }
382 |
383 | if (osEntry != null) {
384 | sb.append(osEntry + "\n");
385 | } else {
386 | sb.append("Operating System: n/a\n");
387 | }
388 |
389 | if (deviceEntry != null) {
390 | sb.append(deviceEntry + "\n");
391 | } else {
392 | sb.append("Device: n/a\n");
393 | }
394 |
395 | return sb.toString();
396 | }
397 |
398 | }
--------------------------------------------------------------------------------
/src/main/java/cz/mallat/uasparser/fileparser/Entry.java:
--------------------------------------------------------------------------------
1 | package cz.mallat.uasparser.fileparser;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | /**
7 | * JavaBean that holds an entry from a parsed file
8 | *
9 | * @author oli
10 | */
11 | public class Entry {
12 |
13 | private String key;
14 | private List data = new ArrayList();
15 |
16 | public Entry(String key) {
17 | this.key = key;
18 | }
19 |
20 | public String getKey() {
21 | return key;
22 | }
23 |
24 | public void setKey(String key) {
25 | this.key = key;
26 | }
27 |
28 | public List getData() {
29 | return data;
30 | }
31 |
32 | public void setData(List data) {
33 | this.data = data;
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/java/cz/mallat/uasparser/fileparser/PHPFileParser.java:
--------------------------------------------------------------------------------
1 | package cz.mallat.uasparser.fileparser;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.File;
5 | import java.io.FileReader;
6 | import java.io.IOException;
7 | import java.io.InputStream;
8 | import java.io.InputStreamReader;
9 | import java.io.Reader;
10 | import java.util.ArrayList;
11 | import java.util.List;
12 |
13 | /**
14 | * Emulates the behavior of the php function "parse_ini_file".
15 | *
16 | * Does NOT support all features of the php function.
17 | *
18 | * @author oli
19 | */
20 | public class PHPFileParser {
21 |
22 | private List sections;
23 |
24 | public PHPFileParser(InputStream is) throws IOException {
25 | loadFile(new InputStreamReader(is));
26 | }
27 |
28 | public PHPFileParser(Reader reader) throws IOException {
29 | loadFile(reader);
30 | }
31 |
32 | public PHPFileParser(File file) throws IOException {
33 | Reader reader = new FileReader(file);
34 | try {
35 | loadFile(reader);
36 | } finally {
37 | try {
38 | reader.close();
39 | } catch (IOException e) {
40 | }
41 | }
42 | }
43 |
44 | private void loadFile(Reader reader) throws IOException {
45 | this.sections = new ArrayList();
46 |
47 | BufferedReader bufferedReader = new BufferedReader(reader);
48 |
49 | int unnamedSectionCounter = 0;
50 |
51 | Section currentSection = null;
52 | Entry currentEntry = null;
53 |
54 | String line = bufferedReader.readLine();
55 | while (line != null) {
56 | if (line.trim().startsWith(";")) {
57 | // comment, do nothing
58 | } else if (line.trim().startsWith("[") && line.trim().endsWith("]")) {
59 | String rawLine = line.trim();
60 | String sectionName = rawLine.substring(1, rawLine.length() - 1);
61 | currentSection = new Section(sectionName);
62 | sections.add(currentSection);
63 | } else {
64 | if (currentSection == null) {
65 | currentSection = new Section("unname section" + (++unnamedSectionCounter));
66 | sections.add(currentSection);
67 | }
68 |
69 | int indexOfEquals = line.indexOf('=');
70 | String key = line.substring(0, indexOfEquals);
71 | String data = line.substring(indexOfEquals + 1);
72 | key = key.replace('[', ' ');
73 | key = key.replace(']', ' ');
74 | key = key.trim();
75 | data = data.trim();
76 | if (data.startsWith("\"") && data.endsWith("\"")) {
77 | data = data.substring(1, data.length() - 1);
78 | }
79 |
80 | if (currentEntry == null || !currentEntry.getKey().equals(key)) {
81 | currentEntry = new Entry(key);
82 | currentSection.getEntries().add(currentEntry);
83 | }
84 |
85 | currentEntry.getData().add(data);
86 | }
87 |
88 | line = bufferedReader.readLine();
89 | }
90 |
91 | }
92 |
93 | public List getSections() {
94 | return sections;
95 | }
96 |
97 | }
98 |
--------------------------------------------------------------------------------
/src/main/java/cz/mallat/uasparser/fileparser/Section.java:
--------------------------------------------------------------------------------
1 | package cz.mallat.uasparser.fileparser;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | /**
7 | * JavaBean that holds a section from a parsed file. A section is a row in square brackets, e.g. [main]
8 | *
9 | * @author oli
10 | */
11 | public class Section {
12 |
13 | private String name;
14 | private List entries;
15 |
16 | public Section(String sectionName) {
17 | this.name = sectionName;
18 | this.entries = new ArrayList();
19 | }
20 |
21 | public String getName() {
22 | return name;
23 | }
24 |
25 | public void setName(String name) {
26 | this.name = name;
27 | }
28 |
29 | public List getEntries() {
30 | return entries;
31 | }
32 |
33 | public void setEntries(List entries) {
34 | this.entries = entries;
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/src/test/java/cz/mallat/uasparser/Benchmark.java:
--------------------------------------------------------------------------------
1 | package cz.mallat.uasparser;
2 |
3 | import java.io.IOException;
4 | import java.io.InputStream;
5 | import java.util.ArrayList;
6 | import java.util.List;
7 |
8 | /**
9 | * Performance tests
10 | *
11 | * Copyright: Copyright (c) 09.10.2012
12 | * Company: Braintags GmbH
13 | *
14 | * @author mremme
15 | */
16 | public class Benchmark {
17 |
18 | public static InputStream getIni() {
19 | return OnlineUpdater.getVendoredInputStream();
20 | }
21 |
22 | public static void main(String[] args) {
23 |
24 | try {
25 | List parserList = new ArrayList();
26 | parserList.add(new UASparser(getIni()));
27 | parserList.add(new SingleThreadedUASparser(getIni()));
28 | parserList.add(new MultithreadedUASparser(getIni()));
29 | //parserList.add(new OnlineUpdateUASparser());
30 |
31 | List uaList = new ArrayList();
32 | uaList.add("user-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.12) Gecko/20050922 Fedora/1.0.7-1.1.fc3 Firefox/1.0.7");
33 | uaList.add("user-agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322)");
34 | uaList.add("WhatWeb/0.4.7");
35 | uaList.add("check_http/v1.4.16 (nagios-plugins 1.4.16)");
36 | uaList.add("Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)");
37 |
38 | List expectedTypes = new ArrayList();
39 | expectedTypes.add("Browser");
40 | expectedTypes.add("Browser");
41 | expectedTypes.add("unknown");
42 | expectedTypes.add("Other");
43 | expectedTypes.add("Robot");
44 |
45 | for (UASparser uaParser : parserList) {
46 | performTest(uaParser, uaList);
47 | }
48 |
49 | } catch (Exception e) {
50 | e.printStackTrace();
51 | }
52 |
53 | }
54 |
55 | private static final void performTest(UASparser uaParser, List uaList) throws IOException {
56 | long startTime = System.currentTimeMillis();
57 |
58 | int i = 0;
59 |
60 | while (i++ < 5000) {
61 | for (String tmpString : uaList) {
62 | UserAgentInfo info = uaParser.parse(tmpString);
63 | //System.out.println("getType: " + info.getType());
64 | }
65 | }
66 | long newTime = System.currentTimeMillis() - startTime;
67 | System.out.println(uaParser.getClass().getSimpleName() + ": " + newTime);
68 |
69 | }
70 |
71 | private static final void checkThreadSafe(final UASparser uaParser, final List uaList,
72 | final List expectedType, final int threadCount, final int runs) {
73 |
74 | List threads = new ArrayList();
75 | for (int i = 0; i < threadCount; i++) {
76 | Runnable runnable = new Runnable() {
77 |
78 | @Override
79 | public void run() {
80 | int r = 0;
81 | while (r++ < runs) {
82 | for (int k = 0; k < uaList.size(); k++) {
83 | String uaString = uaList.get(k);
84 | String expected = expectedType.get(k);
85 | try {
86 | UserAgentInfo info = uaParser.parse(uaString);
87 | if (!info.getType().equals(expected))
88 | throw new IllegalArgumentException("not expected: " + info.getType() + " / " + expected);
89 | } catch (IOException e) {
90 | throw new RuntimeException(e);
91 | }
92 | }
93 | }
94 | System.out.println("finished Thread " + Thread.currentThread().getName());
95 | }
96 | };
97 | threads.add(runnable);
98 | }
99 |
100 | int i = 0;
101 | for (Runnable runnable : threads) {
102 | new Thread(runnable, "Thread " + i++).start();
103 | }
104 | }
105 |
106 |
107 | }
108 |
--------------------------------------------------------------------------------
/src/test/java/cz/mallat/uasparser/TestOldDatabase.java:
--------------------------------------------------------------------------------
1 | package cz.mallat.uasparser;
2 |
3 | import java.io.IOException;
4 | import java.io.InputStream;
5 | import java.util.zip.GZIPInputStream;
6 |
7 | import org.junit.Before;
8 | import org.junit.Test;
9 |
10 | /**
11 | * Test against a copy of the database without device info
12 | *
13 | * @author chetan
14 | *
15 | */
16 | public class TestOldDatabase extends TestParsers {
17 |
18 | @Before
19 | public void disableDeviceTests() {
20 | this.testDeviceInfo = false;
21 | }
22 |
23 | @Override
24 | protected InputStream getDataInputStream() {
25 | try {
26 | return new GZIPInputStream(this.getClass().getClassLoader().getResourceAsStream("uas-nodevice.txt.gz"));
27 | } catch (IOException e) {
28 | }
29 | return null;
30 | }
31 |
32 | @Override
33 | @Test
34 | public void runOnlineUAParser() throws IOException {
35 | // disable
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/src/test/java/cz/mallat/uasparser/TestOnlineUpdater.java:
--------------------------------------------------------------------------------
1 | package cz.mallat.uasparser;
2 |
3 | import static org.junit.Assert.*;
4 |
5 | import java.io.File;
6 | import java.io.IOException;
7 | import java.util.concurrent.TimeUnit;
8 |
9 | import org.junit.Test;
10 |
11 |
12 | public class TestOnlineUpdater {
13 |
14 | @Test
15 | public void testUpdate() throws InterruptedException, IOException {
16 |
17 | File tmpDir = File.createTempFile("uas", ".test");
18 | tmpDir.delete();
19 | tmpDir.mkdirs();
20 | // tmpDir.deleteOnExit();
21 |
22 | try {
23 |
24 | UASparser parser = new UASparser();
25 | assertNull(parser.browserMap);
26 |
27 | OnlineUpdater updater = new OnlineUpdater(parser, tmpDir.toString(), 1, TimeUnit.DAYS);
28 | assertNotNull(parser.browserMap);
29 | assertTrue(updater.isAlive());
30 | updater.update(); // force immediate update
31 |
32 | TestParsers testParsers = new TestParsers();
33 | testParsers.runUAParser();
34 |
35 | assert(new File(tmpDir, OnlineUpdater.CACHE_FILENAME).exists());
36 | assert(new File(tmpDir, OnlineUpdater.PROPERTIES_FILENAME).exists());
37 |
38 | parser = new UASparser();
39 | assertNull(parser.browserMap);
40 | parser.loadDataFromFile(new File(tmpDir, OnlineUpdater.CACHE_FILENAME));
41 | assertNotNull(parser.browserMap);
42 |
43 | } finally {
44 | // new File(tmpDir, OnlineUpdater.CACHE_FILENAME).delete();
45 | // new File(tmpDir, OnlineUpdater.PROPERTIES_FILENAME).delete();
46 | }
47 |
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/src/test/java/cz/mallat/uasparser/TestParsers.java:
--------------------------------------------------------------------------------
1 | package cz.mallat.uasparser;
2 |
3 | import static org.junit.Assert.*;
4 |
5 | import java.io.IOException;
6 | import java.io.InputStream;
7 |
8 | import org.junit.Test;
9 |
10 | /**
11 | * Test the various parser implementations
12 | *
13 | * @author chetan
14 | *
15 | */
16 | public class TestParsers {
17 |
18 | protected boolean testDeviceInfo = true;
19 |
20 | @Test
21 | public void runUAParser() throws IOException {
22 | UASparser p = new UASparser(getDataInputStream());
23 | testUserAgents(p);
24 | }
25 |
26 | @Test
27 | public void runOnlineUAParser() throws IOException {
28 | UASparser p = new OnlineUpdateUASparser();
29 | testUserAgents(p);
30 | }
31 |
32 | @Test
33 | public void runCachedOnlineUAParser() throws IOException {
34 | UASparser p = new CachingOnlineUpdateUASparser();
35 | testUserAgents(p);
36 | }
37 |
38 | @Test
39 | public void testSingleThreadedParser() throws IOException {
40 | UASparser p = new SingleThreadedUASparser(getDataInputStream());
41 | testUserAgents(p);
42 | }
43 |
44 | @Test
45 | public void testMultithreadedParser() throws IOException {
46 | UASparser p = new MultithreadedUASparser(getDataInputStream());
47 | testUserAgents(p);
48 | }
49 |
50 | /**
51 | * Tests for various device types
52 | *
53 | * @throws IOException
54 | * @throws InterruptedException
55 | */
56 | @Test
57 | public void testDeviceUA() throws IOException, InterruptedException {
58 |
59 | if (!this.testDeviceInfo) {
60 | return;
61 | }
62 |
63 | UASparser p = new UASparser(getDataInputStream());
64 |
65 | UserAgentInfo info = p.parse("Mozilla/5.0 (Linux; U; Android 4.0.4; en-au; GT-N7000 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30 Maxthon/4.1.1.2000");
66 | assertEquals("Smartphone", info.getDeviceType());
67 |
68 | info = p.parse("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.116 Safari/537.36 Mozilla/4.0 (compatible; MSIE 5.0; Windows NT;)");
69 | assertEquals("Personal computer", info.getDeviceType());
70 |
71 | info = p.parse("Mozilla/5.0 (Linux; U; Android 4.0.3; ko-kr; LG-L160L Build/IML74K) AppleWebkit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30");
72 | assertEquals("Smartphone", info.getDeviceType());
73 |
74 | info = p.parse("Mozilla/5.0 (compatible; 008/0.83; http://www.80legs.com/spider.html;) Gecko/2008032620");
75 | assertEquals("Other", info.getDeviceType());
76 | }
77 |
78 | /**
79 | * Get database file to test against as an {@link InputStream}
80 | * @return
81 | */
82 | protected InputStream getDataInputStream() {
83 | return OnlineUpdater.getVendoredInputStream();
84 | }
85 |
86 | private void testUserAgents(UASparser parser) throws IOException {
87 | testRobotAgents(parser);
88 | testBrowserAgent(parser);
89 | testEmailAgent(parser);
90 | testTabletAgent(parser);
91 | testSmartphoneAgent(parser);
92 | }
93 |
94 | private void testRobotAgents(UASparser parser) throws IOException {
95 | UserAgentInfo uai = parser.parse("Mozilla/5.0 (compatible; 008/0.83; http://www.80legs.com/spider.html;) Gecko/2008032620");
96 | assertTrue(uai.isRobot());
97 | if (this.testDeviceInfo) {
98 | assertEquals("Datafiniti, LLC.", uai.getUaCompany());
99 | } else {
100 | // when using the 'old db', this may be either of the two strings..
101 | // on a normal run/test, it will be Computational, but the caching test will result in Datafiniti..
102 | assertTrue(uai.getUaCompany().equals("Computational Crawling, LP") || uai.getUaCompany().equals("Datafiniti, LLC."));
103 | }
104 |
105 | uai = parser.parse("Googlebot/2.1 (+http://www.googlebot.com/bot.html)");
106 | assertFalse(uai.isRobot()); // not currently detected
107 |
108 | uai = parser.parse("Pingdom.com_bot_version_1.4_(http://www.pingdom.com/)");
109 | assertTrue(uai.isRobot());
110 | }
111 |
112 | private void testBrowserAgent(UASparser parser) throws IOException {
113 | UserAgentInfo uai = parser.parse("Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.12) Gecko/2009070611 Firefox/3.0.12");
114 | assertNotNull(uai);
115 | assertEquals("Browser", uai.getType());
116 | assertEquals("Firefox 3.0.12", uai.getUaName());
117 | assertEquals("Firefox", uai.getUaFamily());
118 | assertEquals("Mozilla Foundation", uai.getUaCompany());
119 | assertEquals("Windows XP", uai.getOsName());
120 | assertEquals("Windows", uai.getOsFamily());
121 | assertEquals("Microsoft Corporation.", uai.getOsCompany());
122 | }
123 |
124 | private void testEmailAgent(UASparser parser) throws IOException {
125 | UserAgentInfo uai = parser.parse("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_5_8) AppleWebKit/534.50.2 (KHTML, like Gecko)");
126 | assertNotNull(uai);
127 | assertEquals("Email client", uai.getType());
128 | assertEquals("Apple Mail", uai.getUaName());
129 | assertEquals("Apple Mail", uai.getUaFamily());
130 | assertEquals("Apple Inc.", uai.getUaCompany());
131 | assertEquals("OS X 10.5 Leopard", uai.getOsName());
132 | assertEquals("OS X", uai.getOsFamily());
133 | assertEquals("Apple Computer, Inc.", uai.getOsCompany());
134 | }
135 |
136 | private void testTabletAgent(UASparser parser) throws IOException {
137 | UserAgentInfo uai = parser.parse("Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/6.0 Mobile/11A465 Safari/9537.53");
138 | assertNotNull(uai);
139 | assertEquals("Mobile Browser", uai.getType());
140 | assertEquals("Mobile Safari 6.0", uai.getUaName());
141 | assertEquals("Mobile Safari", uai.getUaFamily());
142 | assertEquals("Apple Inc.", uai.getUaCompany());
143 | assertEquals("iOS 6", uai.getOsName());
144 | assertEquals("iOS", uai.getOsFamily());
145 | assertEquals("Apple Inc.", uai.getOsCompany());
146 |
147 | if (!testDeviceInfo) {
148 | return;
149 | }
150 | assertTrue(uai.hasDeviceInfo());
151 | assertEquals("Tablet", uai.getDeviceType());
152 | assertEquals("tablet.png", uai.getDeviceIcon());
153 | assertEquals("http://user-agent-string.info/list-of-ua/device-detail?device=Tablet", uai.getDeviceInfoUrl());
154 | }
155 |
156 | private void testSmartphoneAgent(UASparser parser) throws IOException {
157 | UserAgentInfo uai = parser.parse("Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/546.10 (KHTML, like Gecko) Version/6.0 Mobile/7E18WD Safari/8536.25");
158 | assertNotNull(uai);
159 | assertEquals("Mobile Browser", uai.getType());
160 | assertEquals("Mobile Safari 6.0", uai.getUaName());
161 | assertEquals("Mobile Safari", uai.getUaFamily());
162 | assertEquals("Apple Inc.", uai.getUaCompany());
163 | assertEquals("iOS 6", uai.getOsName());
164 | assertEquals("iOS", uai.getOsFamily());
165 | assertEquals("Apple Inc.", uai.getOsCompany());
166 |
167 | // if (!testDeviceInfo) {
168 | // return;
169 | // }
170 | // assertTrue(uai.hasDeviceInfo());
171 | // assertEquals("Smartphone", uai.getDeviceType());
172 | // assertEquals("phone.png", uai.getDeviceIcon());
173 | // assertEquals("http://user-agent-string.info/list-of-ua/device-detail?device=Smartphone", uai.getDeviceInfoUrl());
174 | }
175 |
176 | @Test
177 | public void testArrayIndexBug() throws IOException {
178 | // should not throw exception
179 | UASparser p = new UASparser(getDataInputStream());
180 | UserAgentInfo uai = p.parse("Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; MRA 4.7 (build 01670); .NET CLR 1.1.4322)");
181 | }
182 | }
183 |
--------------------------------------------------------------------------------
/src/test/java/cz/mallat/uasparser/TestSuite.java:
--------------------------------------------------------------------------------
1 | package cz.mallat.uasparser;
2 |
3 | import org.junit.runner.RunWith;
4 | import org.junit.runners.Suite;
5 | import org.junit.runners.Suite.SuiteClasses;
6 |
7 | @RunWith(Suite.class)
8 | @SuiteClasses({ TestOnlineUpdater.class, TestParsers.class, TestOldDatabase.class })
9 | public class TestSuite {
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/src/test/resources/uas-nodevice.txt.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chetan/UASparser/c92ceffbfcbd1bb18d75e320bc45149eaaacd89e/src/test/resources/uas-nodevice.txt.gz
--------------------------------------------------------------------------------