public static UserAgent parseUserAgent()

in velocity-tools-view/src/main/java/org/apache/velocity/tools/view/UAParser.java [264:613]


    public static UserAgent parseUserAgent(String userAgentString, Logger log)
    {
        UserAgent ua = null;
        try
        {
            ua = new UserAgent();

            Matcher matcher = versionPattern.matcher(userAgentString);
            String merge = null;
            EntityType mergeTarget = null;
            boolean maybeBrowser = true;
            boolean maybeOS = true;
            boolean maybeRobot = false;
            boolean forcedBrowser = false;
            boolean forcedOS = false;

            while (matcher.find())
            {
                String entity = matcher.group(1);
                String separator = matcher.group(2);
                String major = matcher.group(3);
                String minor = matcher.group(4);
                char next = userAgentString.length() == matcher.end(1) ? ';' : userAgentString.charAt(matcher.end(1));
                if (entity != null)
                {
                    if (merge != null)
                    {
                        String merged = merge + " " + entity;
                        if (mergeTarget == null)
                        {
                            entity = merged;
                        }
                        else
                        {
                            Pair<EntityType,DeviceType> pair = entityMap.get(merged.toLowerCase());
                            EntityType mergedType = pair == null ? null : pair.getLeft();
                            if (mergedType != null && (
                                    mergeTarget == mergedType ||
                                            mergeTarget == EntityType.BROWSER && (mergedType == EntityType.MAYBE_BROWSER || mergedType == EntityType.FORCE_BROWSER) ||
                                            mergeTarget == EntityType.OS && (mergedType == EntityType.MAYBE_OS || mergedType == EntityType.FORCE_OS)
                            ))
                            {
                                entity = merged;
                            }
                            else
                            {
                                /* It means the merge failed, so revert it */
                                switch (mergeTarget)
                                {
                                    case BROWSER:
                                        ua.setBrowser(merge, null, null);
                                        break;
                                    case OS:
                                        ua.setOperatingSystem(merge, null, null);
                                        break;
                                    default:
                                        throw new VelocityException("BrowserTool: unhandled case!");
                                }
                            }
                        }
                        merge = null;
                        mergeTarget = null;
                    }
                    Pair<EntityType, DeviceType> identity = entityMap.get(entity.toLowerCase());
                    EntityType entityType = null;
                    DeviceType deviceType = null;
                    if (identity == null)
                    {
                        /* try again with major version appended */
                        String alternateEntity = entity + separator + major;
                        identity = entityMap.get((entity + separator + major).toLowerCase());
                        if (identity != null)
                        {
                            entity = alternateEntity;
                        }
                    }
                    if (identity != null)
                    {
                        entityType = identity.getLeft();
                        deviceType = identity.getRight();
                        DeviceType previousDeviceType = ua.getDeviceType();
                        /* only overwrite device types of lower precedence */
                        if (deviceType != null && (previousDeviceType == null || deviceType.compareTo(previousDeviceType) > 0))
                        {
                            ua.setDeviceType(deviceType); // may be overwritten by 'robot' device type
                        }
                    }
                    if (entityType != null)
                    {
                        switch (entityType)
                        {
                            case BROWSER:
                            {
                                if (ua.getBrowser() == null || !forcedBrowser)
                                {
                                    ua.setBrowser(entity, major, minor);
                                    maybeBrowser = false;
                                }
                                break;
                            }
                            case BROWSER_OS:
                            {
                                ua.setBrowser(entity, major, minor);
                                maybeBrowser = false;
                                ua.setOperatingSystem(entity, major, minor);
                                maybeOS = false;
                                break;
                            }
                            case ENGINE:
                            {
                                if (!"KHTML".equals(entity) || major != null || ua.getRenderingEngine() == null)
                                {
                                    ua.setRenderingEngine(entity, major, minor);
                                }
                                break;
                            }
                            case FORCE_BROWSER:
                            {
                                if (!forcedBrowser)
                                {
                                    ua.setBrowser(entity, major, minor);
                                    maybeBrowser = false;
                                    forcedBrowser = true;
                                }
                                break;
                            }
                            case FORCE_OS:
                            {
                                if (!forcedOS)
                                {
                                    ua.setOperatingSystem(entity, major, minor);
                                    maybeOS = false;
                                    forcedOS = true;
                                }
                                break;
                            }
                            case IGNORE:
                            {
                                break;
                            }
                            case MAYBE_BROWSER:
                            {
                                if (maybeBrowser)
                                {
                                    if ("rv".equals(entity))
                                    {
                                        if (ua.getBrowser() != null && ua.getBrowser().getName().equals("Mozilla"))
                                        {
                                            entity = "Mozilla";
                                        } else
                                        {
                                            entity = null;
                                        }
                                    } else if ("Version".equals(entity))
                                    {
                                        if (ua.getBrowser() != null && ua.getBrowser().getName().startsWith("Opera"))
                                        {
                                            entity = ua.getBrowser().getName();
                                        } else if (ua.getBrowser() != null && ua.getBrowser().getName().equals("Mozilla"))
                                        {
                                            entity = "Safari";
                                        } else
                                        {
                                            entity = null;
                                        }
                                    } else if ("Safari".equals(entity) && ua.getBrowser() != null && "Safari".equals(ua.getBrowser().getName()))
                                    {
                                        entity = null;
                                    }
                                    if (entity != null)
                                    {
                                        ua.setBrowser(entity, major, minor);
                                    }
                                }
                                break;
                            }
                            case MAYBE_OS:
                            {
                                if (maybeOS)
                                {
                                    ua.setOperatingSystem(entity, major, minor);
                                }
                                break;
                            }
                            case MAYBE_ROBOT:
                            {
                                maybeRobot = true;
                                break;
                            }
                            case MERGE:
                            {
                                if (major == null)
                                {
                                    if (nonMergeSep.indexOf(next) == -1)
                                    {
                                        merge = merge == null ? entity : merge + " " + entity;
                                    } else
                                    {
                                        if ("Mobile".equals(entity) && ua.getOperatingSystem() != null)
                                        {
                                            if (ua.getOperatingSystem().getName().equals("Ubuntu"))
                                            {
                                                ua.setOperatingSystem("Ubuntu Mobile", String.valueOf(ua.getOperatingSystem().getMajorVersion()), String.valueOf(ua.getOperatingSystem().getMinorVersion()));
                                            } else if (ua.getOperatingSystem().getName().equals("Linux"))
                                            {
                                                ua.setOperatingSystem("Android", null, null);
                                            }
                                        }
                                    }
                                }
                                break;
                            }
                            case MERGE_OR_BROWSER:
                            {
                                if (!forcedBrowser)
                                {
                                    if (major != null || nonMergeSep.indexOf(next) != -1)
                                    {
                                        ua.setBrowser(entity, major, minor);
                                    } else
                                    {
                                        merge = entity;
                                        mergeTarget = EntityType.BROWSER;
                                    }
                                }
                                break;
                            }
                            case MERGE_OR_OS:
                            {
                                if (!forcedOS)
                                {
                                    if (major != null || nonMergeSep.indexOf(next) != -1)
                                    {
                                        ua.setOperatingSystem(entity, major, minor);
                                    } else
                                    {
                                        merge = entity;
                                        mergeTarget = EntityType.OS;
                                    }
                                }
                                break;
                            }
                            case OS:
                            {
                                if (ua.getOperatingSystem() == null || !forcedOS)
                                {
                                    ua.setOperatingSystem(entity, major, minor);
                                    maybeOS = false;
                                }
                                break;
                            }
                            case ROBOT:
                            {
                                ua.setDeviceType(DeviceType.ROBOT);
                                break;
                            }
                            default:
                            {
                                throw new VelocityException("BrowserTool: unhandled case: " + entityType);
                            }
                        }
                    }
                    else
                    {
                        if (entity.startsWith("Linux") && !forcedOS)
                        {
                            ua.setOperatingSystem("Linux", null, null);
                        }
                        else if (isRobotToken(entity))
                        {
                            ua.setDeviceType(DeviceType.ROBOT);
                        }
                        else if (entity.startsWith("MID") && !entity.startsWith("MIDP") && (ua.getDeviceType() == null || DeviceType.TABLET.compareTo(ua.getDeviceType()) > 0 ))
                        {
                            ua.setDeviceType(DeviceType.TABLET);
                        }
                        else if (entity.startsWith("CoolPad") && (ua.getDeviceType() == null || DeviceType.MOBILE.compareTo(ua.getDeviceType()) > 0 ))
                        {
                            ua.setDeviceType(DeviceType.MOBILE);
                        }
                        else if (entity.startsWith("LG-") && (ua.getDeviceType() == null || DeviceType.MOBILE.compareTo(ua.getDeviceType()) > 0 ))
                        {
                            ua.setDeviceType(DeviceType.MOBILE);
                        }
                        else if (entity.startsWith("SonyEricsson"))
                        {
                            ua.setDeviceType(DeviceType.MOBILE);
                        }
                    }
                }
            }
            if (ua.getOperatingSystem() != null && "Windows".equals(ua.getOperatingSystem().getName()) && (ua.getOperatingSystem().getMajorVersion() == 98 || ua.getOperatingSystem().getMajorVersion() == 2000))
            {
                if (ua.getOperatingSystem().getMajorVersion() == 98)
                {
                    ua.setOperatingSystem("Windows 98", "4", "90");
                }
                else if (ua.getOperatingSystem().getMajorVersion() == 2000)
                {
                    ua.setOperatingSystem("Windows 2000", "5", "0");
                }
            }
            if (ua.getBrowser() == null)
            {
                if (ua.getDeviceType() == DeviceType.ROBOT || maybeRobot)
                {
                    ua.setBrowser("robot", "0", "0");
                    ua.setDeviceType(DeviceType.ROBOT);
                }
                else if (ua.getOperatingSystem() != null && ua.getOperatingSystem().getName().equals("Symbian"))
                {
                    ua.setBrowser("Nokia Browser", String.valueOf(ua.getOperatingSystem().getMajorVersion()), String.valueOf(ua.getOperatingSystem().getMinorVersion()));
                }
                else
                {
                    ua.setBrowser("unknown", "0", "0");
                }
            }
            if (ua.getOperatingSystem() == null)
            {
                if (ua.getDeviceType() == DeviceType.ROBOT || maybeRobot)
                {
                    ua.setOperatingSystem("robot", "0", "0");
                    ua.setDeviceType(DeviceType.ROBOT);
                }
                else
                {
                    ua.setOperatingSystem("unknown", "0", "0");
                }
            }
            if (ua.getDeviceType() == null)
            {
                if (ua.getOperatingSystem() != null && "Android".equals(ua.getOperatingSystem().getName()))
                {
                    ua.setDeviceType(DeviceType.MOBILE);
                }
                else
                {
                    /* make Desktop the default device */
                    ua.setDeviceType(DeviceType.DESKTOP);
                }
            }
        }
        catch (Exception e)
        {
            log.error("Could not parse browser for User-Agent: {}", userAgentString, e);
            ua = null;
        }
        return ua;
    }