|
- * | Copyright @ 2013-2022 Buession.com Inc. |
+ * | Copyright @ 2013-2023 Buession.com Inc. |
* +------------------------------------------------------------------------------------------------+
*/
package com.buession.dao;
@@ -78,7 +78,7 @@ public abstract class AbstractMongoDBDao extends AbstractDao
impleme
@Resource
private List slaveMongoTemplates;
- private final static Logger logger = LoggerFactory.getLogger(AbstractMongoDBDao.class);
+ private final Logger logger = LoggerFactory.getLogger(getClass());
/**
* 返回 master MongoTemplate
diff --git a/buession-dao/src/main/java/com/buession/dao/AbstractMyBatisDao.java b/buession-dao/src/main/java/com/buession/dao/AbstractMyBatisDao.java
index e4a047df8..a97152cf1 100755
--- a/buession-dao/src/main/java/com/buession/dao/AbstractMyBatisDao.java
+++ b/buession-dao/src/main/java/com/buession/dao/AbstractMyBatisDao.java
@@ -21,7 +21,7 @@
* +------------------------------------------------------------------------------------------------+
* | License: http://www.apache.org/licenses/LICENSE-2.0.txt |
* | Author: Yong.Teng |
- * | Copyright @ 2013-2022 Buession.com Inc. |
+ * | Copyright @ 2013-2023 Buession.com Inc. |
* +------------------------------------------------------------------------------------------------+
*/
package com.buession.dao;
@@ -74,7 +74,7 @@ public abstract class AbstractMyBatisDao extends AbstractDao
impleme
@Resource
protected List slaveSqlSessionTemplates;
- private final static Logger logger = LoggerFactory.getLogger(AbstractMyBatisDao.class);
+ private final Logger logger = LoggerFactory.getLogger(getClass());
/**
* 返回 master SqlSessionTemplate
@@ -352,11 +352,8 @@ protected String getStatement(final DML dml){
protected String getStatement(final String dml){
final String statement = getStatement();
- final StringBuilder sb = new StringBuilder(statement.length() + dml.length() + 1);
- sb.append(statement).append('.').append(dml);
-
- return sb.toString();
+ return statement + '.' + dml;
}
}
\ No newline at end of file
diff --git a/buession-geoip/pom.xml b/buession-geoip/pom.xml
index ec1d5d20f..71ef28768 100644
--- a/buession-geoip/pom.xml
+++ b/buession-geoip/pom.xml
@@ -7,10 +7,10 @@
com.buession
buession-parent
../buession-parent
- 2.2.0
+ 2.2.1
buession-geoip
- https://github.com/buession/buessionframework
+ http://www.buession.com/
Buession Framework GeoIP, support maxmind
jar
diff --git a/buession-git/pom.xml b/buession-git/pom.xml
index ca4b9f6f7..0cf66d35b 100644
--- a/buession-git/pom.xml
+++ b/buession-git/pom.xml
@@ -7,10 +7,10 @@
com.buession
buession-parent
../buession-parent
- 2.2.0
+ 2.2.1
buession-git
- https://github.com/buession/buessionframework
+ http://www.buession.com/
Buession Framework Git Library
jar
diff --git a/buession-httpclient/pom.xml b/buession-httpclient/pom.xml
index 960bd5642..522f5adab 100644
--- a/buession-httpclient/pom.xml
+++ b/buession-httpclient/pom.xml
@@ -7,10 +7,10 @@
com.buession
buession-parent
../buession-parent
- 2.2.0
+ 2.2.1
buession-httpclient
- https://github.com/buession/buessionframework
+ http://www.buession.com/
Buession Framework Http Client
jar
diff --git a/buession-io/pom.xml b/buession-io/pom.xml
index 41acac8da..2762e0c42 100644
--- a/buession-io/pom.xml
+++ b/buession-io/pom.xml
@@ -7,10 +7,10 @@
com.buession
buession-parent
../buession-parent
- 2.2.0
+ 2.2.1
buession-io
- https://github.com/buession/buessionframework
+ http://www.buession.com/
Buession Framework IO Package
jar
diff --git a/buession-io/src/main/java/com/buession/io/file/File.java b/buession-io/src/main/java/com/buession/io/file/File.java
index 120b82dff..335ddd63a 100644
--- a/buession-io/src/main/java/com/buession/io/file/File.java
+++ b/buession-io/src/main/java/com/buession/io/file/File.java
@@ -123,12 +123,10 @@ public MimeType getMimeType(){
*
* @return 文件内容
*
- * @throws FileNotFoundException
- * 当文件不存在
* @throws IOException
* IO 异常
*/
- public byte[] read() throws FileNotFoundException, IOException{
+ public byte[] read() throws IOException{
int size = 4096;
BufferedInputStream bis = new FileBufferedInputStream(this);
byte[] tempChars = new byte[size];
diff --git a/buession-jdbc/pom.xml b/buession-jdbc/pom.xml
index 23b623de0..99e6bb35b 100644
--- a/buession-jdbc/pom.xml
+++ b/buession-jdbc/pom.xml
@@ -7,10 +7,10 @@
com.buession
buession-parent
../buession-parent
- 2.2.0
+ 2.2.1
buession-jdbc
- https://github.com/buession/buessionframework
+ http://www.buession.com/
Buession Framework JDBC
jar
diff --git a/buession-json/pom.xml b/buession-json/pom.xml
index b33e2b6a1..54dbb783e 100644
--- a/buession-json/pom.xml
+++ b/buession-json/pom.xml
@@ -7,10 +7,10 @@
com.buession
buession-parent
../buession-parent
- 2.2.0
+ 2.2.1
buession-json
- https://github.com/buession/buessionframework
+ http://www.buession.com/
Buession Framework the extension for jackson
jar
diff --git a/buession-lang/pom.xml b/buession-lang/pom.xml
index 4f6c91baf..d3f9a21f5 100644
--- a/buession-lang/pom.xml
+++ b/buession-lang/pom.xml
@@ -7,10 +7,10 @@
com.buession
buession-parent
../buession-parent
- 2.2.0
+ 2.2.1
buession-lang
- https://github.com/buession/buessionframework
+ http://www.buession.com/
Buession Framework Lang, a package of Java utility classes for the classes that are in java.lang's hierarchy, or are considered to be so standard as to justify existence in java.lang.
jar
diff --git a/buession-net/pom.xml b/buession-net/pom.xml
index 7d67ce3db..c15a09e53 100644
--- a/buession-net/pom.xml
+++ b/buession-net/pom.xml
@@ -7,10 +7,10 @@
com.buession
buession-parent
../buession-parent
- 2.2.0
+ 2.2.1
buession-net
- https://github.com/buession/buessionframework
+ http://www.buession.com/
Buession Framework Network
jar
diff --git a/buession-parent/pom.xml b/buession-parent/pom.xml
index 6b4bda8d7..b7ee686e8 100644
--- a/buession-parent/pom.xml
+++ b/buession-parent/pom.xml
@@ -7,13 +7,13 @@
com.buession
parent
- 2.2.0
+ 2.2.1
com.buession
buession-parent
- https://github.com/buession/buessionframework
+ http://www.buession.com/
Buession Framework Parent
- 2.2.0
+ 2.2.1
pom
diff --git a/buession-redis/pom.xml b/buession-redis/pom.xml
index 249bd4ff4..f810824e3 100644
--- a/buession-redis/pom.xml
+++ b/buession-redis/pom.xml
@@ -7,10 +7,10 @@
com.buession
buession-parent
../buession-parent
- 2.2.0
+ 2.2.1
buession-redis
- https://github.com/buession/buessionframework
+ http://www.buession.com/
Buession Framework for Redis Client
jar
diff --git a/buession-session/pom.xml b/buession-session/pom.xml
index eea9df534..a419b43a8 100644
--- a/buession-session/pom.xml
+++ b/buession-session/pom.xml
@@ -7,10 +7,10 @@
com.buession
buession-parent
../buession-parent
- 2.2.0
+ 2.2.1
buession-session
- https://github.com/buession/buessionframework
+ http://www.buession.com/
Buession Framework Web Session
jar
diff --git a/buession-thesaurus/pom.xml b/buession-thesaurus/pom.xml
index fab967a25..1f89896f7 100644
--- a/buession-thesaurus/pom.xml
+++ b/buession-thesaurus/pom.xml
@@ -7,10 +7,10 @@
com.buession
buession-parent
../buession-parent
- 2.2.0
+ 2.2.1
buession-thesaurus
- https://github.com/buession/buessionframework
+ http://www.buession.com/
Buession Framework Word Thesaurus Parse Tools.
jar
diff --git a/buession-velocity/pom.xml b/buession-velocity/pom.xml
index 15b90d6d2..aedff5e76 100644
--- a/buession-velocity/pom.xml
+++ b/buession-velocity/pom.xml
@@ -7,10 +7,10 @@
com.buession
buession-parent
../buession-parent
- 2.2.0
+ 2.2.1
buession-velocity
- https://github.com/buession/buessionframework
+ http://www.buession.com/
Buession Framework For Velocity Template Engine
jar
diff --git a/buession-web/pom.xml b/buession-web/pom.xml
index 5793d810e..fd4d2c513 100644
--- a/buession-web/pom.xml
+++ b/buession-web/pom.xml
@@ -7,10 +7,10 @@
com.buession
buession-parent
../buession-parent
- 2.2.0
+ 2.2.1
buession-web
- https://github.com/buession/buessionframework
+ http://www.buession.com/
Buession Web
jar
diff --git a/buession-web/src/main/java/com/buession/web/servlet/AbstractHandlerExceptionResolver.java b/buession-web/src/main/java/com/buession/web/servlet/AbstractHandlerExceptionResolver.java
index 10c32ab5f..f73969850 100644
--- a/buession-web/src/main/java/com/buession/web/servlet/AbstractHandlerExceptionResolver.java
+++ b/buession-web/src/main/java/com/buession/web/servlet/AbstractHandlerExceptionResolver.java
@@ -19,7 +19,7 @@
* +-------------------------------------------------------------------------------------------------------+
* | License: http://www.apache.org/licenses/LICENSE-2.0.txt |
* | Author: Yong.Teng |
- * | Copyright @ 2013-2022 Buession.com Inc. |
+ * | Copyright @ 2013-2023 Buession.com Inc. |
* +-------------------------------------------------------------------------------------------------------+
*/
package com.buession.web.servlet;
@@ -65,8 +65,14 @@ public abstract class AbstractHandlerExceptionResolver
extends org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver
implements ServletExceptionHandlerResolver {
+ /**
+ * 异常属性名称
+ */
private String exceptionAttribute = DEFAULT_EXCEPTION_ATTRIBUTE;
+ /**
+ * 默认错误视图
+ */
private String defaultErrorView = DEFAULT_ERROR_VIEW;
private String cacheControl = CACHE_CONTROL;
@@ -75,9 +81,55 @@ public abstract class AbstractHandlerExceptionResolver
private Map exceptionViews;
- private final static Logger logger = LoggerFactory.getLogger(AbstractHandlerExceptionResolver.class);
+ protected final Logger logger = LoggerFactory.getLogger(getClass());
+
+ protected final static Logger pageNotFoundLogger = LoggerFactory.getLogger(PAGE_NOT_FOUND_LOG_CATEGORY);
+
+ /**
+ * 返回异常属性名称
+ *
+ * @return 异常属性名称
+ *
+ * @since 2.2.1
+ */
+ public String getExceptionAttribute(){
+ return exceptionAttribute;
+ }
+
+ /**
+ * 设置异常属性名称
+ *
+ * @param exceptionAttribute
+ * 异常属性名称
+ *
+ * @since 2.2.1
+ */
+ public void setExceptionAttribute(String exceptionAttribute){
+ this.exceptionAttribute = exceptionAttribute;
+ }
+
+ /**
+ * 返回默认错误视图
+ *
+ * @return 默认错误视图
+ *
+ * @since 2.2.1
+ */
+ public String getDefaultErrorView(){
+ return defaultErrorView;
+ }
- private final static Logger pageNotFoundLogger = LoggerFactory.getLogger(PAGE_NOT_FOUND_LOG_CATEGORY);
+ /**
+ * 设置默认错误视图
+ *
+ * @param defaultErrorView
+ * 默认错误视图
+ *
+ * @since 2.2.1
+ */
+ public void setDefaultErrorView(String defaultErrorView){
+ this.defaultErrorView = defaultErrorView;
+ }
public String getCacheControl(){
return cacheControl;
@@ -108,6 +160,9 @@ public void setExceptionViews(Map exceptionViews){
@Override
protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response,
@Nullable Object handler, Exception ex){
+ if(logger.isErrorEnabled()){
+ logger.error("Resolve Exception: {}", ex.getMessage(), ex);
+ }
ModelAndView mv = doSpecialResolveException(request, response, handler, ex);
if(mv != null){
@@ -203,7 +258,7 @@ protected ModelAndView handleMethodArgumentNotValidException(final HttpServletRe
final MethodArgumentNotValidException ex)
throws IOException{
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
- return doResolve(request, response, ex);
+ return doResolve(request, response, handler, ex);
}
/**
@@ -230,7 +285,7 @@ protected ModelAndView handleMissingServletRequestPartException(final HttpServle
final MissingServletRequestPartException ex)
throws IOException{
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
- return doResolve(request, response, ex);
+ return doResolve(request, response, handler, ex);
}
/**
@@ -255,7 +310,7 @@ protected ModelAndView handleBindException(final HttpServletRequest request, fin
@Nullable final Object handler, final BindException ex)
throws IOException{
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
- return doResolve(request, response, ex);
+ return doResolve(request, response, handler, ex);
}
/**
@@ -282,7 +337,7 @@ protected ModelAndView handleMissingServletRequestParameterException(final HttpS
final MissingServletRequestParameterException ex)
throws IOException{
response.sendError(HttpServletResponse.SC_BAD_REQUEST, ex.getMessage());
- return doResolve(request, response, ex);
+ return doResolve(request, response, handler, ex);
}
/**
@@ -309,7 +364,7 @@ protected ModelAndView handleServletRequestBindingException(final HttpServletReq
final ServletRequestBindingException ex)
throws IOException{
response.sendError(HttpServletResponse.SC_BAD_REQUEST, ex.getMessage());
- return doResolve(request, response, ex);
+ return doResolve(request, response, handler, ex);
}
/**
@@ -335,7 +390,7 @@ protected ModelAndView handleTypeMismatchException(final HttpServletRequest requ
@Nullable final Object handler, final TypeMismatchException ex)
throws IOException{
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
- return doResolve(request, response, ex);
+ return doResolve(request, response, handler, ex);
}
/**
@@ -362,7 +417,7 @@ protected ModelAndView handleHttpMessageNotReadableException(final HttpServletRe
final HttpMessageNotReadableException ex)
throws IOException{
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
- return doResolve(request, response, ex);
+ return doResolve(request, response, handler, ex);
}
/**
@@ -389,7 +444,7 @@ protected ModelAndView handleNoHandlerFoundException(final HttpServletRequest re
final NoHandlerFoundException ex) throws IOException{
pageNotFoundLogger.warn(ex.getMessage());
response.sendError(HttpServletResponse.SC_NOT_FOUND);
- return doResolve(request, response, ex);
+ return doResolve(request, response, handler, ex);
}
/**
@@ -422,7 +477,7 @@ protected ModelAndView handleHttpRequestMethodNotSupportedException(final HttpSe
response.setHeader("Allow", Arrays.toString(supportedMethods, ", "));
}
- return doResolve(request, response, ex);
+ return doResolve(request, response, handler, ex);
}
/**
@@ -449,7 +504,7 @@ protected ModelAndView handleHttpMediaTypeNotAcceptableException(final HttpServl
final HttpMediaTypeNotAcceptableException ex)
throws IOException{
response.sendError(HttpServletResponse.SC_NOT_ACCEPTABLE);
- return doResolve(request, response, ex);
+ return doResolve(request, response, handler, ex);
}
/**
@@ -482,7 +537,7 @@ protected ModelAndView handleHttpMediaTypeNotSupportedException(final HttpServle
response.setHeader("Accept", MediaType.toString(mediaTypes));
}
- return doResolve(request, response, ex);
+ return doResolve(request, response, handler, ex);
}
/**
@@ -508,7 +563,7 @@ protected ModelAndView handleMissingPathVariableException(final HttpServletReque
@Nullable final Object handler,
final MissingPathVariableException ex) throws IOException{
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, ex.getMessage());
- return doResolve(request, response, ex);
+ return doResolve(request, response, handler, ex);
}
/**
@@ -535,7 +590,7 @@ protected ModelAndView handleConversionNotSupportedException(final HttpServletRe
final ConversionNotSupportedException ex)
throws IOException{
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
- return doResolve(request, response, ex);
+ return doResolve(request, response, handler, ex);
}
/**
@@ -562,7 +617,7 @@ protected ModelAndView handleHttpMessageNotWritableException(final HttpServletRe
final HttpMessageNotWritableException ex)
throws IOException{
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
- return doResolve(request, response, ex);
+ return doResolve(request, response, handler, ex);
}
/**
@@ -593,7 +648,7 @@ protected ModelAndView handleAsyncRequestTimeoutException(final HttpServletReque
logger.warn("Async request timed out");
}
- return doResolve(request, response, ex);
+ return doResolve(request, response, handler, ex);
}
protected boolean acceptTextHtml(final HttpServletRequest request){
@@ -611,8 +666,14 @@ protected ModelAndView createModelAndView(final HttpServletRequest request, fina
new ModelAndView(determineViewName(request, response, ex, httpStatus));
}
+ @Deprecated
protected ModelAndView doResolve(final HttpServletRequest request, final HttpServletResponse response,
final Exception ex){
+ return doResolve(request, response, null, ex);
+ }
+
+ protected ModelAndView doResolve(final HttpServletRequest request, final HttpServletResponse response,
+ @Nullable final Object handler, final Exception ex){
request.setAttribute("javax.servlet.error.exception", ex);
HttpStatus httpStatus = HttpStatus.resolve(response.getStatus());
@@ -624,7 +685,7 @@ protected ModelAndView doResolve(final HttpServletRequest request, final HttpSer
mv.addObject("message", httpStatus.getReasonPhrase());
mv.addObject("status", httpStatus);
mv.addObject("timestamp", new Date());
- mv.addObject(exceptionAttribute, ex);
+ mv.addObject(getExceptionAttribute(), ex);
applyStatusCodeIfPossible(request, response, httpStatus);
@@ -647,13 +708,13 @@ protected String determineViewName(final HttpServletRequest request, final HttpS
viewName = SERIES_VIEWS.get(httpStatus.series());
}
- if(viewName == null && defaultErrorView != null){
+ if(viewName == null && getDefaultErrorView() != null){
if(logger.isDebugEnabled()){
- logger.debug("Resolving to default view '{}' for exception of type [{}]", defaultErrorView,
+ logger.debug("Resolving to default view '{}' for exception of type [{}]", getDefaultErrorView(),
ex.getClass().getName());
}
- viewName = defaultErrorView;
+ viewName = getDefaultErrorView();
}
return viewName;
diff --git a/buession-web/src/main/java/com/buession/web/servlet/ErrorHandler.java b/buession-web/src/main/java/com/buession/web/servlet/ErrorHandler.java
new file mode 100644
index 000000000..5c625f9f1
--- /dev/null
+++ b/buession-web/src/main/java/com/buession/web/servlet/ErrorHandler.java
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ *
+ * =========================================================================================================
+ *
+ * This software consists of voluntary contributions made by many individuals on behalf of the
+ * Apache Software Foundation. For more information on the Apache Software Foundation, please see
+ * .
+ *
+ * +-------------------------------------------------------------------------------------------------------+
+ * | License: http://www.apache.org/licenses/LICENSE-2.0.txt |
+ * | Author: Yong.Teng |
+ * | Copyright @ 2013-2023 Buession.com Inc. |
+ * +-------------------------------------------------------------------------------------------------------+
+ */
+package com.buession.web.servlet;
+
+import com.buession.web.http.Error;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * 异常错误处理器
+ *
+ * @param
+ * 异常
+ *
+ * @author Yong.Teng
+ * @since 2.2.1
+ */
+public interface ErrorHandler {
+
+ Error apply(final HttpServletRequest request, final HttpServletResponse response, final Object handler,
+ final EX ex);
+
+}
diff --git a/buession-web/src/main/java/com/buession/web/utils/useragentutils/Browser.java b/buession-web/src/main/java/com/buession/web/utils/useragentutils/Browser.java
new file mode 100644
index 000000000..f4456e1aa
--- /dev/null
+++ b/buession-web/src/main/java/com/buession/web/utils/useragentutils/Browser.java
@@ -0,0 +1,576 @@
+/*
+ * 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.
+ *
+ * =========================================================================================================
+ *
+ * This software consists of voluntary contributions made by many individuals on behalf of the
+ * Apache Software Foundation. For more information on the Apache Software Foundation, please see
+ * .
+ *
+ * +-------------------------------------------------------------------------------------------------------+
+ * | License: http://www.apache.org/licenses/LICENSE-2.0.txt |
+ * | Author: Yong.Teng |
+ * | Copyright @ 2013-2023 Buession.com Inc. |
+ * +-------------------------------------------------------------------------------------------------------+
+ */
+package com.buession.web.utils.useragentutils;
+
+import com.buession.core.utils.StringUtils;
+import com.buession.web.utils.useragentutils.browsertypefetcher.BrowserTypeFetcher;
+import com.buession.web.utils.useragentutils.browsertypefetcher.ContainsBrowserTypeFetcher;
+import com.buession.web.utils.useragentutils.versionfetcher.MapVersionFetcher;
+import com.buession.web.utils.useragentutils.versionfetcher.PatternVersionFetcher;
+import com.buession.web.utils.useragentutils.versionfetcher.SequentialVersionFetcher;
+import com.buession.web.utils.useragentutils.versionfetcher.VersionFetcher;
+
+/**
+ * 浏览器
+ *
+ * @author Yong.Teng
+ * @since 2.2.1
+ */
+public enum Browser {
+ IE(
+ "Internet Explorer",
+ new String[]{"MSIE", "Trident", "IE "},
+ null,
+ BrowserType.WEB_BROWSER,
+ new BrowserTypeFetcher[]{
+ new ContainsBrowserTypeFetcher("IEMobile", BrowserType.MOBILE_BROWSER)
+ },
+ RenderingEngine.TRIDENT,
+ Manufacturer.MICROSOFT,
+ new VersionMapping[]{
+ new VersionMapping(new String[]{"IEMobile/11", "Trident/7"}, "11"),
+ new VersionMapping(new String[]{"IEMobile/10"}, "10"),
+ new VersionMapping(new String[]{"IEMobile/9"}, "9"),
+ new VersionMapping(new String[]{"IEMobile/8"}, "8"),
+ new VersionMapping(new String[]{"IEMobile/7"}, "7"),
+ new VersionMapping(new String[]{"IEMobile/6"}, "6"),
+ new VersionMapping(new String[]{"IEMobile/5"}, "5")
+ }, new PatternVersionFetcher("MSIE (([\\d]+)\\.([\\w]+))")
+ ),
+
+ EDGE(
+ "Microsoft Edge",
+ new String[]{"Edge"},
+ null,
+ BrowserType.WEB_BROWSER,
+ new BrowserTypeFetcher[]{
+ new ContainsBrowserTypeFetcher("Mobile Safari", BrowserType.MOBILE_BROWSER)
+ },
+ RenderingEngine.EDGE_HTML,
+ Manufacturer.MICROSOFT,
+ null,
+ new PatternVersionFetcher("(?:Edge\\/(([0-9]+)\\.([0-9]*)))")
+ ),
+
+ CHROME(
+ "Chrome",
+ new String[]{"Chrome", "CrMo", "CriOS"},
+ null,
+ BrowserType.WEB_BROWSER,
+ new BrowserTypeFetcher[]{
+ new ContainsBrowserTypeFetcher("CrMo", BrowserType.MOBILE_BROWSER),
+ new ContainsBrowserTypeFetcher("CriOS", BrowserType.MOBILE_BROWSER),
+ new ContainsBrowserTypeFetcher("Mobile", BrowserType.MOBILE_BROWSER)
+ },
+ RenderingEngine.WEBKIT,
+ Manufacturer.GOOGLE,
+ null,
+ new PatternVersionFetcher("(?:CriOS|CrMo|Chrome)\\/(([0-9]+)\\.?([\\w]+)?(\\.[\\w]+)?(\\.[\\w]+)?)")
+ ),
+
+ FIREFOX(
+ "Firefox",
+ new String[]{"Firefox", "FxiOS"},
+ null,
+ BrowserType.WEB_BROWSER,
+ new BrowserTypeFetcher[]{
+ new ContainsBrowserTypeFetcher("Firefox/3.5 Maemo", BrowserType.MOBILE_BROWSER),
+ new ContainsBrowserTypeFetcher("Mobile", BrowserType.MOBILE_BROWSER)
+ },
+ RenderingEngine.GECKO,
+ Manufacturer.MOZILLA,
+ null,
+ new PatternVersionFetcher("Firefox\\/(([0-9]+)\\.?([\\w]+)?(\\.[\\w]+)?(\\.[\\w]+)?)")
+ ),
+
+ SAFARI(
+ "Safari",
+ new String[]{"Safari"},
+ new String[]{"bot", "preview", "OPR/", "Coast/", "Vivaldi", "CFNetwork", "Phantom"},
+ BrowserType.WEB_BROWSER,
+ new BrowserTypeFetcher[]{
+ new ContainsBrowserTypeFetcher("Mobile Safari", BrowserType.MOBILE_BROWSER),
+ new ContainsBrowserTypeFetcher("Mobile/", BrowserType.MOBILE_BROWSER)
+ },
+ RenderingEngine.WEBKIT,
+ Manufacturer.APPLE,
+ null,
+ new SequentialVersionFetcher(
+ new PatternVersionFetcher("Version\\/(([0-9]+)\\.?([\\w]+)?(\\.[\\w]+)?)"),
+ new MapVersionFetcher("AppleWebKit/(\\d+(?:.\\d+){1,2})", SafariUtils.getWebKitToSafariVersion())
+ )
+ ),
+
+ OPERA_COAST(
+ "Opera Coast",
+ new String[]{"Coast/"},
+ null,
+ BrowserType.MOBILE_BROWSER,
+ null,
+ RenderingEngine.WEBKIT,
+ Manufacturer.OPERA,
+ null,
+ new PatternVersionFetcher("Coast\\/(([\\d]+)\\.([\\w]+)?(\\.[\\w]+)?(\\.[\\w]+)?)")
+ ),
+
+ OPERA(
+ "Opera",
+ new String[]{" OPR/", "Opera"},
+ null,
+ BrowserType.WEB_BROWSER,
+ new BrowserTypeFetcher[]{
+ new ContainsBrowserTypeFetcher("Opera Mini", BrowserType.MOBILE_BROWSER),
+ new ContainsBrowserTypeFetcher("Mobile", BrowserType.MOBILE_BROWSER)
+ },
+ RenderingEngine.PRESTO,
+ Manufacturer.OPERA,
+ new VersionMapping[]{
+ new VersionMapping(new String[]{"Opera/12", "Version/12."}, "12"),
+ new VersionMapping(new String[]{"Opera/11", "Version/11."}, "11"),
+ new VersionMapping(new String[]{"Opera/10", "Version/10."}, "10"),
+ new VersionMapping(new String[]{"Opera/9", "Version/9."}, "9")
+ },
+ new PatternVersionFetcher("OPR\\/(([\\d]+)\\.([\\w]+)?(\\.[\\w]+)?(\\.[\\w]+)?)")
+ ),
+
+ MOZILLA(
+ "Mozilla",
+ new String[]{"Mozilla", "Moozilla"},
+ null,
+ BrowserType.WEB_BROWSER,
+ new BrowserTypeFetcher[]{
+ new ContainsBrowserTypeFetcher("Tablet", BrowserType.MOBILE_BROWSER),
+ new ContainsBrowserTypeFetcher("iPhone", BrowserType.MOBILE_BROWSER),
+ new ContainsBrowserTypeFetcher("Pad", BrowserType.MOBILE_BROWSER),
+ new ContainsBrowserTypeFetcher("Pod", BrowserType.MOBILE_BROWSER),
+ new ContainsBrowserTypeFetcher("Mobile", BrowserType.MOBILE_BROWSER)
+ },
+ RenderingEngine.OTHER,
+ Manufacturer.MOZILLA,
+ null,
+ null
+ ),
+
+ DOLFIN2(
+ "Samsung Dolphin 2",
+ new String[]{"Dolfin/2"},
+ null,
+ BrowserType.MOBILE_BROWSER,
+ null,
+ RenderingEngine.WEBKIT,
+ Manufacturer.SAMSUNG,
+ null,
+ null
+ ),
+
+ CAMINO(
+ "Camino",
+ new String[]{"Camino"},
+ null,
+ BrowserType.WEB_BROWSER,
+ null,
+ RenderingEngine.GECKO,
+ Manufacturer.OTHER,
+ null,
+ new PatternVersionFetcher("Camino\\/(([0-9]+)\\.?([\\w]+)?(\\.[\\w]+)?)")
+ ),
+
+ LOTUS_NOTES(
+ "Lotus Notes",
+ new String[]{"Lotus-Notes"},
+ null,
+ BrowserType.EMAIL_CLIENT,
+ null,
+ RenderingEngine.OTHER,
+ Manufacturer.OTHER,
+ null,
+ new PatternVersionFetcher("Lotus-Notes\\/(([\\d]+)\\.([\\w]+))")
+ ),
+
+ OMNIWEB(
+ "Omniweb",
+ new String[]{"OmniWeb"}, null,
+ BrowserType.WEB_BROWSER,
+ null,
+ RenderingEngine.WEBKIT,
+ Manufacturer.OTHER,
+ null,
+ null
+ ),
+
+ FLOCK(
+ "Flock",
+ new String[]{"Flock"},
+ null,
+ BrowserType.WEB_BROWSER,
+ null,
+ RenderingEngine.GECKO,
+ Manufacturer.OTHER,
+ null,
+ new PatternVersionFetcher("Flock\\/(([0-9]+)\\.?([\\w]+)?(\\.[\\w]+)?)")
+ ),
+
+ VIVALDI(
+ "Vivaldi",
+ new String[]{"Vivaldi"},
+ null,
+ BrowserType.WEB_BROWSER,
+ null,
+ RenderingEngine.BLINK,
+ Manufacturer.OTHER,
+ null,
+ new PatternVersionFetcher("Vivaldi/(([\\d]+).([\\d]+).([\\d]+).([\\d]+))")
+ ),
+
+ SEAMONKEY(
+ "SeaMonkey",
+ new String[]{"SeaMonkey"},
+ null,
+ BrowserType.WEB_BROWSER,
+ null,
+ RenderingEngine.GECKO,
+ Manufacturer.OTHER,
+ null,
+ new PatternVersionFetcher("SeaMonkey\\/(([0-9]+)\\.?([\\w]+)?(\\.[\\w]+)?)")
+ ),
+
+ BOT(
+ "Robot/Spider",
+ new String[]{"Googlebot", "Googlebot-Mobile", "Mediapartners-Google", "Web Preview", "bot",
+ "Applebot", "spider", "crawler", "Feedfetcher", "Slurp", "Twiceler", "Nutch", "BecomeBot",
+ "bingbot", "BingPreview", "Google Web Preview", "WordPress.com mShots", "Seznam",
+ "facebookexternalhit", "YandexMarket", "Teoma", "ThumbSniper", "Phantom", "Go-http-client",
+ "Java/", "python-requests", "YandexBot", "AdsBot-Google", "AhrefsBot"},
+ null,
+ BrowserType.ROBOT,
+ null,
+ RenderingEngine.OTHER,
+ Manufacturer.OTHER,
+ null,
+ null
+ ),
+
+ CFNETWORK(
+ "CFNetwork",
+ new String[]{"CFNetwork"},
+ null,
+ BrowserType.UNKNOWN,
+ null,
+ RenderingEngine.OTHER,
+ Manufacturer.OTHER,
+ null,
+ new PatternVersionFetcher("CFNetwork/(([\\d]+)(?:\\.([\\d]))?(?:\\.([\\d]+))?)")
+ ),
+
+ EUDORA(
+ "Eudora",
+ new String[]{"Eudora", "EUDORA"},
+ null,
+ BrowserType.EMAIL_CLIENT,
+ null,
+ RenderingEngine.OTHER,
+ Manufacturer.OTHER,
+ null,
+ null
+ ),
+
+ POCOMAIL(
+ "PocoMail",
+ new String[]{"PocoMail"},
+ null,
+ BrowserType.EMAIL_CLIENT,
+ null,
+ RenderingEngine.OTHER,
+ Manufacturer.OTHER,
+ null,
+ null
+ ),
+
+ THEBAT(
+ "The Bat!",
+ new String[]{"The Bat"},
+ null,
+ BrowserType.EMAIL_CLIENT,
+ null,
+ RenderingEngine.OTHER,
+ Manufacturer.OTHER,
+ null,
+ null
+ ),
+
+ SILK(
+ "Silk",
+ new String[]{"Silk/"},
+ null,
+ BrowserType.WEB_BROWSER,
+ null,
+ RenderingEngine.WEBKIT,
+ Manufacturer.AMAZON,
+ null,
+ new PatternVersionFetcher("Silk\\/(([0-9]+)\\.?([\\w]+)?(\\.[\\w]+)?(\\-[\\w]+)?)")
+ ),
+
+ BLACKBERRY(
+ "BlackBerry",
+ new String[]{"BB10"},
+ null,
+ BrowserType.MOBILE_BROWSER,
+ null,
+ RenderingEngine.WEBKIT,
+ Manufacturer.BLACKBERRY,
+ null,
+ null
+ ),
+
+ NETFRONT(
+ "NetFront",
+ new String[]{"NetFront"},
+ null,
+ BrowserType.MOBILE_BROWSER,
+ null,
+ RenderingEngine.OTHER,
+ Manufacturer.OTHER,
+ null,
+ null
+ ),
+
+ EVOLUTION(
+ "Evolution",
+ new String[]{"CamelHttpStream"},
+ null,
+ BrowserType.EMAIL_CLIENT,
+ null,
+ RenderingEngine.OTHER,
+ Manufacturer.OTHER,
+ null,
+ null
+ ),
+
+ LYNX(
+ "Lynx",
+ new String[]{"Lynx"},
+ null,
+ BrowserType.TEXT_BROWSER,
+ null,
+ RenderingEngine.OTHER,
+ Manufacturer.OTHER,
+ null,
+ new PatternVersionFetcher("Lynx\\/(([0-9]+)\\.([\\d]+)\\.?([\\w-+]+)?\\.?([\\w-+]+)?)")
+ ),
+
+ KONQUEROR(
+ "Konqueror",
+ new String[]{"Konqueror"},
+ new String[]{"Exabot"},
+ BrowserType.TEXT_BROWSER,
+ null,
+ RenderingEngine.KHTML,
+ Manufacturer.OTHER,
+ null,
+ new PatternVersionFetcher("Konqueror\\/(([0-9]+)\\.?([\\w]+)?(-[\\w]+)?)")
+ ),
+
+ XBOX(
+ "Xbox",
+ new String[]{"xbox"},
+ null,
+ BrowserType.WEB_BROWSER,
+ null,
+ RenderingEngine.TRIDENT,
+ Manufacturer.MICROSOFT,
+ null,
+ null
+ ),
+
+ THUNDERBIRD(
+ "Thunderbird",
+ new String[]{"Thunderbird"},
+ null,
+ BrowserType.EMAIL_CLIENT,
+ null,
+ RenderingEngine.GECKO,
+ Manufacturer.MOZILLA,
+ null,
+ new PatternVersionFetcher("Thunderbird\\/(([0-9]+)\\.?([\\w]+)?(\\.[\\w]+)?(\\.[\\w]+)?)")
+ ),
+
+ UNKNOWN(
+ "Unknown",
+ null,
+ null,
+ BrowserType.UNKNOWN,
+ null,
+ RenderingEngine.OTHER,
+ Manufacturer.OTHER,
+ null,
+ null
+ );
+
+ private final String name;
+
+ private final String[] patterns;
+
+ private final String[] excludePatterns;
+
+ private BrowserType browserType;
+
+ private final BrowserTypeFetcher[] browserTypeFetchers;
+
+ private final RenderingEngine renderingEngine;
+
+ private final Manufacturer manufacturer;
+
+ private final VersionMapping[] versionMappings;
+
+ private final VersionFetcher versionFetcher;
+
+ private String version;
+
+ Browser(final String name, final String[] patterns, final String[] excludePatterns, final BrowserType browserType,
+ final BrowserTypeFetcher[] browserTypeFetchers, final RenderingEngine renderingEngine,
+ final Manufacturer manufacturer, final VersionMapping[] versionMappings,
+ final VersionFetcher versionFetcher){
+ this.name = name;
+ this.patterns = patterns;
+ this.excludePatterns = excludePatterns;
+ this.browserType = browserType;
+ this.browserTypeFetchers = browserTypeFetchers;
+ this.renderingEngine = renderingEngine;
+ this.manufacturer = manufacturer;
+ this.versionMappings = versionMappings;
+ this.versionFetcher = versionFetcher;
+ }
+
+ public String getName(){
+ return name;
+ }
+
+ public BrowserType getBrowserType(){
+ return browserType;
+ }
+
+ public RenderingEngine getRenderingEngine(){
+ return renderingEngine;
+ }
+
+ public Manufacturer getManufacturer(){
+ return manufacturer;
+ }
+
+ public String getVersion(){
+ return version;
+ }
+
+ public static Browser parse(final String userAgent){
+ Browser result = parseBrowser(userAgent);
+
+ if(result == null){
+ return Browser.UNKNOWN;
+ }
+
+ if(result.browserTypeFetchers != null){
+ BrowserType browserType = parseBrowserType(userAgent, result.browserTypeFetchers);
+
+ if(browserType != null){
+ result.browserType = browserType;
+ }
+ }
+
+ return result;
+
+ }
+
+ @Override
+ public String toString(){
+ return name + " " + version;
+ }
+
+ private static Browser parseBrowser(final String userAgent){
+ final Parser parser = new Parser<>(Browser.values());
+ return parser.parse(userAgent, (browser)->{
+ if(browser.excludePatterns != null){
+ for(String excludePattern : browser.excludePatterns){
+ if(StringUtils.containsIgnoreCase(userAgent, excludePattern)){
+ return null;
+ }
+ }
+ }
+
+ if(browser.patterns != null){
+ for(String pattern : browser.patterns){
+ if(StringUtils.containsIgnoreCase(userAgent, pattern)){
+ parseVersion(userAgent, browser);
+
+ return browser;
+ }
+ }
+ }
+
+ return null;
+ });
+ }
+
+ private static void parseVersion(final String userAgent, final Browser browser){
+ if(browser.versionMappings != null){
+ out:
+ for(VersionMapping versionMapping : browser.versionMappings){
+ if(versionMapping.getPatterns() == null){
+ continue;
+ }
+
+ for(String pattern : versionMapping.getPatterns()){
+ if(StringUtils.containsIgnoreCase(userAgent, pattern)){
+ browser.version = versionMapping.getVersion();
+ if(browser.version != null){
+ break out;
+ }
+ }
+ }
+ }
+ }
+
+ if(browser.version == null && browser.versionFetcher != null){
+ Version version = browser.versionFetcher.fetch(userAgent);
+ if(version != null){
+ browser.version = version.getMajorVersion();
+ }
+ }
+ }
+
+ private static BrowserType parseBrowserType(final String userAgent, final BrowserTypeFetcher[] browserTypeFetchers){
+ final Parser browserTypeParser = new Parser<>(BrowserType.values());
+ return browserTypeParser.parse(userAgent, (bt)->{
+ for(BrowserTypeFetcher browserTypeFetcher : browserTypeFetchers){
+ BrowserType ret = browserTypeFetcher.fetch(userAgent);
+ if(ret != null){
+ return ret;
+ }
+ }
+
+ return null;
+ });
+ }
+
+}
diff --git a/buession-web/src/main/java/com/buession/web/utils/useragentutils/BrowserType.java b/buession-web/src/main/java/com/buession/web/utils/useragentutils/BrowserType.java
new file mode 100644
index 000000000..7b28efe74
--- /dev/null
+++ b/buession-web/src/main/java/com/buession/web/utils/useragentutils/BrowserType.java
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ *
+ * =========================================================================================================
+ *
+ * This software consists of voluntary contributions made by many individuals on behalf of the
+ * Apache Software Foundation. For more information on the Apache Software Foundation, please see
+ * .
+ *
+ * +-------------------------------------------------------------------------------------------------------+
+ * | License: http://www.apache.org/licenses/LICENSE-2.0.txt |
+ * | Author: Yong.Teng |
+ * | Copyright @ 2013-2023 Buession.com Inc. |
+ * +-------------------------------------------------------------------------------------------------------+
+ */
+package com.buession.web.utils.useragentutils;
+
+/**
+ * 浏览器类型
+ *
+ * @author Yong.Teng
+ * @since 2.2.1
+ */
+public enum BrowserType {
+
+ /**
+ * Standard web-browser
+ */
+ WEB_BROWSER("Browser"),
+
+ /**
+ * Special web-browser for mobile devices
+ */
+ MOBILE_BROWSER("Browser (mobile)"),
+
+ /**
+ * Text only browser like the good old Lynx
+ */
+ TEXT_BROWSER("Browser (text only)"),
+
+ /**
+ * Email client like Thunderbird
+ */
+ EMAIL_CLIENT("Email Client"),
+
+ /**
+ * Search robot, spider, crawler,...
+ */
+ ROBOT("Robot"),
+
+ /**
+ * Application
+ */
+ APPLICATION("Application"),
+
+ UNKNOWN("unknown");
+
+ private final String name;
+
+ BrowserType(final String name){
+ this.name = name;
+ }
+
+ public String getName(){
+ return name;
+ }
+
+}
diff --git a/buession-web/src/main/java/com/buession/web/utils/useragentutils/DeviceType.java b/buession-web/src/main/java/com/buession/web/utils/useragentutils/DeviceType.java
new file mode 100644
index 000000000..52e0f9b5d
--- /dev/null
+++ b/buession-web/src/main/java/com/buession/web/utils/useragentutils/DeviceType.java
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ *
+ * =========================================================================================================
+ *
+ * This software consists of voluntary contributions made by many individuals on behalf of the
+ * Apache Software Foundation. For more information on the Apache Software Foundation, please see
+ * .
+ *
+ * +-------------------------------------------------------------------------------------------------------+
+ * | License: http://www.apache.org/licenses/LICENSE-2.0.txt |
+ * | Author: Yong.Teng |
+ * | Copyright @ 2013-2023 Buession.com Inc. |
+ * +-------------------------------------------------------------------------------------------------------+
+ */
+package com.buession.web.utils.useragentutils;
+
+/**
+ * 设备类型
+ *
+ * @author Yong.Teng
+ * @since 2.2.1
+ */
+public enum DeviceType {
+ /**
+ * 电脑
+ */
+ COMPUTER("Computer"),
+
+ /**
+ * 手机
+ */
+ MOBILE("Mobile"),
+
+ /**
+ * 平板
+ */
+ TABLET("Tablet"),
+
+ /**
+ * Digital media receiver like the Google TV.
+ */
+ DMR("Digital media receiver"),
+
+ /**
+ * Game console
+ */
+ GAME_CONSOLE("Game console"),
+
+ /**
+ * 未知
+ */
+ UNKNOWN("Unknown");
+
+ private final String name;
+
+ DeviceType(final String name){
+ this.name = name;
+ }
+
+ public String getName(){
+ return name;
+ }
+
+}
diff --git a/buession-web/src/main/java/com/buession/web/utils/useragentutils/Fetcher.java b/buession-web/src/main/java/com/buession/web/utils/useragentutils/Fetcher.java
new file mode 100644
index 000000000..db3e8a006
--- /dev/null
+++ b/buession-web/src/main/java/com/buession/web/utils/useragentutils/Fetcher.java
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ *
+ * =========================================================================================================
+ *
+ * This software consists of voluntary contributions made by many individuals on behalf of the
+ * Apache Software Foundation. For more information on the Apache Software Foundation, please see
+ * .
+ *
+ * +-------------------------------------------------------------------------------------------------------+
+ * | License: http://www.apache.org/licenses/LICENSE-2.0.txt |
+ * | Author: Yong.Teng |
+ * | Copyright @ 2013-2023 Buession.com Inc. |
+ * +-------------------------------------------------------------------------------------------------------+
+ */
+package com.buession.web.utils.useragentutils;
+
+/**
+ * @author Yong.Teng
+ * @since 2.2.1
+ */
+@FunctionalInterface
+public interface Fetcher {
+
+ T fetch(final String str);
+
+}
diff --git a/buession-web/src/main/java/com/buession/web/utils/useragentutils/Manufacturer.java b/buession-web/src/main/java/com/buession/web/utils/useragentutils/Manufacturer.java
new file mode 100644
index 000000000..77e59f1c8
--- /dev/null
+++ b/buession-web/src/main/java/com/buession/web/utils/useragentutils/Manufacturer.java
@@ -0,0 +1,93 @@
+/*
+ * 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.
+ *
+ * =========================================================================================================
+ *
+ * This software consists of voluntary contributions made by many individuals on behalf of the
+ * Apache Software Foundation. For more information on the Apache Software Foundation, please see
+ * .
+ *
+ * +-------------------------------------------------------------------------------------------------------+
+ * | License: http://www.apache.org/licenses/LICENSE-2.0.txt |
+ * | Author: Yong.Teng |
+ * | Copyright @ 2013-2023 Buession.com Inc. |
+ * +-------------------------------------------------------------------------------------------------------+
+ */
+package com.buession.web.utils.useragentutils;
+
+/**
+ * 浏览器厂商
+ *
+ * @author Yong.Teng
+ * @since 2.2.1
+ */
+public enum Manufacturer {
+
+ MICROSOFT("Microsoft Corporation"),
+
+ APPLE("Apple Inc."),
+
+ SUN("Sun Microsystems, Inc."),
+
+ SYMBIAN("Symbian Ltd."),
+
+ NOKIA("Nokia Corporation"),
+
+ BLACKBERRY("Research In Motion Limited"),
+
+ HP("Hewlett Packard"),
+
+ SONY_ERICSSON("Sony Ericsson Mobile Communications AB"),
+
+ SAMSUNG("Samsung Electronics"),
+
+ SONY("Sony Computer Entertainment, Inc."),
+
+ NINTENDO("Nintendo"),
+
+ OPERA("Opera Software ASA"),
+
+ MOZILLA("Mozilla Foundation"),
+
+ GOOGLE("Google Inc."),
+
+ COMPUSERVE("CompuServe Interactive Services, Inc."),
+
+ YAHOO("Yahoo Inc."),
+
+ AOL("AOL LLC."),
+
+ MMC("Mail.com Media Corporation"),
+
+ AMAZON("Amazon.com, Inc."),
+
+ ROKU("Roku, Inc."),
+
+ ADOBE("Adobe Systems Inc."),
+
+ CONONICAL("Canonical Ltd."),
+
+ LINUX_FOUNDATION("Linux Foundation"),
+
+ OTHER("Other");
+
+ private final String name;
+
+ Manufacturer(final String name){
+ this.name = name;
+ }
+
+ public String getName(){
+ return name;
+ }
+
+}
diff --git a/buession-web/src/main/java/com/buession/web/utils/useragentutils/OperatingSystem.java b/buession-web/src/main/java/com/buession/web/utils/useragentutils/OperatingSystem.java
new file mode 100644
index 000000000..b9aabc532
--- /dev/null
+++ b/buession-web/src/main/java/com/buession/web/utils/useragentutils/OperatingSystem.java
@@ -0,0 +1,519 @@
+/*
+ * 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.
+ *
+ * =========================================================================================================
+ *
+ * This software consists of voluntary contributions made by many individuals on behalf of the
+ * Apache Software Foundation. For more information on the Apache Software Foundation, please see
+ * .
+ *
+ * +-------------------------------------------------------------------------------------------------------+
+ * | License: http://www.apache.org/licenses/LICENSE-2.0.txt |
+ * | Author: Yong.Teng |
+ * | Copyright @ 2013-2023 Buession.com Inc. |
+ * +-------------------------------------------------------------------------------------------------------+
+ */
+package com.buession.web.utils.useragentutils;
+
+import com.buession.core.utils.StringUtils;
+import com.buession.web.utils.useragentutils.devicetypefetcher.ContainsDeviceTypeFetcher;
+import com.buession.web.utils.useragentutils.devicetypefetcher.DeviceTypeFetcher;
+import com.buession.web.utils.useragentutils.versionfetcher.PatternVersionFetcher;
+import com.buession.web.utils.useragentutils.versionfetcher.VersionFetcher;
+
+/**
+ * 操作系统
+ *
+ * @author Yong.Teng
+ * @since 2.2.1
+ */
+public enum OperatingSystem {
+ WINDOWS(
+ "Windows",
+ new String[]{"Windows"},
+ null,
+ DeviceType.COMPUTER,
+ new DeviceTypeFetcher[]{
+ new ContainsDeviceTypeFetcher("Tablet", DeviceType.TABLET)
+ },
+ Manufacturer.MICROSOFT,
+ new VersionMapping[]{
+ new VersionMapping(new String[]{"Windows NT 6.4", "Windows NT 10"}, "10"),
+ new VersionMapping(new String[]{"Windows NT 6.2", "Windows NT 6.3"}, "8"),
+ new VersionMapping(new String[]{"Windows NT 6.1"}, "7"),
+ new VersionMapping(new String[]{"Windows NT 6"}, "Vista"),
+ new VersionMapping(new String[]{"Windows NT 5.0"}, "2000"),
+ new VersionMapping(new String[]{"Windows NT 5"}, "XP"),
+ new VersionMapping(new String[]{"Windows 98", "Win98"}, "98"),
+ new VersionMapping(new String[]{"Windows NT"}, null)
+ },
+ null
+ ),
+
+ WINDOWS_PHONE(
+ "Windows Phone",
+ new String[]{"Windows Phone", "Windows Mobile"},
+ null,
+ DeviceType.MOBILE,
+ null,
+ Manufacturer.MICROSOFT,
+ new VersionMapping[]{
+ new VersionMapping(new String[]{"Windows Phone 10"}, "10"),
+ new VersionMapping(new String[]{"Windows Phone 8"}, "8"),
+ new VersionMapping(new String[]{"Windows Phone OS 7"}, "7"),
+ new VersionMapping(new String[]{"Windows Phone"}, null)
+ },
+ null
+ ),
+
+ WINDOWS_MOBILE(
+ "Windows Mobile",
+ new String[]{"Windows CE"},
+ null,
+ DeviceType.MOBILE,
+ null,
+ Manufacturer.MICROSOFT,
+ null,
+ null
+ ),
+
+ XBOX(
+ "Xbox OS",
+ new String[]{"xbox"},
+ null,
+ DeviceType.GAME_CONSOLE,
+ null,
+ Manufacturer.MICROSOFT,
+ null,
+ null
+ ),
+
+ ANDROID(
+ "Android",
+ new String[]{"Android"},
+ null,
+ DeviceType.MOBILE,
+ new DeviceTypeFetcher[]{
+ new ContainsDeviceTypeFetcher("Tablet", DeviceType.TABLET),
+ new ContainsDeviceTypeFetcher("GoogleTV", DeviceType.DMR),
+ },
+ Manufacturer.GOOGLE,
+ new VersionMapping[]{
+ new VersionMapping(new String[]{"Kindle Fire", "GT-P1000", "SCH-I800"}, "2"),
+ },
+ new PatternVersionFetcher("Android[ -]((\\d+))")
+ ),
+
+ IOS(
+ "iOS",
+ new String[]{"iPhone", "iPad", "iPod", "iOS"},
+ null,
+ DeviceType.MOBILE,
+ new DeviceTypeFetcher[]{
+ new ContainsDeviceTypeFetcher("iPad", DeviceType.TABLET)
+ },
+ Manufacturer.APPLE,
+ null,
+ new PatternVersionFetcher("OS ((\\d+)_(\\d+)_(\\d+))")
+ ),
+
+ CHROME_OS(
+ "Chrome OS",
+ new String[]{"CrOS"},
+ null,
+ DeviceType.COMPUTER,
+ null,
+ Manufacturer.GOOGLE,
+ null,
+ null
+ ),
+
+ MAC_OS_X(
+ "Mac OS X",
+ new String[]{"Mac OS X"},
+ null,
+ DeviceType.COMPUTER,
+ null,
+ Manufacturer.APPLE,
+ null,
+ new PatternVersionFetcher("Mac OS X ((\\d+)[_\\.]?(\\d+)?([_\\.]\\d+)?)")
+ ),
+
+ MAC_OS(
+ "Mac OS",
+ new String[]{"Mac OS"},
+ null,
+ DeviceType.COMPUTER,
+ null,
+ Manufacturer.APPLE,
+ null,
+ new PatternVersionFetcher("Mac OS ((\\d+)[_\\.]?(\\d+)?([_\\.]\\d+)?)")
+ ),
+
+ WEBOS(
+ "WebOS",
+ new String[]{"webOS"},
+ null,
+ DeviceType.MOBILE,
+ null,
+ Manufacturer.HP,
+ null,
+ null
+ ),
+
+ PALM(
+ "PalmOS",
+ new String[]{"Palm"},
+ null,
+ DeviceType.MOBILE,
+ null,
+ Manufacturer.HP,
+ null,
+ null
+ ),
+
+ MEEGO(
+ "MeeGo",
+ new String[]{"MeeGo"},
+ null,
+ DeviceType.COMPUTER,
+ null,
+ Manufacturer.NOKIA,
+ null,
+ null
+ ),
+
+ MAEMO(
+ "Maemo",
+ new String[]{"Maemo"},
+ null,
+ DeviceType.MOBILE,
+ null,
+ Manufacturer.NOKIA,
+ null,
+ null
+ ),
+
+ BADA(
+ "Bada",
+ new String[]{"Bada"},
+ null,
+ DeviceType.MOBILE,
+ null,
+ Manufacturer.SAMSUNG,
+ null,
+ null
+ ),
+
+ TIZEN(
+ "Tizen",
+ new String[]{"Tizen"},
+ null,
+ DeviceType.COMPUTER,
+ new DeviceTypeFetcher[]{
+ new ContainsDeviceTypeFetcher("Mobile", DeviceType.MOBILE),
+ new ContainsDeviceTypeFetcher("Smart-TV", DeviceType.DMR),
+ new ContainsDeviceTypeFetcher("TV ", DeviceType.DMR)
+ },
+ Manufacturer.LINUX_FOUNDATION,
+ null,
+ new PatternVersionFetcher("Tizen \\/((\\d+))\\.")
+ ),
+
+ KINDLE(
+ "Kindle",
+ new String[]{"Kindle"},
+ null,
+ DeviceType.TABLET,
+ null,
+ Manufacturer.AMAZON,
+ new VersionMapping[]{
+ new VersionMapping(new String[]{"Kindle"}, null)
+ },
+ new PatternVersionFetcher("Kindle\\/((\\d+))")
+ ),
+
+ Ubuntu(
+ "Ubuntu",
+ new String[]{"Ubuntu"},
+ null,
+ DeviceType.COMPUTER,
+ new DeviceTypeFetcher[]{
+ new ContainsDeviceTypeFetcher("mobile", DeviceType.MOBILE)
+ },
+ Manufacturer.CONONICAL,
+ null,
+ null
+ ),
+
+ LINUX(
+ "Linux",
+ new String[]{"Linux"},
+ null,
+ DeviceType.COMPUTER,
+ new DeviceTypeFetcher[]{
+ new ContainsDeviceTypeFetcher("SmartTv ", DeviceType.DMR)
+ },
+ Manufacturer.OTHER,
+ null,
+ null
+ ),
+
+ SUN_OS(
+ "SunOS",
+ new String[]{"SunOS"},
+ null,
+ DeviceType.COMPUTER,
+ null,
+ Manufacturer.SUN,
+ null,
+ null
+ ),
+
+ BLACKBERRY(
+ "BlackBerryOS",
+ new String[]{"BlackBerry"},
+ null,
+ DeviceType.MOBILE,
+ new DeviceTypeFetcher[]{
+ new ContainsDeviceTypeFetcher("RIM Tablet OS", DeviceType.TABLET)
+ },
+ Manufacturer.BLACKBERRY,
+ null,
+ new PatternVersionFetcher("Version\\/((\\d+))")
+ ),
+
+ SYMBIAN(
+ "Symbian OS",
+ new String[]{"Symbian", "Series60"},
+ null,
+ DeviceType.MOBILE,
+ new DeviceTypeFetcher[]{
+ new ContainsDeviceTypeFetcher("Mobile", DeviceType.MOBILE),
+ new ContainsDeviceTypeFetcher("Smart-TV", DeviceType.DMR),
+ new ContainsDeviceTypeFetcher("TV ", DeviceType.DMR)
+ },
+ Manufacturer.SYMBIAN,
+ new VersionMapping[]{
+ new VersionMapping(new String[]{"Series60/3"}, "9"),
+ new VersionMapping(new String[]{"Series60/2.6", "Series60/2.8"}, "8")
+ },
+ new PatternVersionFetcher("Symbian\\/((\\d+))")
+ ),
+
+ SERIES40(
+ "Series 40",
+ new String[]{"Nokia6300"},
+ null,
+ DeviceType.MOBILE,
+ null,
+ Manufacturer.NOKIA,
+ null,
+ null
+ ),
+
+ SONY_ERICSSON(
+ "Sony Ericsson",
+ new String[]{"SonyEricsson"},
+ null,
+ DeviceType.MOBILE,
+ null,
+ Manufacturer.SONY_ERICSSON,
+ null,
+ null
+ ),
+
+ PSP(
+ "Sony Playstation",
+ new String[]{"Playstation"},
+ null,
+ DeviceType.GAME_CONSOLE,
+ null,
+ Manufacturer.SONY,
+ null,
+ null
+ ),
+
+ WII(
+ "Nintendo Wii",
+ new String[]{"Wii"},
+ null,
+ DeviceType.GAME_CONSOLE,
+ null,
+ Manufacturer.NINTENDO,
+ null,
+ null
+ ),
+
+ ROKU(
+ "Roku OS",
+ new String[]{"Roku"},
+ null,
+ DeviceType.DMR,
+ null,
+ Manufacturer.ROKU,
+ null,
+ null
+ ),
+
+ UNKNOWN(
+ "Unknown",
+ null,
+ null,
+ DeviceType.COMPUTER,
+ new DeviceTypeFetcher[]{
+ new ContainsDeviceTypeFetcher("Mobile", DeviceType.MOBILE),
+ new ContainsDeviceTypeFetcher("Tablet", DeviceType.TABLET)
+ },
+ Manufacturer.OTHER,
+ null,
+ null
+ );
+
+ private final String name;
+
+ private final String[] patterns;
+
+ private final String[] excludePatterns;
+
+ private DeviceType deviceType;
+
+ private final DeviceTypeFetcher[] deviceTypeFetchers;
+
+ private final Manufacturer manufacturer;
+
+ private final VersionMapping[] versionMappings;
+
+ private final VersionFetcher versionFetcher;
+
+ private String version;
+
+ OperatingSystem(final String name, final String[] patterns, final String[] excludePatterns,
+ final DeviceType deviceType, final DeviceTypeFetcher[] deviceTypeFetchers,
+ final Manufacturer manufacturer, final VersionMapping[] versionMappings,
+ final VersionFetcher versionFetcher){
+ this.name = name;
+ this.patterns = patterns;
+ this.excludePatterns = excludePatterns;
+ this.deviceType = deviceType;
+ this.deviceTypeFetchers = deviceTypeFetchers;
+ this.manufacturer = manufacturer;
+ this.versionMappings = versionMappings;
+ this.versionFetcher = versionFetcher;
+ }
+
+ public String getName(){
+ return name;
+ }
+
+ public DeviceType getDeviceType(){
+ return deviceType;
+ }
+
+ public Manufacturer getManufacturer(){
+ return manufacturer;
+ }
+
+ public String getVersion(){
+ return version;
+ }
+
+ public static OperatingSystem parse(final String userAgent){
+ OperatingSystem result = parseOperatingSystem(userAgent);
+
+ if(result == null){
+ return OperatingSystem.UNKNOWN;
+ }
+
+ if(result.deviceTypeFetchers != null){
+ DeviceType deviceType = parseDeviceType(userAgent, result.deviceTypeFetchers);
+
+ if(deviceType != null){
+ result.deviceType = deviceType;
+ }
+ }
+
+ return result;
+ }
+
+ @Override
+ public String toString(){
+ return name + " " + version;
+ }
+
+ private static OperatingSystem parseOperatingSystem(final String userAgent){
+ final Parser parser = new Parser<>(OperatingSystem.values());
+ return parser.parse(userAgent, (operatingSystem)->{
+ if(operatingSystem.excludePatterns != null){
+ for(String excludePattern : operatingSystem.excludePatterns){
+ if(StringUtils.containsIgnoreCase(userAgent, excludePattern)){
+ return null;
+ }
+ }
+ }
+
+ if(operatingSystem.patterns != null){
+ for(String pattern : operatingSystem.patterns){
+ if(StringUtils.containsIgnoreCase(userAgent, pattern)){
+ parseVersion(userAgent, operatingSystem);
+
+ return operatingSystem;
+ }
+ }
+ }
+
+ return null;
+ });
+ }
+
+ private static void parseVersion(final String userAgent, final OperatingSystem operatingSystem){
+ if(operatingSystem.versionMappings != null){
+ out:
+ for(VersionMapping versionMapping : operatingSystem.versionMappings){
+ if(versionMapping.getPatterns() == null){
+ continue;
+ }
+
+ for(String pattern : versionMapping.getPatterns()){
+ if(StringUtils.containsIgnoreCase(userAgent, pattern)){
+ operatingSystem.version = versionMapping.getVersion();
+ if(operatingSystem.version != null){
+ break out;
+ }
+ }
+ }
+ }
+ }
+
+ if(operatingSystem.version == null && operatingSystem.versionFetcher != null){
+ Version version = operatingSystem.versionFetcher.fetch(userAgent);
+ if(version != null){
+ operatingSystem.version = version.getMajorVersion();
+ }
+ }
+ }
+
+ private static DeviceType parseDeviceType(final String userAgent, final DeviceTypeFetcher[] deviceTypeFetchers){
+ final Parser deviceTypeParser = new Parser<>(DeviceType.values());
+ return deviceTypeParser.parse(userAgent, (dt)->{
+ for(DeviceTypeFetcher deviceTypeFetcher : deviceTypeFetchers){
+ DeviceType ret = deviceTypeFetcher.fetch(userAgent);
+ if(ret != null){
+ return ret;
+ }
+ }
+
+ return null;
+ });
+ }
+
+}
diff --git a/buession-web/src/main/java/com/buession/web/utils/useragentutils/Parser.java b/buession-web/src/main/java/com/buession/web/utils/useragentutils/Parser.java
new file mode 100644
index 000000000..c9f54041a
--- /dev/null
+++ b/buession-web/src/main/java/com/buession/web/utils/useragentutils/Parser.java
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ *
+ * =========================================================================================================
+ *
+ * This software consists of voluntary contributions made by many individuals on behalf of the
+ * Apache Software Foundation. For more information on the Apache Software Foundation, please see
+ * .
+ *
+ * +-------------------------------------------------------------------------------------------------------+
+ * | License: http://www.apache.org/licenses/LICENSE-2.0.txt |
+ * | Author: Yong.Teng |
+ * | Copyright @ 2013-2023 Buession.com Inc. |
+ * +-------------------------------------------------------------------------------------------------------+
+ */
+package com.buession.web.utils.useragentutils;
+
+import com.buession.core.validator.Validate;
+
+import java.util.function.Function;
+
+/**
+ * @author Yong.Teng
+ * @since 2.2.1
+ */
+class Parser> {
+
+ private final E[] enumElements;
+
+ public Parser(final E[] enumElements){
+ this.enumElements = enumElements;
+ }
+
+ public E parse(final String userAgent, final Function function){
+ if(Validate.hasText(userAgent)){
+ E result;
+
+ for(E element : enumElements){
+ result = function.apply(element);
+ if(result != null){
+ return result;
+ }
+ }
+ }
+
+ return null;
+ }
+
+}
diff --git a/buession-web/src/main/java/com/buession/web/utils/useragentutils/RenderingEngine.java b/buession-web/src/main/java/com/buession/web/utils/useragentutils/RenderingEngine.java
new file mode 100644
index 000000000..4a040ab53
--- /dev/null
+++ b/buession-web/src/main/java/com/buession/web/utils/useragentutils/RenderingEngine.java
@@ -0,0 +1,99 @@
+/*
+ * 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.
+ *
+ * =========================================================================================================
+ *
+ * This software consists of voluntary contributions made by many individuals on behalf of the
+ * Apache Software Foundation. For more information on the Apache Software Foundation, please see
+ * .
+ *
+ * +-------------------------------------------------------------------------------------------------------+
+ * | License: http://www.apache.org/licenses/LICENSE-2.0.txt |
+ * | Author: Yong.Teng |
+ * | Copyright @ 2013-2023 Buession.com Inc. |
+ * +-------------------------------------------------------------------------------------------------------+
+ */
+package com.buession.web.utils.useragentutils;
+
+/**
+ * 渲染引擎
+ *
+ * @author Yong.Teng
+ * @since 2.2.1
+ */
+public enum RenderingEngine {
+ /**
+ * EdgeHTML is a proprietary layout engine developed for the Microsoft Edge web browser, developed by Microsoft.
+ */
+ EDGE_HTML("EdgeHTML"),
+
+ /**
+ * Trident is the the Microsoft layout engine, mainly used by Internet Explorer.
+ */
+ TRIDENT("Trident"),
+
+ /**
+ * HTML parsing and rendering engine of Microsoft Office Word, used by some other products of the Office suite instead of Trident.
+ */
+ WORD("Microsoft Office Word"),
+
+ /**
+ * Open source and cross platform layout engine, used by Firefox and many other browsers.
+ */
+ GECKO("Gecko"),
+
+ /**
+ * Layout engine based on KHTML, used by Safari, Chrome and some other browsers.
+ */
+ WEBKIT("WebKit"),
+
+ /**
+ * Proprietary layout engine by Opera Software ASA
+ */
+ PRESTO("Presto"),
+
+ /**
+ * Original layout engine of the Mozilla browser and related products. Predecessor of Gecko.
+ */
+ MOZILLA("Mozilla"),
+
+ /**
+ * Layout engine of the KDE project
+ */
+ KHTML("KHTML"),
+
+ /**
+ * Other or unknown layout engine.
+ */
+ BLINK("Blink"),
+
+ /**
+ * Layout engine developed as part ofthe Chromium project. Fored from WebKit.
+ */
+ OTHER("Other");
+
+ private final String name;
+
+ RenderingEngine(String name){
+ this.name = name;
+ }
+
+ public String getName(){
+ return name;
+ }
+
+ @Override
+ public String toString(){
+ return name;
+ }
+
+}
diff --git a/buession-web/src/main/java/com/buession/web/utils/useragentutils/SafariUtils.java b/buession-web/src/main/java/com/buession/web/utils/useragentutils/SafariUtils.java
new file mode 100644
index 000000000..92ec54890
--- /dev/null
+++ b/buession-web/src/main/java/com/buession/web/utils/useragentutils/SafariUtils.java
@@ -0,0 +1,223 @@
+/*
+ * 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.
+ *
+ * =========================================================================================================
+ *
+ * This software consists of voluntary contributions made by many individuals on behalf of the
+ * Apache Software Foundation. For more information on the Apache Software Foundation, please see
+ * .
+ *
+ * +-------------------------------------------------------------------------------------------------------+
+ * | License: http://www.apache.org/licenses/LICENSE-2.0.txt |
+ * | Author: Yong.Teng |
+ * | Copyright @ 2013-2023 Buession.com Inc. |
+ * +-------------------------------------------------------------------------------------------------------+
+ */
+package com.buession.web.utils.useragentutils;
+
+import com.buession.core.utils.StringUtils;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Yong.Teng
+ * @since 2.2.1
+ */
+public class SafariUtils {
+
+ private final static String[][] webKitToSafariVersion = new String[][]{
+ {"48", "0.8"},
+ {"73", "0.9"},
+ {"85", "1.0"},
+ {"85.8.5", "1.0.3"},
+ {"100", "1.1"},
+ {"125", "1.2"},
+ {"312", "1.3"},
+ {"312.3", "1.3.1"},
+ {"312.5", "1.3.2"},
+ {"312.6", "1.3.2"},
+ {"412", "2.0"},
+ {"416.11", "2.0.2"},
+ {"419.3", "2.0.4"},
+ {"522.11", "3.0"},
+ {"522.12", "3.0.2"},
+ {"522.12.1", "3.0.3"},
+ {"523.10", "3.0.4"},
+ {"525.20", "3.1.1"},
+ {"525.21", "3.1.2"},
+ {"525.26", "3.2"},
+ {"525.27", "3.2.1"},
+ {"525.28", "3.2.3"},
+ // {"530.17", "4.0.1"}, // ambiguity: Safari 4.0 for Mac 10.4-10.5 and Safari 4.0.1 for Windows vista and XP
+ {"530.18", "4.0.1"},
+ {"530.19", "4.0.2"},
+ {"531.9", "4.0.3"},
+ {"531.21.10", "4.0.4"},
+ {"531.22.7", "4.0.5"},
+
+ // {"533.16", "4.1"}, // ambiguity: Safari 4.1 on MacOsX 10.4, Safari 5.0 on MacOsX 10.5-10.6 and Windows XP, Vista and 7
+ // {"533.17.8", "4.1.1"}, // ambiguity: Safari 4.1.1 on MacOsX 10.4, Safari 5.0.1 on MacOsX 10.5-10.6 and Windows XP, Vista and 7
+ //{"533.18.5", "4.1.2"}, // ambiguity: Safari 4.1.2 on MacOsX 10.4, Safari 5.0.2 on MacOsX 10.5-10.6 and Windows XP, Vista and 7
+ //{"533.19.4", "4.1.3"},// ambiguity: Safari 4.1.3 on MacOsX 10.4, Safari 5.0.3 on MacOsX 10.5-10.6 and Windows XP, Vista and 7
+
+ {"533.20.27", "5.0.4"},
+ {"533.21.1", "5.0.5"},
+ {"533.22.3", "5.0.6"},
+ {"534.48.3", "5.1"},
+ {"534.51.22", "5.1.1"},
+ {"534.52.7", "5.1.2"},
+ {"534.53.10", "5.1.3"},
+ {"534.54.16", "5.1.4"},
+ {"534.55.3", "5.1.5"},
+ {"534.56.5", "5.1.6"},
+ {"534.57.2", "5.1.7"},
+ {"534.58.2", "5.1.8"},
+ {"534.59.8", "5.1.9"},
+ {"534.59.10", "5.1.10"},
+ {"536.25", "6.0"},
+ {"536.26", "6.0.1"},
+ {"536.26.17", "6.0.2"},
+ {"536.28.10", "6.0.3"},
+ {"536.29.13", "6.0.4"},
+ {"536.30.1", "6.0.5"},
+ {"537.43.58", "6.1"},
+ //{"537.73.11", "6.1.1"}, // ambiguity: Safari 6.1.1 on OsX 10.7-10.8 and 7.0.1 on OsX 10.9
+
+
+ // data is absent in wikipedia
+ // {"", "6.1.2"},
+ // {"", "6.1.3"},
+ // {"", "6.1.4"},
+ // {"", "6.1.5"},
+ // {"537.78.2", "6.1.6"}, // ambiguity: Safari 6.1.6 on OsX 10.7-10.8 and 7.0.6 on OsX 10.9
+ // data is absent in wikipedia
+ // {"", "6.2"},
+ // {"", "6.2.1"},
+ // {"", "6.2.2"},
+ // {"", "6.2.3"},
+ // {"", "6.2.4"},
+ // {"", "6.2.5"},
+ // {"", "6.2.6"},
+ // {"", "6.2.7"},
+
+
+ // {"537.85.17", "6.2.8"}, // ambiguity: Safari 6.2.8 on OsX 10.8 and 7.1.8 on OsX 10.9
+
+ {"537.71", "7.0"},
+ // data is absent in wikipedia
+ // {"", "7.0.2"},
+ {"537.75.14", "7.0.3"},
+ {"537.76.4", "7.0.4"},
+ {"537.77.4", "7.0.5"},
+
+ ////{"537.78.2", "7.0.6"}, //TODO ambiguity
+
+ // data is absent in wikipedia
+ // {"", "7.1"},
+ // {"", "7.1.1"},
+ // {"", "7.1.2"},
+ // {"", "7.1.3"},
+ // {"", "7.1.4"},
+ // {"", "7.1.5"},
+ // {"", "7.1.6"},
+ // {"", "7.1.7"},
+ {"538.35.8", "8.0"},
+
+ // data is absent in wikipedia
+ // {"", "8.0.1"},
+ // {"", "8.0.2"},
+ // {"", "8.0.3"},
+ // {"", "8.0.4"},
+ // {"", "8.0.5"},
+
+ {"600.6.3", "8.0.6"},
+ {"600.7.12", "8.0.7"},
+ // data is absent in wikipedia
+ // {"", "8.0.8"},
+ // {"", "9.0"},
+
+ {"601.2.7", "9.0.1"},
+ {"601.3.9", "9.0.2"},
+ {"601.4.4", "9.0.3"},
+ {"601.5.17", "9.1"},
+ {"601.6.17", "9.1.1"},
+ {"601.7.1", "9.1.2"},
+ {"601.7.8", "9.1.3"},
+
+ // Safari 10.x
+ {"602.1.50", "10"},
+ {"602.2.14", "10.0.1"},
+ {"602.3.12", "10.0.2"},
+ {"602.4.8", "10.0.3"},
+ {"603.1.30", "10.1"}, // New web technology additions and improvements.
+ {"603.2.4", "10.1.1"},
+ {"603.3.8", "10.1.2"},
+
+ //Safari 11.x ... TODO
+
+ {"522.11.3", "3.0"},
+ {"522.13.1", "3.0.2"},
+ {"522.12.2", "3.0.1"},
+ {"522.15.5", "3.0.3"},
+ {"523.12.9", "3.0.4"},
+ {"523.13", "3.0.4"},
+ {"523.15", "3.0.4"},
+ // mac os 10.4 - 10.5 and Windows XP, Vista
+ {"525.13", "3.1"},
+ {"525.17", "3.1.1"},
+ {"525.21", "3.1.2"},
+
+ {"525.26.13", "3.2"},
+ {"525.27.1", "3.2.1"},
+ {"525.28.1", "3.2.2"},
+ {"525.29.1", "3.2.3"},
+
+ {"526.12.2", "4.0"},
+ {"528.1.1", "4.0"},
+
+ {"526.11.2", "4.0"}, // actually 4.0 beta
+ // 4.0 and 4.0 beta but since it is the same version we do not distinguish between 4.0 and 4.0 beta
+ {"528.16", "4.0"},
+ {"528.17", "4.0"},
+ // end of 4.0 and 4.0 beta
+
+ {"530.19.1", "4.0.2"},
+ {"531.9.1", "4.0.3"},
+ {"531.22.7", "4.0.5"},
+ {"534.50", "5.1"},
+ };
+
+ private final static Map safariVersions;
+
+ static{
+ Map versions = new HashMap<>(webKitToSafariVersion.length);
+
+ for(String[] pair : webKitToSafariVersion){
+ String webKitVersion = pair[0];
+ String browserVersion = pair[1];
+ String[] parts = StringUtils.split(browserVersion, '.');
+ String majorVersion = parts[0];
+ String minorVersion = parts.length > 1 ? parts[1] : null;
+ Version version = new Version(browserVersion, majorVersion, minorVersion);
+ versions.put(webKitVersion, version);
+ }
+
+ safariVersions = Collections.unmodifiableMap(versions);
+ }
+
+ public static Map getWebKitToSafariVersion(){
+ return safariVersions;
+ }
+
+}
diff --git a/buession-web/src/main/java/com/buession/web/utils/useragentutils/UserAgent.java b/buession-web/src/main/java/com/buession/web/utils/useragentutils/UserAgent.java
new file mode 100644
index 000000000..ae6eb444c
--- /dev/null
+++ b/buession-web/src/main/java/com/buession/web/utils/useragentutils/UserAgent.java
@@ -0,0 +1,87 @@
+/*
+ * 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.
+ *
+ * =========================================================================================================
+ *
+ * This software consists of voluntary contributions made by many individuals on behalf of the
+ * Apache Software Foundation. For more information on the Apache Software Foundation, please see
+ * .
+ *
+ * +-------------------------------------------------------------------------------------------------------+
+ * | License: http://www.apache.org/licenses/LICENSE-2.0.txt |
+ * | Author: Yong.Teng |
+ * | Copyright @ 2013-2023 Buession.com Inc. |
+ * +-------------------------------------------------------------------------------------------------------+
+ */
+package com.buession.web.utils.useragentutils;
+
+import com.buession.core.validator.Validate;
+
+/**
+ * User-Agent 解析操作系统和浏览器信息
+ *
+ * @author Yong.Teng
+ * @since 2.2.1
+ */
+public class UserAgent {
+
+ /**
+ * 操作系统信息
+ */
+ private final OperatingSystem operatingSystem;
+
+ /**
+ * 浏览器信息
+ */
+ private final Browser browser;
+
+ /**
+ * 构造函数
+ *
+ * @param userAgent
+ * User-Agent
+ */
+ public UserAgent(final String userAgent){
+ if(Validate.hasText(userAgent)){
+ this.browser = Browser.parse(userAgent);
+ this.operatingSystem = this.browser == Browser.BOT ? OperatingSystem.UNKNOWN :
+ OperatingSystem.parse(userAgent);
+ }else{
+ this.operatingSystem = OperatingSystem.UNKNOWN;
+ this.browser = Browser.UNKNOWN;
+ }
+ }
+
+ /**
+ * 返回操作系统信息
+ *
+ * @return 操作系统信息
+ */
+ public OperatingSystem getOperatingSystem(){
+ return operatingSystem;
+ }
+
+ /**
+ * 返回浏览器信息
+ *
+ * @return 浏览器信息
+ */
+ public Browser getBrowser(){
+ return browser;
+ }
+
+ @Override
+ public String toString(){
+ return operatingSystem.toString() + '-' + browser.toString();
+ }
+
+}
diff --git a/buession-web/src/main/java/com/buession/web/utils/useragentutils/Version.java b/buession-web/src/main/java/com/buession/web/utils/useragentutils/Version.java
new file mode 100644
index 000000000..633931808
--- /dev/null
+++ b/buession-web/src/main/java/com/buession/web/utils/useragentutils/Version.java
@@ -0,0 +1,160 @@
+/*
+ * 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.
+ *
+ * =========================================================================================================
+ *
+ * This software consists of voluntary contributions made by many individuals on behalf of the
+ * Apache Software Foundation. For more information on the Apache Software Foundation, please see
+ * .
+ *
+ * +-------------------------------------------------------------------------------------------------------+
+ * | License: http://www.apache.org/licenses/LICENSE-2.0.txt |
+ * | Author: Yong.Teng |
+ * | Copyright @ 2013-2023 Buession.com Inc. |
+ * +-------------------------------------------------------------------------------------------------------+
+ */
+package com.buession.web.utils.useragentutils;
+
+import com.buession.core.utils.VersionUtils;
+
+/**
+ * 版本
+ *
+ * @author Yong.Teng
+ * @since 2.2.1
+ */
+public final class Version implements Comparable {
+
+ /**
+ * 版本
+ */
+ private final String version;
+
+ /**
+ * 主版本号
+ */
+ private final String majorVersion;
+
+ /**
+ * 次版本号
+ */
+ private final String minorVersion;
+
+ /**
+ * 构造函数
+ *
+ * @param version
+ * 版本
+ * @param majorVersion
+ * 主版本号
+ * @param minorVersion
+ * 次版本号
+ */
+ public Version(final String version, final String majorVersion, final String minorVersion){
+ this.version = version;
+ this.majorVersion = majorVersion;
+ this.minorVersion = minorVersion;
+ }
+
+ /**
+ * 返回版本
+ *
+ * @return 版本
+ */
+ public String getVersion(){
+ return version;
+ }
+
+ /**
+ * 返回主版本号
+ *
+ * @return 主版本号
+ */
+ public String getMajorVersion(){
+ return majorVersion;
+ }
+
+ /**
+ * 返回次版本号
+ *
+ * @return 次版本号
+ */
+ public String getMinorVersion(){
+ return minorVersion;
+ }
+
+ @Override
+ public int hashCode(){
+ final int prime = 31;
+ int result = 1;
+ result = prime * result
+ + ((majorVersion == null) ? 0 : majorVersion.hashCode());
+ result = prime * result
+ + ((minorVersion == null) ? 0 : minorVersion.hashCode());
+ result = prime * result + ((version == null) ? 0 : version.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj){
+ if(this == obj){
+ return true;
+ }
+
+ if(obj instanceof Version){
+ Version that = (Version) obj;
+
+ if(majorVersion == null){
+ if(that.majorVersion != null){
+ return false;
+ }
+ }else if(majorVersion.equals(that.majorVersion) == false){
+ return false;
+ }
+
+ if(minorVersion == null){
+ if(that.minorVersion != null){
+ return false;
+ }
+ }else if(minorVersion.equals(that.minorVersion) == false){
+ return false;
+ }
+
+ if(version == null){
+ if(that.version != null){
+ return false;
+ }
+ }else if(version.equals(that.version) == false){
+ return false;
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ @Override
+ public int compareTo(Version other){
+ if(other == null){
+ return 1;
+ }
+
+ return VersionUtils.compare(version, other.version);
+ }
+
+ @Override
+ public String toString(){
+ return version;
+ }
+
+}
diff --git a/buession-web/src/main/java/com/buession/web/utils/useragentutils/VersionMapping.java b/buession-web/src/main/java/com/buession/web/utils/useragentutils/VersionMapping.java
new file mode 100644
index 000000000..a89ef5115
--- /dev/null
+++ b/buession-web/src/main/java/com/buession/web/utils/useragentutils/VersionMapping.java
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ *
+ * =========================================================================================================
+ *
+ * This software consists of voluntary contributions made by many individuals on behalf of the
+ * Apache Software Foundation. For more information on the Apache Software Foundation, please see
+ * .
+ *
+ * +-------------------------------------------------------------------------------------------------------+
+ * | License: http://www.apache.org/licenses/LICENSE-2.0.txt |
+ * | Author: Yong.Teng |
+ * | Copyright @ 2013-2023 Buession.com Inc. |
+ * +-------------------------------------------------------------------------------------------------------+
+ */
+package com.buession.web.utils.useragentutils;
+
+/**
+ * @author Yong.Teng
+ * @since 2.2.1
+ */
+class VersionMapping {
+
+ private String[] patterns;
+
+ private String version;
+
+ VersionMapping(final String[] patterns, final String version){
+ this.patterns = patterns;
+ this.version = version;
+ }
+
+ public String[] getPatterns(){
+ return patterns;
+ }
+
+ public String getVersion(){
+ return version;
+ }
+
+}
diff --git a/buession-web/src/main/java/com/buession/web/utils/useragentutils/browsertypefetcher/BrowserTypeFetcher.java b/buession-web/src/main/java/com/buession/web/utils/useragentutils/browsertypefetcher/BrowserTypeFetcher.java
new file mode 100644
index 000000000..5df6b9cf9
--- /dev/null
+++ b/buession-web/src/main/java/com/buession/web/utils/useragentutils/browsertypefetcher/BrowserTypeFetcher.java
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ *
+ * =========================================================================================================
+ *
+ * This software consists of voluntary contributions made by many individuals on behalf of the
+ * Apache Software Foundation. For more information on the Apache Software Foundation, please see
+ * .
+ *
+ * +-------------------------------------------------------------------------------------------------------+
+ * | License: http://www.apache.org/licenses/LICENSE-2.0.txt |
+ * | Author: Yong.Teng |
+ * | Copyright @ 2013-2023 Buession.com Inc. |
+ * +-------------------------------------------------------------------------------------------------------+
+ */
+package com.buession.web.utils.useragentutils.browsertypefetcher;
+
+import com.buession.web.utils.useragentutils.BrowserType;
+import com.buession.web.utils.useragentutils.Fetcher;
+
+/**
+ * @author Yong.Teng
+ * @since 2.2.1
+ */
+@FunctionalInterface
+public interface BrowserTypeFetcher extends Fetcher {
+
+}
diff --git a/buession-web/src/main/java/com/buession/web/utils/useragentutils/browsertypefetcher/ContainsBrowserTypeFetcher.java b/buession-web/src/main/java/com/buession/web/utils/useragentutils/browsertypefetcher/ContainsBrowserTypeFetcher.java
new file mode 100644
index 000000000..bb609df2f
--- /dev/null
+++ b/buession-web/src/main/java/com/buession/web/utils/useragentutils/browsertypefetcher/ContainsBrowserTypeFetcher.java
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ *
+ * =========================================================================================================
+ *
+ * This software consists of voluntary contributions made by many individuals on behalf of the
+ * Apache Software Foundation. For more information on the Apache Software Foundation, please see
+ * .
+ *
+ * +-------------------------------------------------------------------------------------------------------+
+ * | License: http://www.apache.org/licenses/LICENSE-2.0.txt |
+ * | Author: Yong.Teng |
+ * | Copyright @ 2013-2023 Buession.com Inc. |
+ * +-------------------------------------------------------------------------------------------------------+
+ */
+package com.buession.web.utils.useragentutils.browsertypefetcher;
+
+import com.buession.core.utils.StringUtils;
+import com.buession.web.utils.useragentutils.BrowserType;
+
+/**
+ * @author Yong.Teng
+ * @since 2.2.1
+ */
+public class ContainsBrowserTypeFetcher implements BrowserTypeFetcher {
+
+ private final String str;
+
+ private final boolean ignoreCase;
+
+ private final BrowserType browserType;
+
+ public ContainsBrowserTypeFetcher(final String str, final BrowserType browserType){
+ this(str, true, browserType);
+ }
+
+ public ContainsBrowserTypeFetcher(final String str, final boolean ignoreCase, final BrowserType browserType){
+ this.str = str;
+ this.ignoreCase = ignoreCase;
+ this.browserType = browserType;
+ }
+
+ @Override
+ public BrowserType fetch(final String userAgent){
+ if(ignoreCase){
+ return StringUtils.containsIgnoreCase(userAgent, str) ? browserType : null;
+ }else{
+ return StringUtils.contains(userAgent, str) ? browserType : null;
+ }
+ }
+
+}
diff --git a/buession-web/src/main/java/com/buession/web/utils/useragentutils/browsertypefetcher/package-info.java b/buession-web/src/main/java/com/buession/web/utils/useragentutils/browsertypefetcher/package-info.java
new file mode 100644
index 000000000..7378ededa
--- /dev/null
+++ b/buession-web/src/main/java/com/buession/web/utils/useragentutils/browsertypefetcher/package-info.java
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ *
+ * =========================================================================================================
+ *
+ * This software consists of voluntary contributions made by many individuals on behalf of the
+ * Apache Software Foundation. For more information on the Apache Software Foundation, please see
+ * .
+ *
+ * +-------------------------------------------------------------------------------------------------------+
+ * | License: http://www.apache.org/licenses/LICENSE-2.0.txt |
+ * | Author: Yong.Teng |
+ * | Copyright @ 2013-2023 Buession.com Inc. |
+ * +-------------------------------------------------------------------------------------------------------+
+ */
+/**
+ * @author Yong.Teng
+ */
+package com.buession.web.utils.useragentutils.browsertypefetcher;
\ No newline at end of file
diff --git a/buession-web/src/main/java/com/buession/web/utils/useragentutils/devicetypefetcher/ContainsDeviceTypeFetcher.java b/buession-web/src/main/java/com/buession/web/utils/useragentutils/devicetypefetcher/ContainsDeviceTypeFetcher.java
new file mode 100644
index 000000000..a5c955545
--- /dev/null
+++ b/buession-web/src/main/java/com/buession/web/utils/useragentutils/devicetypefetcher/ContainsDeviceTypeFetcher.java
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ *
+ * =========================================================================================================
+ *
+ * This software consists of voluntary contributions made by many individuals on behalf of the
+ * Apache Software Foundation. For more information on the Apache Software Foundation, please see
+ * .
+ *
+ * +-------------------------------------------------------------------------------------------------------+
+ * | License: http://www.apache.org/licenses/LICENSE-2.0.txt |
+ * | Author: Yong.Teng |
+ * | Copyright @ 2013-2023 Buession.com Inc. |
+ * +-------------------------------------------------------------------------------------------------------+
+ */
+package com.buession.web.utils.useragentutils.devicetypefetcher;
+
+import com.buession.core.utils.StringUtils;
+import com.buession.web.utils.useragentutils.DeviceType;
+
+/**
+ * @author Yong.Teng
+ * @since 2.2.1
+ */
+public class ContainsDeviceTypeFetcher implements DeviceTypeFetcher {
+
+ private final String str;
+
+ private final boolean ignoreCase;
+
+ private final DeviceType deviceType;
+
+ public ContainsDeviceTypeFetcher(final String str, final DeviceType deviceType){
+ this(str, true, deviceType);
+ }
+
+ public ContainsDeviceTypeFetcher(final String str, final boolean ignoreCase, final DeviceType deviceType){
+ this.str = str;
+ this.ignoreCase = ignoreCase;
+ this.deviceType = deviceType;
+ }
+
+ @Override
+ public DeviceType fetch(final String userAgent){
+ if(ignoreCase){
+ return StringUtils.containsIgnoreCase(userAgent, str) ? deviceType : null;
+ }else{
+ return StringUtils.contains(userAgent, str) ? deviceType : null;
+ }
+ }
+
+}
diff --git a/buession-web/src/main/java/com/buession/web/utils/useragentutils/devicetypefetcher/DeviceTypeFetcher.java b/buession-web/src/main/java/com/buession/web/utils/useragentutils/devicetypefetcher/DeviceTypeFetcher.java
new file mode 100644
index 000000000..c56885871
--- /dev/null
+++ b/buession-web/src/main/java/com/buession/web/utils/useragentutils/devicetypefetcher/DeviceTypeFetcher.java
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ *
+ * =========================================================================================================
+ *
+ * This software consists of voluntary contributions made by many individuals on behalf of the
+ * Apache Software Foundation. For more information on the Apache Software Foundation, please see
+ * .
+ *
+ * +-------------------------------------------------------------------------------------------------------+
+ * | License: http://www.apache.org/licenses/LICENSE-2.0.txt |
+ * | Author: Yong.Teng |
+ * | Copyright @ 2013-2023 Buession.com Inc. |
+ * +-------------------------------------------------------------------------------------------------------+
+ */
+package com.buession.web.utils.useragentutils.devicetypefetcher;
+
+import com.buession.web.utils.useragentutils.DeviceType;
+import com.buession.web.utils.useragentutils.Fetcher;
+
+/**
+ * @author Yong.Teng
+ * @since 2.2.1
+ */
+@FunctionalInterface
+public interface DeviceTypeFetcher extends Fetcher {
+
+}
diff --git a/buession-web/src/main/java/com/buession/web/utils/useragentutils/devicetypefetcher/package-info.java b/buession-web/src/main/java/com/buession/web/utils/useragentutils/devicetypefetcher/package-info.java
new file mode 100644
index 000000000..8bee19a14
--- /dev/null
+++ b/buession-web/src/main/java/com/buession/web/utils/useragentutils/devicetypefetcher/package-info.java
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ *
+ * =========================================================================================================
+ *
+ * This software consists of voluntary contributions made by many individuals on behalf of the
+ * Apache Software Foundation. For more information on the Apache Software Foundation, please see
+ * .
+ *
+ * +-------------------------------------------------------------------------------------------------------+
+ * | License: http://www.apache.org/licenses/LICENSE-2.0.txt |
+ * | Author: Yong.Teng |
+ * | Copyright @ 2013-2023 Buession.com Inc. |
+ * +-------------------------------------------------------------------------------------------------------+
+ */
+/**
+ * @author Yong.Teng
+ */
+package com.buession.web.utils.useragentutils.devicetypefetcher;
\ No newline at end of file
diff --git a/buession-web/src/main/java/com/buession/web/utils/useragentutils/package-info.java b/buession-web/src/main/java/com/buession/web/utils/useragentutils/package-info.java
new file mode 100644
index 000000000..2c9f75f8a
--- /dev/null
+++ b/buession-web/src/main/java/com/buession/web/utils/useragentutils/package-info.java
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ *
+ * =========================================================================================================
+ *
+ * This software consists of voluntary contributions made by many individuals on behalf of the
+ * Apache Software Foundation. For more information on the Apache Software Foundation, please see
+ * .
+ *
+ * +-------------------------------------------------------------------------------------------------------+
+ * | License: http://www.apache.org/licenses/LICENSE-2.0.txt |
+ * | Author: Yong.Teng |
+ * | Copyright @ 2013-2023 Buession.com Inc. |
+ * +-------------------------------------------------------------------------------------------------------+
+ */
+/**
+ * @author Yong.Teng
+ */
+package com.buession.web.utils.useragentutils;
\ No newline at end of file
diff --git a/buession-web/src/main/java/com/buession/web/utils/useragentutils/versionfetcher/MapVersionFetcher.java b/buession-web/src/main/java/com/buession/web/utils/useragentutils/versionfetcher/MapVersionFetcher.java
new file mode 100644
index 000000000..715f84818
--- /dev/null
+++ b/buession-web/src/main/java/com/buession/web/utils/useragentutils/versionfetcher/MapVersionFetcher.java
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ *
+ * =========================================================================================================
+ *
+ * This software consists of voluntary contributions made by many individuals on behalf of the
+ * Apache Software Foundation. For more information on the Apache Software Foundation, please see
+ * .
+ *
+ * +-------------------------------------------------------------------------------------------------------+
+ * | License: http://www.apache.org/licenses/LICENSE-2.0.txt |
+ * | Author: Yong.Teng |
+ * | Copyright @ 2013-2023 Buession.com Inc. |
+ * +-------------------------------------------------------------------------------------------------------+
+ */
+package com.buession.web.utils.useragentutils.versionfetcher;
+
+import com.buession.web.utils.useragentutils.Version;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author Yong.Teng
+ * @since 2.2.1
+ */
+public class MapVersionFetcher extends PatternVersionFetcher {
+
+ private final Map versions;
+
+ public MapVersionFetcher(final String regex, final Map versions){
+ this(Pattern.compile(regex), versions);
+ }
+
+ public MapVersionFetcher(final Pattern pattern, final Map versions){
+ super(pattern);
+ this.versions = Collections.unmodifiableMap(versions);
+ }
+
+ @Override
+ protected Version createVersion(Matcher matcher){
+ return versions.get(matcher.group(1));
+ }
+
+}
diff --git a/buession-web/src/main/java/com/buession/web/utils/useragentutils/versionfetcher/PatternVersionFetcher.java b/buession-web/src/main/java/com/buession/web/utils/useragentutils/versionfetcher/PatternVersionFetcher.java
new file mode 100644
index 000000000..92bb378a6
--- /dev/null
+++ b/buession-web/src/main/java/com/buession/web/utils/useragentutils/versionfetcher/PatternVersionFetcher.java
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ *
+ * =========================================================================================================
+ *
+ * This software consists of voluntary contributions made by many individuals on behalf of the
+ * Apache Software Foundation. For more information on the Apache Software Foundation, please see
+ * .
+ *
+ * +-------------------------------------------------------------------------------------------------------+
+ * | License: http://www.apache.org/licenses/LICENSE-2.0.txt |
+ * | Author: Yong.Teng |
+ * | Copyright @ 2013-2023 Buession.com Inc. |
+ * +-------------------------------------------------------------------------------------------------------+
+ */
+package com.buession.web.utils.useragentutils.versionfetcher;
+
+import com.buession.web.utils.useragentutils.Version;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author Yong.Teng
+ * @since 2.2.1
+ */
+public class PatternVersionFetcher implements VersionFetcher {
+
+ private final Pattern pattern;
+
+ public PatternVersionFetcher(final String regex){
+ this(Pattern.compile(regex, Pattern.CASE_INSENSITIVE));
+ }
+
+ public PatternVersionFetcher(final Pattern pattern){
+ this.pattern = pattern;
+ }
+
+ @Override
+ public final Version fetch(String userAgent){
+ Matcher matcher = pattern.matcher(userAgent);
+ return matcher.find() ? createVersion(matcher) : null;
+ }
+
+ protected Version createVersion(Matcher matcher){
+ String fullVersionString = matcher.group(1);
+ String majorVersion = matcher.group(2);
+ String minorVersion = "0";
+
+ if(matcher.groupCount() > 2){ // usually but not always there is a minor version
+ minorVersion = matcher.group(3);
+ }
+
+ return new Version(fullVersionString, majorVersion, minorVersion);
+ }
+
+}
diff --git a/buession-web/src/main/java/com/buession/web/utils/useragentutils/versionfetcher/SequentialVersionFetcher.java b/buession-web/src/main/java/com/buession/web/utils/useragentutils/versionfetcher/SequentialVersionFetcher.java
new file mode 100644
index 000000000..685f032bd
--- /dev/null
+++ b/buession-web/src/main/java/com/buession/web/utils/useragentutils/versionfetcher/SequentialVersionFetcher.java
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ *
+ * =========================================================================================================
+ *
+ * This software consists of voluntary contributions made by many individuals on behalf of the
+ * Apache Software Foundation. For more information on the Apache Software Foundation, please see
+ * .
+ *
+ * +-------------------------------------------------------------------------------------------------------+
+ * | License: http://www.apache.org/licenses/LICENSE-2.0.txt |
+ * | Author: Yong.Teng |
+ * | Copyright @ 2013-2023 Buession.com Inc. |
+ * +-------------------------------------------------------------------------------------------------------+
+ */
+package com.buession.web.utils.useragentutils.versionfetcher;
+
+import com.buession.web.utils.useragentutils.Version;
+
+/**
+ * @author Yong.Teng
+ * @since 2.2.1
+ */
+public class SequentialVersionFetcher implements VersionFetcher {
+
+ private final VersionFetcher[] fetchers;
+
+ public SequentialVersionFetcher(VersionFetcher first, VersionFetcher... others){
+ fetchers = new VersionFetcher[others.length + 1];
+ fetchers[0] = first;
+ for(int i = 0; i < others.length; i++){
+ fetchers[i + 1] = others[i];
+ }
+ }
+
+ @Override
+ public Version fetch(final String str){
+ Version version;
+
+ for(VersionFetcher fetcher : fetchers){
+ version = fetcher.fetch(str);
+ if(version != null){
+ return version;
+ }
+ }
+
+ return null;
+ }
+
+}
diff --git a/buession-web/src/main/java/com/buession/web/utils/useragentutils/versionfetcher/VersionFetcher.java b/buession-web/src/main/java/com/buession/web/utils/useragentutils/versionfetcher/VersionFetcher.java
new file mode 100644
index 000000000..46d200586
--- /dev/null
+++ b/buession-web/src/main/java/com/buession/web/utils/useragentutils/versionfetcher/VersionFetcher.java
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ *
+ * =========================================================================================================
+ *
+ * This software consists of voluntary contributions made by many individuals on behalf of the
+ * Apache Software Foundation. For more information on the Apache Software Foundation, please see
+ * .
+ *
+ * +-------------------------------------------------------------------------------------------------------+
+ * | License: http://www.apache.org/licenses/LICENSE-2.0.txt |
+ * | Author: Yong.Teng |
+ * | Copyright @ 2013-2023 Buession.com Inc. |
+ * +-------------------------------------------------------------------------------------------------------+
+ */
+package com.buession.web.utils.useragentutils.versionfetcher;
+
+import com.buession.web.utils.useragentutils.Fetcher;
+import com.buession.web.utils.useragentutils.Version;
+
+/**
+ * @author Yong.Teng
+ * @since 2.2.1
+ */
+@FunctionalInterface
+public interface VersionFetcher extends Fetcher {
+
+}
diff --git a/buession-web/src/main/java/com/buession/web/utils/useragentutils/versionfetcher/package-info.java b/buession-web/src/main/java/com/buession/web/utils/useragentutils/versionfetcher/package-info.java
new file mode 100644
index 000000000..30d68f8fa
--- /dev/null
+++ b/buession-web/src/main/java/com/buession/web/utils/useragentutils/versionfetcher/package-info.java
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ *
+ * =========================================================================================================
+ *
+ * This software consists of voluntary contributions made by many individuals on behalf of the
+ * Apache Software Foundation. For more information on the Apache Software Foundation, please see
+ * .
+ *
+ * +-------------------------------------------------------------------------------------------------------+
+ * | License: http://www.apache.org/licenses/LICENSE-2.0.txt |
+ * | Author: Yong.Teng |
+ * | Copyright @ 2013-2023 Buession.com Inc. |
+ * +-------------------------------------------------------------------------------------------------------+
+ */
+/**
+ * @author Yong.Teng
+ */
+package com.buession.web.utils.useragentutils.versionfetcher;
\ No newline at end of file
diff --git a/buession-web/src/test/java/com/buession/web/utils/useragentutils/BrowserTest.java b/buession-web/src/test/java/com/buession/web/utils/useragentutils/BrowserTest.java
new file mode 100644
index 000000000..e5a9858fa
--- /dev/null
+++ b/buession-web/src/test/java/com/buession/web/utils/useragentutils/BrowserTest.java
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ *
+ * =========================================================================================================
+ *
+ * This software consists of voluntary contributions made by many individuals on behalf of the
+ * Apache Software Foundation. For more information on the Apache Software Foundation, please see
+ * .
+ *
+ * +-------------------------------------------------------------------------------------------------------+
+ * | License: http://www.apache.org/licenses/LICENSE-2.0.txt |
+ * | Author: Yong.Teng |
+ * | Copyright @ 2013-2023 Buession.com Inc. |
+ * +-------------------------------------------------------------------------------------------------------+
+ */
+package com.buession.web.utils.useragentutils;
+
+import com.buession.core.utils.StringUtils;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.LinkedHashSet;
+import java.util.stream.Collectors;
+
+/**
+ * @author Yong.Teng
+ * @since 2.2.1
+ */
+public class BrowserTest {
+
+ @Test
+ public void parse(){
+ Browser browser = Browser.parse(
+ "Mozilla/5.0 (Linux; Android 11; V2054A Build/RP1A.200720.012; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/107.0.5304.141 Mobile Safari/537.36 XWEB/5023 MMWEBSDK/20230202 MMWEBID/2072 MicroMessenger/8.0.33.2320(0x28002151) WeChat/arm64 Weixin NetType/5G Language/zh_CN ABI/arm64");
+ System.out.println(browser + " " + browser.getBrowserType());
+ }
+
+ @Test
+ public void toEnum(){
+ for(Browser browser : Browser.values()){
+ System.out.println(browser.name() + "(\"" + browser.getName() + "\"),");
+ System.out.println("");
+ }
+ }
+
+ @Test
+ public void join(){
+ System.out.println("'" +
+ StringUtils.join(Arrays.stream(Browser.values()).map(Enum::name).toArray(), "', '") + "'");
+ }
+
+}
diff --git a/buession-web/src/test/java/com/buession/web/utils/useragentutils/OperatingSystemTest.java b/buession-web/src/test/java/com/buession/web/utils/useragentutils/OperatingSystemTest.java
new file mode 100644
index 000000000..f65ec054e
--- /dev/null
+++ b/buession-web/src/test/java/com/buession/web/utils/useragentutils/OperatingSystemTest.java
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ *
+ * =========================================================================================================
+ *
+ * This software consists of voluntary contributions made by many individuals on behalf of the
+ * Apache Software Foundation. For more information on the Apache Software Foundation, please see
+ * .
+ *
+ * +-------------------------------------------------------------------------------------------------------+
+ * | License: http://www.apache.org/licenses/LICENSE-2.0.txt |
+ * | Author: Yong.Teng |
+ * | Copyright @ 2013-2023 Buession.com Inc. |
+ * +-------------------------------------------------------------------------------------------------------+
+ */
+package com.buession.web.utils.useragentutils;
+
+import com.buession.core.utils.StringUtils;
+import org.junit.Test;
+
+import java.util.Arrays;
+
+/**
+ * @author Yong.Teng
+ * @since 2.2.1
+ */
+public class OperatingSystemTest {
+
+ @Test
+ public void parse(){
+ OperatingSystem operatingSystem = OperatingSystem.parse(
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/111.0");
+ System.out.println(operatingSystem + " " + operatingSystem.getDeviceType());
+ }
+
+ @Test
+ public void toEnum(){
+ for(OperatingSystem operatingSystem : OperatingSystem.values()){
+ System.out.println(operatingSystem.name() + "(\"" + operatingSystem.getName() + "\"),");
+ System.out.println("");
+ }
+ }
+
+ @Test
+ public void join(){
+ System.out.println("'" +
+ StringUtils.join(Arrays.stream(OperatingSystem.values()).map(Enum::name).toArray(), "', '") + "'");
+ }
+
+}