Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
guns-vip
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
chenjunxiong
guns-vip
Commits
7f4f3d7c
Commit
7f4f3d7c
authored
May 16, 2019
by
fengshuonan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
更新邮件和短信发送
parent
554f4d22
Hide whitespace changes
Inline
Side-by-side
Showing
43 changed files
with
4425 additions
and
0 deletions
+4425
-0
guns-base-email/pom.xml
+38
-0
guns-base-email/src/main/java/cn/stylefeng/guns/email/config/ServiceAutoConfiguration.java
+22
-0
guns-base-email/src/main/java/cn/stylefeng/guns/email/core/enums/MailSendResultEnum.java
+42
-0
guns-base-email/src/main/java/cn/stylefeng/guns/email/core/exception/MailException.java
+36
-0
guns-base-email/src/main/java/cn/stylefeng/guns/email/core/mail/MailManager.java
+20
-0
guns-base-email/src/main/java/cn/stylefeng/guns/email/core/mail/service/JavaMailManager.java
+69
-0
guns-base-email/src/main/java/cn/stylefeng/guns/email/core/model/SendMailParam.java
+28
-0
guns-base-email/src/main/java/cn/stylefeng/guns/email/provider/MailServiceApi.java
+20
-0
guns-base-email/src/main/java/cn/stylefeng/guns/email/provider/MailServiceProvider.java
+30
-0
guns-base-email/src/main/resources/META-INF/spring.factories
+3
-0
guns-base-sms/pom.xml
+45
-0
guns-base-sms/src/main/java/cn/stylefeng/guns/sms/config/ServiceAutoConfiguration.java
+41
-0
guns-base-sms/src/main/java/cn/stylefeng/guns/sms/config/SmsAutoConfiguration.java
+54
-0
guns-base-sms/src/main/java/cn/stylefeng/guns/sms/config/properties/AliyunSmsProperties.java
+39
-0
guns-base-sms/src/main/java/cn/stylefeng/guns/sms/core/cache/MultiSignManager.java
+21
-0
guns-base-sms/src/main/java/cn/stylefeng/guns/sms/core/cache/impl/MapSignManager.java
+61
-0
guns-base-sms/src/main/java/cn/stylefeng/guns/sms/core/db/SmsInfoInitizlizer.java
+41
-0
guns-base-sms/src/main/java/cn/stylefeng/guns/sms/core/enums/MessageType.java
+39
-0
guns-base-sms/src/main/java/cn/stylefeng/guns/sms/core/enums/SmsResultEnum.java
+57
-0
guns-base-sms/src/main/java/cn/stylefeng/guns/sms/core/enums/SmsSendSource.java
+43
-0
guns-base-sms/src/main/java/cn/stylefeng/guns/sms/core/enums/SmsSendStatus.java
+43
-0
guns-base-sms/src/main/java/cn/stylefeng/guns/sms/core/enums/SmsVerifyResult.java
+43
-0
guns-base-sms/src/main/java/cn/stylefeng/guns/sms/core/exception/SmsException.java
+36
-0
guns-base-sms/src/main/java/cn/stylefeng/guns/sms/core/sms/SmsManager.java
+39
-0
guns-base-sms/src/main/java/cn/stylefeng/guns/sms/core/sms/service/AliyunSmsManager.java
+245
-0
guns-base-sms/src/main/java/cn/stylefeng/guns/sms/modular/entity/SmsInfo.java
+172
-0
guns-base-sms/src/main/java/cn/stylefeng/guns/sms/modular/mapper/SmsInfoMapper.java
+16
-0
guns-base-sms/src/main/java/cn/stylefeng/guns/sms/modular/mapper/mapping/SmsInfoMapper.xml
+24
-0
guns-base-sms/src/main/java/cn/stylefeng/guns/sms/modular/model/SendMessageParam.java
+43
-0
guns-base-sms/src/main/java/cn/stylefeng/guns/sms/modular/model/SmsSendRecord.java
+53
-0
guns-base-sms/src/main/java/cn/stylefeng/guns/sms/modular/model/VerifySMSParam.java
+35
-0
guns-base-sms/src/main/java/cn/stylefeng/guns/sms/modular/provider/SmsServiceApi.java
+47
-0
guns-base-sms/src/main/java/cn/stylefeng/guns/sms/modular/provider/SmsServiceProvider.java
+97
-0
guns-base-sms/src/main/java/cn/stylefeng/guns/sms/modular/service/SmsInfoService.java
+152
-0
guns-base-sms/src/main/java/org/json/JSON.java
+116
-0
guns-base-sms/src/main/java/org/json/JSONArray.java
+622
-0
guns-base-sms/src/main/java/org/json/JSONException.java
+49
-0
guns-base-sms/src/main/java/org/json/JSONObject.java
+775
-0
guns-base-sms/src/main/java/org/json/JSONStringer.java
+435
-0
guns-base-sms/src/main/java/org/json/JSONTokener.java
+614
-0
guns-base-sms/src/main/resources/META-INF/spring.factories
+4
-0
guns-vip-main/pom.xml
+14
-0
pom.xml
+2
-0
No files found.
guns-base-email/pom.xml
0 → 100644
View file @
7f4f3d7c
<?xml version="1.0" encoding="UTF-8"?>
<project
xmlns=
"http://maven.apache.org/POM/4.0.0"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
>
<modelVersion>
4.0.0
</modelVersion>
<parent>
<groupId>
cn.stylefeng
</groupId>
<artifactId>
guns-vip
</artifactId>
<version>
1.0.0
</version>
<relativePath>
../pom.xml
</relativePath>
</parent>
<artifactId>
guns-base-email
</artifactId>
<packaging>
jar
</packaging>
<dependencies>
<!--基础组件-->
<dependency>
<groupId>
cn.stylefeng
</groupId>
<artifactId>
guns-base
</artifactId>
<version>
1.0.0
</version>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-mail
</artifactId>
</dependency>
</dependencies>
<build>
<finalName>
${project.artifactId}
</finalName>
</build>
</project>
guns-base-email/src/main/java/cn/stylefeng/guns/email/config/ServiceAutoConfiguration.java
0 → 100644
View file @
7f4f3d7c
package
cn
.
stylefeng
.
guns
.
email
.
config
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
cn.stylefeng.guns.email.provider.MailServiceProvider
;
/**
* 邮件服务的配置
*
* @author fengshuonan
* @Date 2018/7/6 下午3:24
*/
@Configuration
public
class
ServiceAutoConfiguration
{
@Bean
public
MailServiceProvider
mailServiceProvider
()
{
return
new
MailServiceProvider
();
}
}
\ No newline at end of file
guns-base-email/src/main/java/cn/stylefeng/guns/email/core/enums/MailSendResultEnum.java
0 → 100644
View file @
7f4f3d7c
package
cn
.
stylefeng
.
guns
.
email
.
core
.
enums
;
import
cn.stylefeng.roses.kernel.model.exception.AbstractBaseExceptionEnum
;
/**
* 邮件发送失败的异常枚举
*
* @author stylefeng
* @Date 2018年07月08日18:39:47
*/
public
enum
MailSendResultEnum
implements
AbstractBaseExceptionEnum
{
MAIL_SEND_ERROR
(
500
,
"邮件发送失败"
);
MailSendResultEnum
(
int
code
,
String
message
)
{
this
.
code
=
code
;
this
.
message
=
message
;
}
private
Integer
code
;
private
String
message
;
@Override
public
Integer
getCode
()
{
return
code
;
}
public
void
setCode
(
Integer
code
)
{
this
.
code
=
code
;
}
@Override
public
String
getMessage
()
{
return
message
;
}
public
void
setMessage
(
String
message
)
{
this
.
message
=
message
;
}
}
guns-base-email/src/main/java/cn/stylefeng/guns/email/core/exception/MailException.java
0 → 100644
View file @
7f4f3d7c
package
cn
.
stylefeng
.
guns
.
email
.
core
.
exception
;
/**
* 邮件发送异常
*
* @author fengshuonan
* @date 2018-07-06-下午3:00
*/
public
class
MailException
extends
RuntimeException
{
private
String
code
;
private
String
errorMessage
;
public
MailException
(
String
code
,
String
errorMessage
)
{
super
(
errorMessage
);
this
.
code
=
code
;
this
.
errorMessage
=
errorMessage
;
}
public
String
getCode
()
{
return
code
;
}
public
void
setCode
(
String
code
)
{
this
.
code
=
code
;
}
public
String
getErrorMessage
()
{
return
errorMessage
;
}
public
void
setErrorMessage
(
String
errorMessage
)
{
this
.
errorMessage
=
errorMessage
;
}
}
guns-base-email/src/main/java/cn/stylefeng/guns/email/core/mail/MailManager.java
0 → 100644
View file @
7f4f3d7c
package
cn
.
stylefeng
.
guns
.
email
.
core
.
mail
;
import
cn.stylefeng.guns.email.core.model.SendMailParam
;
/**
* 邮件收发统一接口
*
* @author fengshuonan
* @date 2018-07-08-下午3:26
*/
public
interface
MailManager
{
/**
* 发送普通邮件
*
* @author fengshuonan
* @Date 2018/7/8 下午3:34
*/
void
sendMail
(
SendMailParam
sendMailParam
);
}
guns-base-email/src/main/java/cn/stylefeng/guns/email/core/mail/service/JavaMailManager.java
0 → 100644
View file @
7f4f3d7c
package
cn
.
stylefeng
.
guns
.
email
.
core
.
mail
.
service
;
import
cn.stylefeng.guns.email.core.enums.MailSendResultEnum
;
import
cn.stylefeng.guns.email.core.mail.MailManager
;
import
cn.stylefeng.guns.email.core.model.SendMailParam
;
import
cn.stylefeng.roses.kernel.model.exception.RequestEmptyException
;
import
cn.stylefeng.roses.kernel.model.exception.ServiceException
;
import
cn.stylefeng.roses.kernel.model.util.ValidateUtil
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.mail.javamail.JavaMailSender
;
import
org.springframework.mail.javamail.MimeMessageHelper
;
import
org.springframework.stereotype.Service
;
import
javax.mail.MessagingException
;
import
javax.mail.internet.MimeMessage
;
/**
* java默认的邮件发送方式实现
*
* @author fengshuonan
* @date 2018-07-08-下午3:34
*/
@Service
@Slf4j
public
class
JavaMailManager
implements
MailManager
{
@Autowired
private
JavaMailSender
javaMailSender
;
@Value
(
"${mail.from}"
)
private
String
from
;
@Override
public
void
sendMail
(
SendMailParam
sendMailParam
)
{
//校验发送邮件的参数
assertSendMailParams
(
sendMailParam
);
log
.
info
(
"参数校验成功。。。。"
);
//spring发送邮件
try
{
MimeMessage
mimeMessage
=
javaMailSender
.
createMimeMessage
();
MimeMessageHelper
mimeMessageHelper
=
new
MimeMessageHelper
(
mimeMessage
,
true
);
mimeMessageHelper
.
setFrom
(
from
);
mimeMessageHelper
.
setTo
(
sendMailParam
.
getTo
());
mimeMessageHelper
.
setSubject
(
sendMailParam
.
getTitle
());
mimeMessageHelper
.
setText
(
sendMailParam
.
getContent
(),
true
);
javaMailSender
.
send
(
mimeMessage
);
}
catch
(
MessagingException
e
)
{
log
.
error
(
"发送邮件异常"
,
e
);
throw
new
ServiceException
(
MailSendResultEnum
.
MAIL_SEND_ERROR
);
}
}
/**
* 校验发送邮件的请求参数
*
* @author fengshuonan
* @Date 2018/7/8 下午6:41
*/
private
void
assertSendMailParams
(
SendMailParam
sendMailParam
)
{
if
(
sendMailParam
==
null
||
ValidateUtil
.
isOneEmpty
(
sendMailParam
.
getTo
(),
sendMailParam
.
getTitle
(),
sendMailParam
.
getContent
()))
{
throw
new
RequestEmptyException
();
}
}
}
guns-base-email/src/main/java/cn/stylefeng/guns/email/core/model/SendMailParam.java
0 → 100644
View file @
7f4f3d7c
package
cn
.
stylefeng
.
guns
.
email
.
core
.
model
;
import
lombok.Data
;
/**
* 发送邮件的请求参数
*
* @author fengshuonan
* @date 2018-07-05 21:19
*/
@Data
public
class
SendMailParam
{
/**
* 发送给某人的邮箱
*/
private
String
to
;
/**
* 邮件标题
*/
private
String
title
;
/**
* 邮件内容(经过base64编码后的)
*/
private
String
content
;
}
guns-base-email/src/main/java/cn/stylefeng/guns/email/provider/MailServiceApi.java
0 → 100644
View file @
7f4f3d7c
package
cn
.
stylefeng
.
guns
.
email
.
provider
;
import
cn.stylefeng.guns.email.core.model.SendMailParam
;
/**
* 邮件发送的api
*
* @author fengshuonan
* @date 2018-07-08-下午3:47
*/
public
interface
MailServiceApi
{
/**
* 发送邮件
*
* @author fengshuonan
* @Date 2018/7/8 下午6:28
*/
void
sendMail
(
SendMailParam
sendMailParam
);
}
guns-base-email/src/main/java/cn/stylefeng/guns/email/provider/MailServiceProvider.java
0 → 100644
View file @
7f4f3d7c
package
cn
.
stylefeng
.
guns
.
email
.
provider
;
import
cn.stylefeng.guns.email.core.mail.MailManager
;
import
cn.stylefeng.guns.email.core.model.SendMailParam
;
import
com.alibaba.fastjson.JSONObject
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Autowired
;
/**
* 短信通知接口
*
* @author stylefeng
* @Date 2018/7/5 21:05
*/
public
class
MailServiceProvider
implements
MailServiceApi
{
private
static
Logger
logger
=
LoggerFactory
.
getLogger
(
MailServiceProvider
.
class
);
@Autowired
private
MailManager
mailManager
;
@Override
public
void
sendMail
(
SendMailParam
sendMailParam
)
{
logger
.
info
(
"email调用入参:"
+
JSONObject
.
toJSON
(
sendMailParam
).
toString
());
mailManager
.
sendMail
(
sendMailParam
);
}
}
guns-base-email/src/main/resources/META-INF/spring.factories
0 → 100644
View file @
7f4f3d7c
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.stylefeng.guns.email.config.ServiceAutoConfiguration
\ No newline at end of file
guns-base-sms/pom.xml
0 → 100644
View file @
7f4f3d7c
<?xml version="1.0" encoding="UTF-8"?>
<project
xmlns=
"http://maven.apache.org/POM/4.0.0"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
>
<modelVersion>
4.0.0
</modelVersion>
<parent>
<groupId>
cn.stylefeng
</groupId>
<artifactId>
guns-vip
</artifactId>
<version>
1.0.0
</version>
<relativePath>
../pom.xml
</relativePath>
</parent>
<artifactId>
guns-base-sms
</artifactId>
<packaging>
jar
</packaging>
<dependencies>
<!--基础组件-->
<dependency>
<groupId>
cn.stylefeng
</groupId>
<artifactId>
guns-base
</artifactId>
<version>
1.0.0
</version>
</dependency>
<!--短信发送的sdk-->
<dependency>
<groupId>
com.aliyun
</groupId>
<artifactId>
aliyun-java-sdk-core
</artifactId>
<version>
3.7.1
</version>
</dependency>
<dependency>
<groupId>
com.aliyun
</groupId>
<artifactId>
aliyun-java-sdk-dysmsapi
</artifactId>
<version>
1.1.0
</version>
</dependency>
</dependencies>
<build>
<finalName>
${project.artifactId}
</finalName>
</build>
</project>
guns-base-sms/src/main/java/cn/stylefeng/guns/sms/config/ServiceAutoConfiguration.java
0 → 100644
View file @
7f4f3d7c
package
cn
.
stylefeng
.
guns
.
sms
.
config
;
import
cn.stylefeng.guns.sms.core.db.SmsInfoInitizlizer
;
import
cn.stylefeng.guns.sms.core.sms.SmsManager
;
import
cn.stylefeng.guns.sms.core.sms.service.AliyunSmsManager
;
import
cn.stylefeng.guns.sms.modular.provider.SmsServiceProvider
;
import
cn.stylefeng.guns.sms.modular.service.SmsInfoService
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
/**
* 短信服务的配置
*
* @author fengshuonan
* @Date 2018/7/6 下午3:24
*/
@Configuration
public
class
ServiceAutoConfiguration
{
@Bean
public
SmsServiceProvider
smsServiceProvider
()
{
return
new
SmsServiceProvider
();
}
@Bean
public
SmsInfoService
smsInfoService
()
{
return
new
SmsInfoService
();
}
@Bean
public
SmsManager
smsManager
()
{
return
new
AliyunSmsManager
();
}
@Bean
public
SmsInfoInitizlizer
smsInfoInitizlizer
()
{
return
new
SmsInfoInitizlizer
();
}
}
\ No newline at end of file
guns-base-sms/src/main/java/cn/stylefeng/guns/sms/config/SmsAutoConfiguration.java
0 → 100644
View file @
7f4f3d7c
package
cn
.
stylefeng
.
guns
.
sms
.
config
;
import
cn.stylefeng.guns.sms.config.properties.AliyunSmsProperties
;
import
cn.stylefeng.guns.sms.core.cache.impl.MapSignManager
;
import
cn.stylefeng.guns.sms.core.sms.service.AliyunSmsManager
;
import
org.springframework.boot.context.properties.ConfigurationProperties
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
/**
* aliyun短信发送的配置
*
* @author fengshuonan
* @Date 2018/7/6 下午3:24
*/
@Configuration
public
class
SmsAutoConfiguration
{
/**
* 阿里云短信发送的配置
*
* @author fengshuonan
* @Date 2018/7/6 下午3:24
*/
@Bean
@ConfigurationProperties
(
prefix
=
"aliyun.sms"
)
public
AliyunSmsProperties
aliyunSmsProperties
()
{
return
new
AliyunSmsProperties
();
}
/**
* 短信发送管理器
*
* @author fengshuonan
* @Date 2018/9/21 上午10:07
*/
@Bean
public
AliyunSmsManager
aliyunSmsManager
()
{
return
new
AliyunSmsManager
();
}
/**
* 缓存的管理
*
* @author fengshuonan
* @Date 2018/9/21 上午10:59
*/
@Bean
public
MapSignManager
mapSignManager
()
{
return
new
MapSignManager
();
}
}
\ No newline at end of file
guns-base-sms/src/main/java/cn/stylefeng/guns/sms/config/properties/AliyunSmsProperties.java
0 → 100644
View file @
7f4f3d7c
package
cn
.
stylefeng
.
guns
.
sms
.
config
.
properties
;
import
lombok.Data
;
/**
* oss相关配置
*
* @author fengshuonan
* @date 2018-06-27-下午1:20
*/
@Data
public
class
AliyunSmsProperties
{
/**
* accessKeyId
*/
private
String
accessKeyId
;
/**
* accessKeySecret
*/
private
String
accessKeySecret
;
/**
* 签名名称
*/
private
String
signName
;
/**
* 登录验证码的模板
*/
private
String
loginTemplateCode
;
/**
* 短信失效时间(分钟)
*/
private
Integer
invalidateMinutes
=
2
;
}
guns-base-sms/src/main/java/cn/stylefeng/guns/sms/core/cache/MultiSignManager.java
0 → 100644
View file @
7f4f3d7c
package
cn
.
stylefeng
.
guns
.
sms
.
core
.
cache
;
/**
* 多个签名的缓存管理
*
* @author fengshuonan
* @date 2018-09-21-上午10:47
*/
public
interface
MultiSignManager
{
/**
* 获取签名
*
* @param phone 电话
* @param signName 发送短信用的签名,是一个以逗号隔开的字符串
* @author fengshuonan
* @Date 2018/9/21 上午10:51
*/
String
getSign
(
String
phone
,
String
signName
);
}
guns-base-sms/src/main/java/cn/stylefeng/guns/sms/core/cache/impl/MapSignManager.java
0 → 100644
View file @
7f4f3d7c
package
cn
.
stylefeng
.
guns
.
sms
.
core
.
cache
.
impl
;
import
cn.stylefeng.guns.sms.core.cache.MultiSignManager
;
import
lombok.extern.slf4j.Slf4j
;
import
java.util.Map
;
import
java.util.concurrent.ConcurrentHashMap
;
/**
* 使用map缓存的实现
*
* @author fengshuonan
* @date 2018-09-21-上午10:49
*/
@Slf4j
public
class
MapSignManager
implements
MultiSignManager
{
private
static
final
Long
EXPIRED_TIME
=
86400L
;
private
Map
<
String
,
String
>
cacheMap
=
new
ConcurrentHashMap
<>();
@Override
public
String
getSign
(
String
phone
,
String
signName
)
{
clearMap
();
String
[]
signNames
=
signName
.
split
(
","
);
//获取上次发送的时候用的哪个签名,这次换一个
Object
lastSignName
=
cacheMap
.
get
(
phone
);
if
(
lastSignName
==
null
)
{
cacheMap
.
put
(
phone
,
signNames
[
0
]);
log
.
info
(
"发送短信,签名为:"
+
signNames
[
0
]
+
",电话为:"
+
phone
);
return
signNames
[
0
];
}
else
{
for
(
String
name
:
signNames
)
{
if
(!
name
.
equals
(
lastSignName
))
{
cacheMap
.
put
(
phone
,
name
);
log
.
info
(
"发送短信,签名为:"
+
name
+
",电话为:"
+
phone
);
return
name
;
}
}
cacheMap
.
put
(
phone
,
signNames
[
0
]);
log
.
info
(
"发送短信,签名为:"
+
signNames
[
0
]
+
",电话为:"
+
phone
);
return
signNames
[
0
];
}
}
/**
* 每隔一段时间清除下map
*
* @author fengshuonan
* @Date 2018/9/21 上午10:57
*/
private
void
clearMap
()
{
if
(
cacheMap
.
size
()
>=
1000
)
{
cacheMap
.
clear
();
}
}
}
guns-base-sms/src/main/java/cn/stylefeng/guns/sms/core/db/SmsInfoInitizlizer.java
0 → 100644
View file @
7f4f3d7c
package
cn
.
stylefeng
.
guns
.
sms
.
core
.
db
;
import
cn.stylefeng.guns.sms.modular.entity.SmsInfo
;
import
cn.stylefeng.roses.core.db.DbInitializer
;
/**
* 短信发送表的初始化程序
*
* @author fengshuonan
* @date 2018-07-30-上午9:29
*/
public
class
SmsInfoInitizlizer
extends
DbInitializer
{
@Override
public
String
getTableInitSql
()
{
return
"CREATE TABLE `sms_info` (\n"
+
" `ID` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',\n"
+
" `PHONE_NUMBERS` varchar(200) COLLATE utf8_bin NOT NULL COMMENT '手机号',\n"
+
" `VALIDATE_CODE` varchar(255) COLLATE utf8_bin DEFAULT NULL COMMENT '短信验证码',\n"
+
" `TEMPLATE_CODE` varchar(255) COLLATE utf8_bin DEFAULT NULL COMMENT '短信模板ID',\n"
+
" `BIZID` varchar(255) COLLATE utf8_bin DEFAULT NULL COMMENT '回执ID,可根据该ID查询具体的发送状态',\n"
+
" `STATUS` smallint(3) NOT NULL COMMENT '0=未发送,1=发送成功,2=发送失败,3=失效',\n"
+
" `SOURCE` smallint(3) NOT NULL COMMENT '0=app,1=pc,2=其它',\n"
+
" `INVALID_TIME` timestamp NULL DEFAULT NULL COMMENT '失效时间',\n"
+
" `MODIFY_TIME` timestamp NULL DEFAULT NULL COMMENT '修改时间',\n"
+
" `CREATE_TIME` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n"
+
" PRIMARY KEY (`ID`)\n"
+
") ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='短信信息发送表'"
;
}
@Override
public
String
getTableName
()
{
return
"sms_info"
;
}
@Override
public
Class
<?>
getEntityClass
()
{
return
SmsInfo
.
class
;
}
}
guns-base-sms/src/main/java/cn/stylefeng/guns/sms/core/enums/MessageType.java
0 → 100644
View file @
7f4f3d7c
package
cn
.
stylefeng
.
guns
.
sms
.
core
.
enums
;
/**
* 消息类型
*
* @author stylefeng
* @Date 2018年5月6日 12:30:48
*/
public
enum
MessageType
{
SMS
(
1
,
"验证类消息"
),
MESSAGE
(
2
,
"纯发送消息"
);
private
Integer
code
;
private
String
desc
;
MessageType
(
Integer
code
,
String
desc
)
{
this
.
code
=
code
;
this
.
desc
=
desc
;
}
public
Integer
getCode
()
{
return
code
;
}
public
void
setCode
(
Integer
code
)
{
this
.
code
=
code
;
}
public
String
getDesc
()
{
return
desc
;
}
public
void
setDesc
(
String
desc
)
{
this
.
desc
=
desc
;
}
}
guns-base-sms/src/main/java/cn/stylefeng/guns/sms/core/enums/SmsResultEnum.java
0 → 100644
View file @
7f4f3d7c
package
cn
.
stylefeng
.
guns
.
sms
.
core
.
enums
;
/**
* core模块的异常集合
*
* @author stylefeng
* @Date 2018/1/4 22:40
*/
public
enum
SmsResultEnum
{
INIT_SMS_CLIENT_ERROR
(
"SMS_CLIENT_INIT_ERROR"
,
"初始化sms客户端错误,accessKey错误"
),
PARAM_NULL
(
"NULL"
,
"请求参数为空"
),
OK
(
"OK"
,
"请求成功"
),
RAM_PERMISSION_DENY
(
"isp.RAM_PERMISSION_DENY"
,
"RAM权限DENY"
),
PRODUCT_UNSUBSCRIBE
(
"isv.PRODUCT_UNSUBSCRIBE"
,
"产品未开通"
),
ACCOUNT_NOT_EXISTS
(
"isv.ACCOUNT_NOT_EXISTS"
,
"账户不存在"
),
ACCOUNT_ABNORMAL
(
"isv.ACCOUNT_ABNORMAL"
,
"账户异常"
),
SMS_TEMPLATE_ILLEGAL
(
"isv.SMS_TEMPLATE_ILLEGAL"
,
"短信模板不合法"
),
SMS_SIGNATURE_ILLEGAL
(
"isv.SMS_SIGNATURE_ILLEGAL"
,
"短信签名不合法"
),
INVALID_PARAMETERS
(
"isv.INVALID_PARAMETERS"
,
"参数异常"
),
SYSTEM_ERROR
(
"isp.SYSTEM_ERROR"
,
"系统错误"
),
MOBILE_NUMBER_ILLEGAL
(
"isv.MOBILE_NUMBER_ILLEGAL"
,
"非法手机号"
),
MOBILE_COUNT_OVER_LIMIT
(
"isv.MOBILE_COUNT_OVER_LIMIT"
,
"手机号码数量超过限制"
),
TEMPLATE_MISSING_PARAMETERS
(
"isv.TEMPLATE_MISSING_PARAMETERS"
,
"模板缺少变量"
),
BUSINESS_LIMIT_CONTROL
(
"isv.BUSINESS_LIMIT_CONTROL"
,
"发送短信过于频繁,请稍后再试"
),
INVALID_JSON_PARAM
(
"isv.INVALID_JSON_PARAM"
,
"JSON参数不合法,只接受字符串值"
),
BLACK_KEY_CONTROL_LIMIT
(
"isv.BLACK_KEY_CONTROL_LIMIT"
,
"黑名单管控"
),
PARAM_LENGTH_LIMIT
(
"isv.PARAM_LENGTH_LIMIT"
,
"参数超出长度限制"
),
PARAM_NOT_SUPPORT_URL
(
"isv.PARAM_NOT_SUPPORT_URL"
,
"不支持URL"
),
AMOUNT_NOT_ENOUGH
(
"isv.AMOUNT_NOT_ENOUGH"
,
"账户余额不足"
);
SmsResultEnum
(
String
code
,
String
message
)
{
this
.
code
=
code
;
this
.
message
=
message
;
}
private
String
code
;
private
String
message
;
public
String
getCode
()
{
return
code
;
}
public
void
setCode
(
String
code
)
{
this
.
code
=
code
;
}
public
String
getMessage
()
{
return
message
;
}
public
void
setMessage
(
String
message
)
{
this
.
message
=
message
;
}
}
guns-base-sms/src/main/java/cn/stylefeng/guns/sms/core/enums/SmsSendSource.java
0 → 100644
View file @
7f4f3d7c
package
cn
.
stylefeng
.
guns
.
sms
.
core
.
enums
;
/**
* 短信发送业务枚举
*
* @author stylefeng
* @Date 2018年5月6日 12:30:48
*/
public
enum
SmsSendSource
{
WEB
(
0
),
PC
(
1
),
OTHER
(
2
);
private
Integer
code
;
SmsSendSource
(
Integer
code
)
{
this
.
code
=
code
;
}
public
Integer
getCode
()
{
return
code
;
}
public
void
setCode
(
Integer
code
)
{
this
.
code
=
code
;
}
public
static
SmsSendSource
toEnum
(
Integer
type
)
{
if
(
type
==
null
)
{
return
null
;
}
else
{
for
(
SmsSendSource
item
:
SmsSendSource
.
values
())
{
if
(
item
.
getCode
().
equals
(
type
))
{
return
item
;
}
}
return
null
;
}
}
}
guns-base-sms/src/main/java/cn/stylefeng/guns/sms/core/enums/SmsSendStatus.java
0 → 100644
View file @
7f4f3d7c
package
cn
.
stylefeng
.
guns
.
sms
.
core
.
enums
;
/**
* 短信发送状态枚举
*
* @author stylefeng
* @Date 2018年5月6日 12:30:48
*/
public
enum
SmsSendStatus
{
WAITING
(
0
,
"未发送"
),
SUCCESS
(
1
,
"发送成功"
),
INVALID
(
3
,
"失效"
),
FAILED
(
2
,
"发送失败"
);
private
Integer
code
;
private
String
desc
;
SmsSendStatus
(
Integer
code
,
String
desc
)
{
this
.
code
=
code
;
this
.
desc
=
desc
;
}
public
Integer
getCode
()
{
return
code
;
}
public
void
setCode
(
Integer
code
)
{
this
.
code
=
code
;
}
public
String
getDesc
()
{
return
desc
;
}
public
void
setDesc
(
String
desc
)
{
this
.
desc
=
desc
;
}
}
guns-base-sms/src/main/java/cn/stylefeng/guns/sms/core/enums/SmsVerifyResult.java
0 → 100644
View file @
7f4f3d7c
package
cn
.
stylefeng
.
guns
.
sms
.
core
.
enums
;
/**
* 短信验证结果
*
* @author stylefeng
* @Date 2018年5月6日 12:30:48
*/
public
enum
SmsVerifyResult
{
SUCCESS
(
10
,
"验证成功"
),
ERROR
(
20
,
"验证码错误"
),
EXPIRED
(
30
,
"验证码超时"
),
TIMES_UP
(
40
,
"超过验证次数"
);
private
Integer
code
;
private
String
desc
;
SmsVerifyResult
(
Integer
code
,
String
desc
)
{
this
.
code
=
code
;
this
.
desc
=
desc
;
}
public
Integer
getCode
()
{
return
code
;
}
public
void
setCode
(
Integer
code
)
{
this
.
code
=
code
;
}
public
String
getDesc
()
{
return
desc
;
}
public
void
setDesc
(
String
desc
)
{
this
.
desc
=
desc
;
}
}
guns-base-sms/src/main/java/cn/stylefeng/guns/sms/core/exception/SmsException.java
0 → 100644
View file @
7f4f3d7c
package
cn
.
stylefeng
.
guns
.
sms
.
core
.
exception
;
/**
* 短信发送异常
*
* @author fengshuonan
* @date 2018-07-06-下午3:00
*/
public
class
SmsException
extends
RuntimeException
{
private
String
code
;
private
String
errorMessage
;
public
SmsException
(
String
code
,
String
errorMessage
)
{
super
(
errorMessage
);
this
.
code
=
code
;
this
.
errorMessage
=
errorMessage
;
}
public
String
getCode
()
{
return
code
;
}
public
void
setCode
(
String
code
)
{
this
.
code
=
code
;
}
public
String
getErrorMessage
()
{
return
errorMessage
;
}
public
void
setErrorMessage
(
String
errorMessage
)
{
this
.
errorMessage
=
errorMessage
;
}
}
guns-base-sms/src/main/java/cn/stylefeng/guns/sms/core/sms/SmsManager.java
0 → 100644
View file @
7f4f3d7c
package
cn
.
stylefeng
.
guns
.
sms
.
core
.
sms
;
import
cn.stylefeng.guns.sms.modular.model.SmsSendRecord
;
import
java.util.Date
;
import
java.util.List
;
import
java.util.Map
;
/**
* 短信发送服务
*
* @author fengshuonan
* @date 2018-07-06-下午2:14
*/
public
interface
SmsManager
{
/**
* 发送短信
*
* @param phoneNumber 电话号码
* @param templateCode 模板号码
* @param params 模板里参数的集合
* @author fengshuonan
* @Date 2018/7/6 下午2:32
*/
void
sendSms
(
String
phoneNumber
,
String
templateCode
,
Map
<
String
,
Object
>
params
);
/**
* 获取某个手机号已发送短信列表
*
* @param phoneNumber 手机号码
* @param sendDate 发送日期
* @param pageNo 分页(第几页)不传递返回第一页,默认分页大小50
* @author fengshuonan
* @Date 2018/7/6 下午3:54
*/
List
<
SmsSendRecord
>
getAlreadySendList
(
String
phoneNumber
,
Date
sendDate
,
Integer
pageNo
);
}
guns-base-sms/src/main/java/cn/stylefeng/guns/sms/core/sms/service/AliyunSmsManager.java
0 → 100644
View file @
7f4f3d7c
package
cn
.
stylefeng
.
guns
.
sms
.
core
.
sms
.
service
;
import
cn.hutool.core.date.DateUtil
;
import
cn.stylefeng.guns.sms.config.properties.AliyunSmsProperties
;
import
cn.stylefeng.guns.sms.core.cache.MultiSignManager
;
import
cn.stylefeng.guns.sms.core.enums.SmsResultEnum
;
import
cn.stylefeng.guns.sms.core.exception.SmsException
;
import
cn.stylefeng.guns.sms.core.sms.SmsManager
;
import
cn.stylefeng.guns.sms.modular.model.SmsSendRecord
;
import
cn.stylefeng.roses.kernel.model.util.ValidateUtil
;
import
com.alibaba.fastjson.JSON
;
import
com.aliyuncs.DefaultAcsClient
;
import
com.aliyuncs.IAcsClient
;
import
com.aliyuncs.dysmsapi.model.v20170525.QuerySendDetailsRequest
;
import
com.aliyuncs.dysmsapi.model.v20170525.QuerySendDetailsResponse
;
import
com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest
;
import
com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse
;
import
com.aliyuncs.exceptions.ClientException
;
import
com.aliyuncs.http.MethodType
;
import
com.aliyuncs.profile.DefaultProfile
;
import
com.aliyuncs.profile.IClientProfile
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.BeanUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
java.util.ArrayList
;
import
java.util.Date
;
import
java.util.List
;
import
java.util.Map
;
import
static
cn
.
hutool
.
core
.
date
.
DatePattern
.
PURE_DATE_PATTERN
;
/**
* 阿里云短信发送服务
*
* @author fengshuonan
* @date 2018-07-06-下午2:15
*/
@Slf4j
public
class
AliyunSmsManager
implements
SmsManager
{
@Autowired
private
AliyunSmsProperties
aliyunSmsProperties
;
@Autowired
private
MultiSignManager
multiSignManager
;
@Override
public
void
sendSms
(
String
phoneNumber
,
String
templateCode
,
Map
<
String
,
Object
>
params
)
{
log
.
info
(
"开始发送阿里云短信,手机号是:"
+
phoneNumber
+
",模板号是:"
+
templateCode
+
",参数是:"
+
JSON
.
toJSONString
(
params
));
//检验参数是否合法
assertSendSmsParams
(
phoneNumber
,
templateCode
,
params
,
aliyunSmsProperties
);
//初始化client profile
IClientProfile
profile
=
initClientProfile
();
IAcsClient
acsClient
=
new
DefaultAcsClient
(
profile
);
//组装请求对象
SendSmsResponse
sendSmsResponse
=
createSmsRequest
(
phoneNumber
,
templateCode
,
params
,
acsClient
);
//如果返回ok则发送成功
if
(
sendSmsResponse
.
getCode
()
!=
null
&&
SmsResultEnum
.
OK
.
getCode
().
equals
(
sendSmsResponse
.
getCode
()))
{
return
;
}
else
{
//放回其他状态码根据情况抛出业务异常
String
code
=
SmsResultEnum
.
SYSTEM_ERROR
.
getCode
();
String
errorMessage
=
SmsResultEnum
.
SYSTEM_ERROR
.
getMessage
();
for
(
SmsResultEnum
smsResultEnum
:
SmsResultEnum
.
values
())
{
if
(
smsResultEnum
.
getCode
().
equals
(
sendSmsResponse
.
getCode
()))
{
code
=
smsResultEnum
.
getCode
();
errorMessage
=
smsResultEnum
.
getMessage
();
}
}
log
.
error
(
"发送短信异常!code = "
+
code
+
",message = "
+
errorMessage
);
throw
new
SmsException
(
code
,
errorMessage
);
}
}
@Override
public
List
<
SmsSendRecord
>
getAlreadySendList
(
String
phoneNumber
,
Date
sendDate
,
Integer
pageNo
)
{
//检验参数是否合法
assertGetSendListParams
(
phoneNumber
,
sendDate
,
pageNo
);
//初始化阿里云短信发送环境
IClientProfile
clientProfile
=
initClientProfile
();
IAcsClient
acsClient
=
new
DefaultAcsClient
(
clientProfile
);
//组装请求对象
QuerySendDetailsRequest
request
=
new
QuerySendDetailsRequest
();
request
.
setPhoneNumber
(
phoneNumber
);
//必填-短信发送的日期 支持30天内记录查询(可查其中一天的发送数据),格式yyyyMMdd
String
dateString
=
DateUtil
.
format
(
sendDate
,
PURE_DATE_PATTERN
);
request
.
setSendDate
(
dateString
);
//必填-页大小
request
.
setPageSize
(
50L
);
//必填-当前页码从1开始计数
request
.
setCurrentPage
(
pageNo
==
null
?
1L
:
pageNo
);
//hint 此处可能会抛出异常,注意catch
QuerySendDetailsResponse
querySendDetailsResponse
=
null
;
try
{
querySendDetailsResponse
=
acsClient
.
getAcsResponse
(
request
);
}
catch
(
ClientException
e
)
{
log
.
error
(
"获取已发短信列表异常!"
,
e
);
}
//获取返回结果
if
(
querySendDetailsResponse
.
getCode
()
!=
null
&&
querySendDetailsResponse
.
getCode
().
equals
(
"OK"
))
{
//转化查询结果为List<SmsSendRecord>
List
<
QuerySendDetailsResponse
.
SmsSendDetailDTO
>
smsSendDetailDTOs
=
querySendDetailsResponse
.
getSmsSendDetailDTOs
();
ArrayList
<
SmsSendRecord
>
results
=
new
ArrayList
<>();
for
(
QuerySendDetailsResponse
.
SmsSendDetailDTO
smsSendDetailDTO
:
smsSendDetailDTOs
)
{
SmsSendRecord
smsSendRecord
=
new
SmsSendRecord
();
BeanUtils
.
copyProperties
(
smsSendDetailDTO
,
smsSendRecord
);
results
.
add
(
smsSendRecord
);
}
return
results
;
}
else
{
log
.
error
(
"获取短信列表异常!code = "
+
querySendDetailsResponse
.
getCode
());
throw
new
SmsException
(
querySendDetailsResponse
.
getCode
(),
"获取短信列表异常!"
);
}
}
/**
* 初始化短信发送的环境
*
* @author fengshuonan
* @Date 2018/7/6 下午3:57
*/
private
IClientProfile
initClientProfile
()
{
//设置超时时间
System
.
setProperty
(
"sun.net.client.defaultConnectTimeout"
,
"10000"
);
System
.
setProperty
(
"sun.net.client.defaultReadTimeout"
,
"10000"
);
//初始化ascClient需要的几个参数
final
String
product
=
"Dysmsapi"
;
//短信API产品名称(短信产品名固定,无需修改)
final
String
domain
=
"dysmsapi.aliyuncs.com"
;
//短信API产品域名(接口地址固定,无需修改)
final
String
accessKeyId
=
aliyunSmsProperties
.
getAccessKeyId
();
final
String
accessKeySecret
=
aliyunSmsProperties
.
getAccessKeySecret
();
//初始化ascClient,暂时不支持多region(请勿修改)
IClientProfile
profile
=
DefaultProfile
.
getProfile
(
"cn-hangzhou"
,
accessKeyId
,
accessKeySecret
);
try
{
DefaultProfile
.
addEndpoint
(
"cn-hangzhou"
,
"cn-hangzhou"
,
product
,
domain
);
}
catch
(
ClientException
e
)
{
log
.
error
(
"初始化阿里云sms异常!"
,
e
);
}
return
profile
;
}
/**
* 组装请求对象
*
* @author fengshuonan
* @Date 2018/7/6 下午3:00
*/
private
SendSmsResponse
createSmsRequest
(
String
phoneNumber
,
String
templateCode
,
Map
<
String
,
Object
>
params
,
IAcsClient
acsClient
)
{
SendSmsRequest
request
=
new
SendSmsRequest
();
request
.
setMethod
(
MethodType
.
POST
);
//必填:待发送手机号。支持以逗号分隔的形式进行批量调用,
//批量上限为1000个手机号码,批量调用相对于单条调用及时性稍有延迟,验证码类型的短信推荐使用单条调用的方式;发送国际/港澳台消息时,接收号码格式为00+国际区号+号码,如“0085200000000”
request
.
setPhoneNumbers
(
phoneNumber
);
//必填:短信签名-可在短信控制台中找到
request
.
setSignName
(
this
.
getSmsSign
(
phoneNumber
));
//必填:短信模板-可在短信控制台中找到
request
.
setTemplateCode
(
templateCode
);
//可选:模板中的变量替换JSON串
//友情提示:如果JSON中需要带换行符,请参照标准的JSON协议对换行符的要求,比如短信内容中包含\r\n的情况在JSON中需要表示成\\r\\n,否则会导致JSON在服务端解析失败
request
.
setTemplateParam
(
JSON
.
toJSONString
(
params
));
//可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者
request
.
setOutId
(
"yourOutId"
);
//请求失败这里会抛ClientException异常
SendSmsResponse
sendSmsResponse
=
null
;
try
{
sendSmsResponse
=
acsClient
.
getAcsResponse
(
request
);
}
catch
(
ClientException
e
)
{
log
.
error
(
"初始化阿里云sms异常!可能是accessKey和secret错误!"
,
e
);
throw
new
SmsException
(
SmsResultEnum
.
INIT_SMS_CLIENT_ERROR
.
getCode
(),
SmsResultEnum
.
INIT_SMS_CLIENT_ERROR
.
getMessage
());
}
return
sendSmsResponse
;
}
/**
* 校验发送短信的参数是否正确
*
* @author fengshuonan
* @Date 2018/7/6 下午3:19
*/
private
void
assertSendSmsParams
(
String
phoneNumber
,
String
templateCode
,
Map
<
String
,
Object
>
params
,
AliyunSmsProperties
aliyunSmsProperties
)
{
if
(
ValidateUtil
.
isOneEmpty
(
phoneNumber
,
templateCode
,
params
,
aliyunSmsProperties
))
{
log
.
error
(
"阿里云短信发送异常!请求参数存在空!"
);
throw
new
SmsException
(
SmsResultEnum
.
PARAM_NULL
.
getCode
(),
SmsResultEnum
.
PARAM_NULL
.
getMessage
());
}
}
/**
* 校验获取已发送列表的传参
*
* @author fengshuonan
* @Date 2018/7/6 下午4:13
*/
private
void
assertGetSendListParams
(
String
phoneNumber
,
Date
sendDate
,
Integer
pageNo
)
{
if
(
ValidateUtil
.
isOneEmpty
(
phoneNumber
,
sendDate
))
{
log
.
error
(
"阿里云获取短信发送列表异常!请求参数存在空!"
);
throw
new
SmsException
(
SmsResultEnum
.
PARAM_NULL
.
getCode
(),
SmsResultEnum
.
PARAM_NULL
.
getMessage
());
}
}
/**
* 获取sms发送的sign标识,参数phone是发送的手机号码
*
* @author stylefeng
* @Date 2018/8/13 21:23
*/
private
String
getSmsSign
(
String
phone
)
{
String
signName
=
this
.
aliyunSmsProperties
.
getSignName
();
//如果是单个签名就用一个签名发
if
(!
signName
.
contains
(
","
))
{
log
.
info
(
"发送短信,签名为:"
+
signName
+
",电话为:"
+
phone
);
return
signName
;
}
else
{
return
multiSignManager
.
getSign
(
phone
,
signName
);
}
}
}
guns-base-sms/src/main/java/cn/stylefeng/guns/sms/modular/entity/SmsInfo.java
0 → 100644
View file @
7f4f3d7c
package
cn
.
stylefeng
.
guns
.
sms
.
modular
.
entity
;
import
com.baomidou.mybatisplus.annotation.IdType
;
import
com.baomidou.mybatisplus.annotation.TableField
;
import
com.baomidou.mybatisplus.annotation.TableId
;
import
com.baomidou.mybatisplus.annotation.TableName
;
import
java.io.Serializable
;
import
java.util.Date
;
/**
* <p>
* 短信信息表
* </p>
*
* @author fengshuonan
* @since 2018-07-05
*/
@TableName
(
"sms_info"
)
public
class
SmsInfo
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
/**
* 主键
*/
@TableId
(
value
=
"ID"
,
type
=
IdType
.
AUTO
)
private
Integer
id
;
/**
* 手机号
*/
@TableField
(
"PHONE_NUMBERS"
)
private
String
phoneNumbers
;
/**
* 短信验证码
*/
@TableField
(
"VALIDATE_CODE"
)
private
String
validateCode
;
/**
* 短信模板ID
*/
@TableField
(
"TEMPLATE_CODE"
)
private
String
templateCode
;
/**
* 回执ID,可根据该ID查询具体的发送状态
*/
@TableField
(
"BIZID"
)
private
String
bizid
;
/**
* 0=未发送,1=发送成功,2=发送失败
*/
@TableField
(
"STATUS"
)
private
Integer
status
;
/**
* 0=app,1=pc,2=其它
*/
@TableField
(
"SOURCE"
)
private
Integer
source
;
/**
* 失效时间
*/
@TableField
(
"INVALID_TIME"
)
private
Date
invalidTime
;
/**
* 修改时间
*/
@TableField
(
"MODIFY_TIME"
)
private
Date
modifyTime
;
/**
* 创建时间
*/
@TableField
(
"CREATE_TIME"
)
private
Date
createTime
;
public
Integer
getId
()
{
return
id
;
}
public
void
setId
(
Integer
id
)
{
this
.
id
=
id
;
}
public
String
getPhoneNumbers
()
{
return
phoneNumbers
;
}
public
void
setPhoneNumbers
(
String
phoneNumbers
)
{
this
.
phoneNumbers
=
phoneNumbers
;
}
public
String
getValidateCode
()
{
return
validateCode
;
}
public
void
setValidateCode
(
String
validateCode
)
{
this
.
validateCode
=
validateCode
;
}
public
String
getTemplateCode
()
{
return
templateCode
;
}
public
void
setTemplateCode
(
String
templateCode
)
{
this
.
templateCode
=
templateCode
;
}
public
String
getBizid
()
{
return
bizid
;
}
public
void
setBizid
(
String
bizid
)
{
this
.
bizid
=
bizid
;
}
public
Integer
getStatus
()
{
return
status
;
}
public
void
setStatus
(
Integer
status
)
{
this
.
status
=
status
;
}
public
Integer
getSource
()
{
return
source
;
}
public
void
setSource
(
Integer
source
)
{
this
.
source
=
source
;
}
public
Date
getInvalidTime
()
{
return
invalidTime
;
}
public
void
setInvalidTime
(
Date
invalidTime
)
{
this
.
invalidTime
=
invalidTime
;
}
public
Date
getModifyTime
()
{
return
modifyTime
;
}
public
void
setModifyTime
(
Date
modifyTime
)
{
this
.
modifyTime
=
modifyTime
;
}
public
Date
getCreateTime
()
{
return
createTime
;
}
public
void
setCreateTime
(
Date
createTime
)
{
this
.
createTime
=
createTime
;
}
@Override
public
String
toString
()
{
return
"TcSmsInfo{"
+
"id="
+
id
+
", phoneNumbers="
+
phoneNumbers
+
", validateCode="
+
validateCode
+
", templateCode="
+
templateCode
+
", bizid="
+
bizid
+
", status="
+
status
+
", source="
+
source
+
", invalidTime="
+
invalidTime
+
", modifyTime="
+
modifyTime
+
", createTime="
+
createTime
+
"}"
;
}
}
guns-base-sms/src/main/java/cn/stylefeng/guns/sms/modular/mapper/SmsInfoMapper.java
0 → 100644
View file @
7f4f3d7c
package
cn
.
stylefeng
.
guns
.
sms
.
modular
.
mapper
;
import
cn.stylefeng.guns.sms.modular.entity.SmsInfo
;
import
com.baomidou.mybatisplus.core.mapper.BaseMapper
;
/**
* <p>
* 短信信息表 Mapper 接口
* </p>
*
* @author fengshuonan
* @since 2018-07-05
*/
public
interface
SmsInfoMapper
extends
BaseMapper
<
SmsInfo
>
{
}
guns-base-sms/src/main/java/cn/stylefeng/guns/sms/modular/mapper/mapping/SmsInfoMapper.xml
0 → 100644
View file @
7f4f3d7c
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper
namespace=
"cn.stylefeng.guns.sms.modular.mapper.SmsInfoMapper"
>
<!-- 通用查询映射结果 -->
<resultMap
id=
"BaseResultMap"
type=
"cn.stylefeng.guns.sms.modular.entity.SmsInfo"
>
<id
column=
"ID"
property=
"id"
/>
<result
column=
"PHONE_NUMBERS"
property=
"phoneNumbers"
/>
<result
column=
"VALIDATE_CODE"
property=
"validateCode"
/>
<result
column=
"TEMPLATE_CODE"
property=
"templateCode"
/>
<result
column=
"BIZID"
property=
"bizid"
/>
<result
column=
"STATUS"
property=
"status"
/>
<result
column=
"SOURCE"
property=
"source"
/>
<result
column=
"INVALID_TIME"
property=
"invalidTime"
/>
<result
column=
"MODIFY_TIME"
property=
"modifyTime"
/>
<result
column=
"CREATE_TIME"
property=
"createTime"
/>
</resultMap>
<!-- 通用查询结果列 -->
<sql
id=
"Base_Column_List"
>
ID as id, PHONE_NUMBERS AS phoneNumbers, VALIDATE_CODE AS validateCode, TEMPLATE_CODE AS templateCode, BIZID as bizid, STATUS as status, SOURCE as source, INVALID_TIME AS invalidTime, MODIFY_TIME AS modifyTime, CREATE_TIME AS createTime
</sql>
</mapper>
guns-base-sms/src/main/java/cn/stylefeng/guns/sms/modular/model/SendMessageParam.java
0 → 100644
View file @
7f4f3d7c
package
cn
.
stylefeng
.
guns
.
sms
.
modular
.
model
;
import
cn.stylefeng.guns.sms.core.enums.MessageType
;
import
cn.stylefeng.guns.sms.core.enums.SmsSendSource
;
import
lombok.Data
;
import
java.util.Map
;
/**
* 发送短信的参数
*
* @author fengshuonan
* @date 2018-07-05 21:19
*/
@Data
public
class
SendMessageParam
{
/**
* 手机号
*/
private
String
phoneNumbers
;
/**
* 模板号
*/
private
String
templateCode
;
/**
* 模板中的参数
*/
private
Map
<
String
,
Object
>
params
;
/**
* sms发送源
*/
private
SmsSendSource
smsSendSource
=
SmsSendSource
.
PC
;
/**
* 消息类型,1=验证码,2=消息,默认不传为验证码
*/
private
MessageType
messageType
=
MessageType
.
SMS
;
}
guns-base-sms/src/main/java/cn/stylefeng/guns/sms/modular/model/SmsSendRecord.java
0 → 100644
View file @
7f4f3d7c
package
cn
.
stylefeng
.
guns
.
sms
.
modular
.
model
;
import
lombok.Data
;
/**
* 消息发送记录
*
* @author fengshuonan
* @date 2018-07-06-下午4:07
*/
@Data
public
class
SmsSendRecord
{
/**
* 手机号码
*/
private
String
phoneNum
;
/**
* 发送状态 1:等待回执,2:发送失败,3:发送成功
*/
private
Long
sendStatus
;
/**
* 运营商短信错误码
*/
private
String
errCode
;
/**
* 模板ID
*/
private
String
templateCode
;
/**
* 短信内容
*/
private
String
content
;
/**
* 发送时间
*/
private
String
sendDate
;
/**
* 接收时间
*/
private
String
receiveDate
;
/**
* 外部流水扩展字段
*/
private
String
outId
;
}
guns-base-sms/src/main/java/cn/stylefeng/guns/sms/modular/model/VerifySMSParam.java
0 → 100644
View file @
7f4f3d7c
package
cn
.
stylefeng
.
guns
.
sms
.
modular
.
model
;
import
cn.stylefeng.guns.sms.core.enums.SmsSendSource
;
import
lombok.Data
;
/**
* 发送短信的参数
*
* @author fengshuonan
* @date 2018-07-05 21:19
*/
@Data
public
class
VerifySMSParam
{
/**
* 手机号
*/
private
String
phoneNumbers
;
/**
* 验证码
*/
private
String
code
;
/**
* 模板号
*/
private
String
templateCode
;
/**
* 来源
*/
private
SmsSendSource
smsSendSource
;
}
guns-base-sms/src/main/java/cn/stylefeng/guns/sms/modular/provider/SmsServiceApi.java
0 → 100644
View file @
7f4f3d7c
package
cn
.
stylefeng
.
guns
.
sms
.
modular
.
provider
;
import
cn.stylefeng.guns.sms.core.enums.SmsSendStatus
;
import
cn.stylefeng.guns.sms.core.enums.SmsVerifyResult
;
import
cn.stylefeng.guns.sms.modular.model.SendMessageParam
;
import
cn.stylefeng.guns.sms.modular.model.VerifySMSParam
;
/**
* 短信通知接口
*
* @author stylefeng
* @Date 2018/7/5 21:05
*/
public
interface
SmsServiceApi
{
/**
* 发送短信
*
* @author fengshuonan
* @Date 2018/7/6 下午4:32
*/
Boolean
sendShortMessage
(
SendMessageParam
sendMessageParam
);
/**
* 验证短信
*
* @author fengshuonan
* @Date 2018/7/6 下午4:30
*/
SmsVerifyResult
verifyShortMessage
(
VerifySMSParam
verifySMSParam
);
/**
* <pre>
* 查看短信发送状态
*
* 0=未发送,1=发送成功,2=发送失败
* </pre>
*
* @author fengshuonan
* @Date 2018/7/6 下午4:32
*/
SmsSendStatus
getMessageSendStatus
(
Integer
smsId
);
}
guns-base-sms/src/main/java/cn/stylefeng/guns/sms/modular/provider/SmsServiceProvider.java
0 → 100644
View file @
7f4f3d7c
package
cn
.
stylefeng
.
guns
.
sms
.
modular
.
provider
;
import
cn.hutool.core.util.RandomUtil
;
import
cn.stylefeng.guns.sms.core.enums.MessageType
;
import
cn.stylefeng.guns.sms.core.enums.SmsSendStatus
;
import
cn.stylefeng.guns.sms.core.enums.SmsVerifyResult
;
import
cn.stylefeng.guns.sms.core.sms.SmsManager
;
import
cn.stylefeng.guns.sms.modular.model.SendMessageParam
;
import
cn.stylefeng.guns.sms.modular.model.VerifySMSParam
;
import
cn.stylefeng.guns.sms.modular.service.SmsInfoService
;
import
com.alibaba.fastjson.JSON
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.transaction.annotation.Transactional
;
import
java.util.HashMap
;
import
java.util.Map
;
/**
* 短信通知接口
*
* @author stylefeng
* @Date 2018/7/5 21:05
*/
@Slf4j
public
class
SmsServiceProvider
implements
SmsServiceApi
{
@Autowired
private
SmsManager
smsManager
;
@Autowired
private
SmsInfoService
smsInfoService
;
@Override
@Transactional
(
rollbackFor
=
Exception
.
class
)
public
Boolean
sendShortMessage
(
SendMessageParam
sendMessageParam
)
{
Map
<
String
,
Object
>
params
=
sendMessageParam
.
getParams
();
log
.
info
(
"发送短信Provider接口,参数为:"
+
JSON
.
toJSONString
(
sendMessageParam
));
//如果是纯消息发送
if
(
MessageType
.
MESSAGE
.
equals
(
sendMessageParam
.
getMessageType
()))
{
smsManager
.
sendSms
(
sendMessageParam
.
getPhoneNumbers
(),
sendMessageParam
.
getTemplateCode
(),
params
);
log
.
info
(
"发送短信Provider接口--message,params的map具体为:"
+
JSON
.
toJSONString
(
params
));
}
else
{
//初始化短信发送参数
String
validateCode
=
null
;
//如果传的参数中没有code,就初始化一个code放到参数map里
if
(
params
!=
null
&&
params
.
get
(
"code"
)
!=
null
)
{
validateCode
=
params
.
get
(
"code"
).
toString
();
}
else
{
validateCode
=
RandomUtil
.
randomNumbers
(
6
);
if
(
params
==
null
)
{
params
=
new
HashMap
<>();
}
params
.
put
(
"code"
,
validateCode
);
}
log
.
info
(
"发送短信Provider接口,params的map具体为:"
+
JSON
.
toJSONString
(
params
));
log
.
info
(
"发送短信Provider接口,验证码为:"
+
validateCode
);
//存储短信到数据库
Integer
keyId
=
smsInfoService
.
saveSmsInfo
(
sendMessageParam
,
validateCode
);
log
.
info
(
"开始发送短信:发送的电话号码= "
+
sendMessageParam
.
getPhoneNumbers
()
+
",发送的模板号="
+
sendMessageParam
.
getTemplateCode
()
+
",发送的参数是:"
+
JSON
.
toJSONString
(
params
));
//发送短信
smsManager
.
sendSms
(
sendMessageParam
.
getPhoneNumbers
(),
sendMessageParam
.
getTemplateCode
(),
params
);
//更新短信发送状态
smsInfoService
.
updateSmsInfo
(
keyId
,
SmsSendStatus
.
SUCCESS
);
}
return
true
;
}
@Override
public
SmsVerifyResult
verifyShortMessage
(
VerifySMSParam
verifySMSParam
)
{
log
.
info
(
"验证短信Provider接口,参数为:"
+
JSON
.
toJSONString
(
verifySMSParam
));
SmsVerifyResult
smsVerifyResult
=
smsInfoService
.
validateSmsInfo
(
verifySMSParam
);
log
.
info
(
"验证短信Provider接口,响应结果为:"
+
JSON
.
toJSONString
(
smsVerifyResult
));
return
smsVerifyResult
;
//return SmsVerifyResult.SUCCESS;
}
@Override
public
SmsSendStatus
getMessageSendStatus
(
Integer
smsId
)
{
return
null
;
}
}
guns-base-sms/src/main/java/cn/stylefeng/guns/sms/modular/service/SmsInfoService.java
0 → 100644
View file @
7f4f3d7c
package
cn
.
stylefeng
.
guns
.
sms
.
modular
.
service
;
import
cn.stylefeng.guns.sms.config.properties.AliyunSmsProperties
;
import
cn.stylefeng.guns.sms.core.enums.SmsResultEnum
;
import
cn.stylefeng.guns.sms.core.enums.SmsSendStatus
;
import
cn.stylefeng.guns.sms.core.enums.SmsVerifyResult
;
import
cn.stylefeng.guns.sms.core.exception.SmsException
;
import
cn.stylefeng.guns.sms.modular.entity.SmsInfo
;
import
cn.stylefeng.guns.sms.modular.mapper.SmsInfoMapper
;
import
cn.stylefeng.guns.sms.modular.model.SendMessageParam
;
import
cn.stylefeng.guns.sms.modular.model.VerifySMSParam
;
import
cn.stylefeng.roses.kernel.model.util.ValidateUtil
;
import
com.alibaba.fastjson.JSON
;
import
com.baomidou.mybatisplus.core.conditions.query.QueryWrapper
;
import
com.baomidou.mybatisplus.extension.service.impl.ServiceImpl
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.transaction.annotation.Transactional
;
import
java.util.Date
;
import
java.util.List
;
/**
* <p>
* 短信信息表 服务实现类
* </p>
*
* @author fengshuonan
* @since 2018-07-05
*/
@Slf4j
public
class
SmsInfoService
extends
ServiceImpl
<
SmsInfoMapper
,
SmsInfo
>
{
@Autowired
private
AliyunSmsProperties
aliyunSmsProperties
;
/**
* 存储短信验证信息
*
* @author fengshuonan
* @Date 2018/7/6 下午4:47
*/
public
Integer
saveSmsInfo
(
SendMessageParam
sendMessageParam
,
String
validateCode
)
{
if
(
ValidateUtil
.
isOneEmpty
(
sendMessageParam
.
getPhoneNumbers
(),
validateCode
,
sendMessageParam
.
getTemplateCode
()))
{
log
.
error
(
"存储短信到数据库失败!有参数为空!"
);
throw
new
SmsException
(
SmsResultEnum
.
PARAM_NULL
.
getCode
(),
SmsResultEnum
.
PARAM_NULL
.
getMessage
());
}
//当前时间
Date
nowDate
=
new
Date
();
//短信失效时间
long
invalidateTime
=
nowDate
.
getTime
()
+
aliyunSmsProperties
.
getInvalidateMinutes
()
*
60
*
1000
;
Date
invalidate
=
new
Date
(
invalidateTime
);
SmsInfo
smsInfo
=
new
SmsInfo
();
smsInfo
.
setCreateTime
(
nowDate
);
smsInfo
.
setInvalidTime
(
invalidate
);
smsInfo
.
setPhoneNumbers
(
sendMessageParam
.
getPhoneNumbers
());
smsInfo
.
setStatus
(
SmsSendStatus
.
WAITING
.
getCode
());
smsInfo
.
setSource
(
sendMessageParam
.
getSmsSendSource
().
getCode
());
smsInfo
.
setTemplateCode
(
sendMessageParam
.
getTemplateCode
());
smsInfo
.
setValidateCode
(
validateCode
);
this
.
save
(
smsInfo
);
log
.
info
(
"发送短信,存储短信到数据库,数据为:"
+
JSON
.
toJSONString
(
smsInfo
));
return
smsInfo
.
getId
();
}
/**
* 更新短息发送状态
*
* @author fengshuonan
* @Date 2018/7/6 下午5:12
*/
public
void
updateSmsInfo
(
Integer
keyId
,
SmsSendStatus
smsSendStatus
)
{
SmsInfo
smsInfo
=
this
.
getById
(
keyId
);
smsInfo
.
setStatus
(
smsSendStatus
.
getCode
());
this
.
updateById
(
smsInfo
);
}
/**
* 校验验证码是否正确
*
* @author fengshuonan
* @Date 2018/7/6 下午5:16
*/
@Transactional
(
rollbackFor
=
Exception
.
class
)
public
SmsVerifyResult
validateSmsInfo
(
VerifySMSParam
verifySMSParam
)
{
//校验请求是否为空
if
(
ValidateUtil
.
isOneEmpty
(
verifySMSParam
.
getPhoneNumbers
(),
verifySMSParam
.
getCode
(),
verifySMSParam
.
getTemplateCode
()))
{
log
.
error
(
"校验短信是否正确失败!有参数为空!"
);
throw
new
SmsException
(
SmsResultEnum
.
PARAM_NULL
.
getCode
(),
SmsResultEnum
.
PARAM_NULL
.
getMessage
());
}
//查询有没有这条记录
QueryWrapper
<
SmsInfo
>
wrapper
=
new
QueryWrapper
<>();
wrapper
.
eq
(
"phone_numbers"
,
verifySMSParam
.
getPhoneNumbers
())
.
and
(
f
->
f
.
eq
(
"source"
,
verifySMSParam
.
getSmsSendSource
().
getCode
()))
.
and
(
f
->
f
.
eq
(
"template_code"
,
verifySMSParam
.
getTemplateCode
()));
wrapper
.
orderByDesc
(
"create_time"
);
List
<
SmsInfo
>
smsInfos
=
this
.
list
(
wrapper
);
log
.
info
(
"验证短信Provider接口,查询到sms记录:"
+
JSON
.
toJSONString
(
smsInfos
));
//如果找不到记录,提示验证失败
if
(
smsInfos
==
null
||
smsInfos
.
isEmpty
())
{
log
.
info
(
"验证短信Provider接口,找不到验证码记录,响应验证失败!"
);
return
SmsVerifyResult
.
ERROR
;
}
else
{
//获取最近发送的第一条
SmsInfo
smsInfo
=
smsInfos
.
get
(
0
);
//先判断状态是不是失效的状态
if
(
SmsSendStatus
.
INVALID
.
getCode
().
equals
(
smsInfo
.
getStatus
()))
{
log
.
info
(
"验证短信Provider接口,短信状态是失效,响应验证失败!"
);
return
SmsVerifyResult
.
ERROR
;
}
//如果验证码和传过来的不一致
if
(!
verifySMSParam
.
getCode
().
equals
(
smsInfo
.
getValidateCode
()))
{
log
.
info
(
"验证短信Provider接口,验证手机号和验证码不一致,响应验证失败!"
);
return
SmsVerifyResult
.
ERROR
;
}
//判断是否超时
Date
invalidTime
=
smsInfo
.
getInvalidTime
();
if
(
invalidTime
==
null
||
new
Date
().
after
(
invalidTime
))
{
log
.
info
(
"验证短信Provider接口,验证码超时,响应验证失败!"
);
return
SmsVerifyResult
.
EXPIRED
;
}
//验证成功把短信设置成失效
smsInfo
.
setStatus
(
SmsSendStatus
.
INVALID
.
getCode
());
this
.
updateById
(
smsInfo
);
log
.
info
(
"验证短信Provider接口,验证码验证成功!"
);
return
SmsVerifyResult
.
SUCCESS
;
}
}
}
guns-base-sms/src/main/java/org/json/JSON.java
0 → 100644
View file @
7f4f3d7c
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org
.
json
;
class
JSON
{
/**
* Returns the input if it is a JSON-permissible value; throws otherwise.
*/
static
double
checkDouble
(
double
d
)
throws
JSONException
{
if
(
Double
.
isInfinite
(
d
)
||
Double
.
isNaN
(
d
))
{
throw
new
JSONException
(
"Forbidden numeric value: "
+
d
);
}
return
d
;
}
static
Boolean
toBoolean
(
Object
value
)
{
if
(
value
instanceof
Boolean
)
{
return
(
Boolean
)
value
;
}
else
if
(
value
instanceof
String
)
{
String
stringValue
=
(
String
)
value
;
if
(
"true"
.
equalsIgnoreCase
(
stringValue
))
{
return
true
;
}
else
if
(
"false"
.
equalsIgnoreCase
(
stringValue
))
{
return
false
;
}
}
return
null
;
}
static
Double
toDouble
(
Object
value
)
{
if
(
value
instanceof
Double
)
{
return
(
Double
)
value
;
}
else
if
(
value
instanceof
Number
)
{
return
((
Number
)
value
).
doubleValue
();
}
else
if
(
value
instanceof
String
)
{
try
{
return
Double
.
valueOf
((
String
)
value
);
}
catch
(
NumberFormatException
ignored
)
{
}
}
return
null
;
}
static
Integer
toInteger
(
Object
value
)
{
if
(
value
instanceof
Integer
)
{
return
(
Integer
)
value
;
}
else
if
(
value
instanceof
Number
)
{
return
((
Number
)
value
).
intValue
();
}
else
if
(
value
instanceof
String
)
{
try
{
return
(
int
)
Double
.
parseDouble
((
String
)
value
);
}
catch
(
NumberFormatException
ignored
)
{
}
}
return
null
;
}
static
Long
toLong
(
Object
value
)
{
if
(
value
instanceof
Long
)
{
return
(
Long
)
value
;
}
else
if
(
value
instanceof
Number
)
{
return
((
Number
)
value
).
longValue
();
}
else
if
(
value
instanceof
String
)
{
try
{
return
(
long
)
Double
.
parseDouble
((
String
)
value
);
}
catch
(
NumberFormatException
ignored
)
{
}
}
return
null
;
}
static
String
toString
(
Object
value
)
{
if
(
value
instanceof
String
)
{
return
(
String
)
value
;
}
else
if
(
value
!=
null
)
{
return
String
.
valueOf
(
value
);
}
return
null
;
}
public
static
JSONException
typeMismatch
(
Object
indexOrName
,
Object
actual
,
String
requiredType
)
throws
JSONException
{
if
(
actual
==
null
)
{
throw
new
JSONException
(
"Value at "
+
indexOrName
+
" is null."
);
}
else
{
throw
new
JSONException
(
"Value "
+
actual
+
" at "
+
indexOrName
+
" of type "
+
actual
.
getClass
().
getName
()
+
" cannot be converted to "
+
requiredType
);
}
}
public
static
JSONException
typeMismatch
(
Object
actual
,
String
requiredType
)
throws
JSONException
{
if
(
actual
==
null
)
{
throw
new
JSONException
(
"Value is null."
);
}
else
{
throw
new
JSONException
(
"Value "
+
actual
+
" of type "
+
actual
.
getClass
().
getName
()
+
" cannot be converted to "
+
requiredType
);
}
}
}
guns-base-sms/src/main/java/org/json/JSONArray.java
0 → 100644
View file @
7f4f3d7c
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org
.
json
;
import
java.lang.reflect.Array
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.Iterator
;
import
java.util.List
;
// Note: this class was written without inspecting the non-free org.json sourcecode.
/**
* A dense indexed sequence of values. Values may be any mix of
* {@link JSONObject JSONObjects}, other {@link JSONArray JSONArrays}, Strings,
* Booleans, Integers, Longs, Doubles, {@code null} or {@link JSONObject#NULL}.
* Values may not be {@link Double#isNaN() NaNs}, {@link Double#isInfinite()
* infinities}, or of any type not listed here.
*
* <p>{@code JSONArray} has the same type coercion behavior and
* optional/mandatory accessors as {@link JSONObject}. See that class'
* documentation for details.
*
* <p><strong>Warning:</strong> this class represents null in two incompatible
* ways: the standard Java {@code null} reference, and the sentinel value {@link
* JSONObject#NULL}. In particular, {@code get} fails if the requested index
* holds the null reference, but succeeds if it holds {@code JSONObject.NULL}.
*
* <p>Instances of this class are not thread safe. Although this class is
* nonfinal, it was not designed for inheritance and should not be subclassed.
* In particular, self-use by overridable methods is not specified. See
* <i>Effective Java</i> Item 17, "Design and Document or inheritance or else
* prohibit it" for further information.
*/
public
class
JSONArray
{
private
final
List
<
Object
>
values
;
/**
* Creates a {@code JSONArray} with no values.
*/
public
JSONArray
()
{
values
=
new
ArrayList
<
Object
>();
}
/**
* Creates a new {@code JSONArray} by copying all values from the given
* collection.
*
* @param copyFrom a collection whose values are of supported types.
* Unsupported values are not permitted and will yield an array in an
* inconsistent state.
*/
/* Accept a raw type for API compatibility */
public
JSONArray
(
Collection
copyFrom
)
{
this
();
if
(
copyFrom
!=
null
)
{
for
(
Iterator
it
=
copyFrom
.
iterator
();
it
.
hasNext
();
)
{
put
(
JSONObject
.
wrap
(
it
.
next
()));
}
}
}
/**
* Creates a new {@code JSONArray} with values from the next array in the
* tokener.
*
* @param readFrom a tokener whose nextValue() method will yield a
* {@code JSONArray}.
* @throws JSONException if the parse fails or doesn't yield a
* {@code JSONArray}.
*/
public
JSONArray
(
JSONTokener
readFrom
)
throws
JSONException
{
/*
* Getting the parser to populate this could get tricky. Instead, just
* parse to temporary JSONArray and then steal the data from that.
*/
Object
object
=
readFrom
.
nextValue
();
if
(
object
instanceof
JSONArray
)
{
values
=
((
JSONArray
)
object
).
values
;
}
else
{
throw
JSON
.
typeMismatch
(
object
,
"JSONArray"
);
}
}
/**
* Creates a new {@code JSONArray} with values from the JSON string.
*
* @param json a JSON-encoded string containing an array.
* @throws JSONException if the parse fails or doesn't yield a {@code
* JSONArray}.
*/
public
JSONArray
(
String
json
)
throws
JSONException
{
this
(
new
JSONTokener
(
json
));
}
/**
* Creates a new {@code JSONArray} with values from the given primitive array.
*/
public
JSONArray
(
Object
array
)
throws
JSONException
{
if
(!
array
.
getClass
().
isArray
())
{
throw
new
JSONException
(
"Not a primitive array: "
+
array
.
getClass
());
}
final
int
length
=
Array
.
getLength
(
array
);
values
=
new
ArrayList
<
Object
>(
length
);
for
(
int
i
=
0
;
i
<
length
;
++
i
)
{
put
(
JSONObject
.
wrap
(
Array
.
get
(
array
,
i
)));
}
}
/**
* Returns the number of values in this array.
*/
public
int
length
()
{
return
values
.
size
();
}
/**
* Appends {@code value} to the end of this array.
*
* @return this array.
*/
public
JSONArray
put
(
boolean
value
)
{
values
.
add
(
value
);
return
this
;
}
/**
* Appends {@code value} to the end of this array.
*
* @param value a finite value. May not be {@link Double#isNaN() NaNs} or
* {@link Double#isInfinite() infinities}.
* @return this array.
*/
public
JSONArray
put
(
double
value
)
throws
JSONException
{
values
.
add
(
JSON
.
checkDouble
(
value
));
return
this
;
}
/**
* Appends {@code value} to the end of this array.
*
* @return this array.
*/
public
JSONArray
put
(
int
value
)
{
values
.
add
(
value
);
return
this
;
}
/**
* Appends {@code value} to the end of this array.
*
* @return this array.
*/
public
JSONArray
put
(
long
value
)
{
values
.
add
(
value
);
return
this
;
}
/**
* Appends {@code value} to the end of this array.
*
* @param value a {@link JSONObject}, {@link JSONArray}, String, Boolean,
* Integer, Long, Double, {@link JSONObject#NULL}, or {@code null}. May
* not be {@link Double#isNaN() NaNs} or {@link Double#isInfinite()
* infinities}. Unsupported values are not permitted and will cause the
* array to be in an inconsistent state.
* @return this array.
*/
public
JSONArray
put
(
Object
value
)
{
values
.
add
(
value
);
return
this
;
}
/**
* Sets the value at {@code index} to {@code value}, null padding this array
* to the required length if necessary. If a value already exists at {@code
* index}, it will be replaced.
*
* @return this array.
*/
public
JSONArray
put
(
int
index
,
boolean
value
)
throws
JSONException
{
return
put
(
index
,
(
Boolean
)
value
);
}
/**
* Sets the value at {@code index} to {@code value}, null padding this array
* to the required length if necessary. If a value already exists at {@code
* index}, it will be replaced.
*
* @param value a finite value. May not be {@link Double#isNaN() NaNs} or
* {@link Double#isInfinite() infinities}.
* @return this array.
*/
public
JSONArray
put
(
int
index
,
double
value
)
throws
JSONException
{
return
put
(
index
,
(
Double
)
value
);
}
/**
* Sets the value at {@code index} to {@code value}, null padding this array
* to the required length if necessary. If a value already exists at {@code
* index}, it will be replaced.
*
* @return this array.
*/
public
JSONArray
put
(
int
index
,
int
value
)
throws
JSONException
{
return
put
(
index
,
(
Integer
)
value
);
}
/**
* Sets the value at {@code index} to {@code value}, null padding this array
* to the required length if necessary. If a value already exists at {@code
* index}, it will be replaced.
*
* @return this array.
*/
public
JSONArray
put
(
int
index
,
long
value
)
throws
JSONException
{
return
put
(
index
,
(
Long
)
value
);
}
/**
* Sets the value at {@code index} to {@code value}, null padding this array
* to the required length if necessary. If a value already exists at {@code
* index}, it will be replaced.
*
* @param value a {@link JSONObject}, {@link JSONArray}, String, Boolean,
* Integer, Long, Double, {@link JSONObject#NULL}, or {@code null}. May
* not be {@link Double#isNaN() NaNs} or {@link Double#isInfinite()
* infinities}.
* @return this array.
*/
public
JSONArray
put
(
int
index
,
Object
value
)
throws
JSONException
{
if
(
value
instanceof
Number
)
{
// deviate from the original by checking all Numbers, not just floats & doubles
JSON
.
checkDouble
(((
Number
)
value
).
doubleValue
());
}
while
(
values
.
size
()
<=
index
)
{
values
.
add
(
null
);
}
values
.
set
(
index
,
value
);
return
this
;
}
/**
* Returns true if this array has no value at {@code index}, or if its value
* is the {@code null} reference or {@link JSONObject#NULL}.
*/
public
boolean
isNull
(
int
index
)
{
Object
value
=
opt
(
index
);
return
value
==
null
||
value
==
JSONObject
.
NULL
;
}
/**
* Returns the value at {@code index}.
*
* @throws JSONException if this array has no value at {@code index}, or if
* that value is the {@code null} reference. This method returns
* normally if the value is {@code JSONObject#NULL}.
*/
public
Object
get
(
int
index
)
throws
JSONException
{
try
{
Object
value
=
values
.
get
(
index
);
if
(
value
==
null
)
{
throw
new
JSONException
(
"Value at "
+
index
+
" is null."
);
}
return
value
;
}
catch
(
IndexOutOfBoundsException
e
)
{
throw
new
JSONException
(
"Index "
+
index
+
" out of range [0.."
+
values
.
size
()
+
")"
);
}
}
/**
* Returns the value at {@code index}, or null if the array has no value
* at {@code index}.
*/
public
Object
opt
(
int
index
)
{
if
(
index
<
0
||
index
>=
values
.
size
())
{
return
null
;
}
return
values
.
get
(
index
);
}
/**
* Removes and returns the value at {@code index}, or null if the array has no value
* at {@code index}.
*/
public
Object
remove
(
int
index
)
{
if
(
index
<
0
||
index
>=
values
.
size
())
{
return
null
;
}
return
values
.
remove
(
index
);
}
/**
* Returns the value at {@code index} if it exists and is a boolean or can
* be coerced to a boolean.
*
* @throws JSONException if the value at {@code index} doesn't exist or
* cannot be coerced to a boolean.
*/
public
boolean
getBoolean
(
int
index
)
throws
JSONException
{
Object
object
=
get
(
index
);
Boolean
result
=
JSON
.
toBoolean
(
object
);
if
(
result
==
null
)
{
throw
JSON
.
typeMismatch
(
index
,
object
,
"boolean"
);
}
return
result
;
}
/**
* Returns the value at {@code index} if it exists and is a boolean or can
* be coerced to a boolean. Returns false otherwise.
*/
public
boolean
optBoolean
(
int
index
)
{
return
optBoolean
(
index
,
false
);
}
/**
* Returns the value at {@code index} if it exists and is a boolean or can
* be coerced to a boolean. Returns {@code fallback} otherwise.
*/
public
boolean
optBoolean
(
int
index
,
boolean
fallback
)
{
Object
object
=
opt
(
index
);
Boolean
result
=
JSON
.
toBoolean
(
object
);
return
result
!=
null
?
result
:
fallback
;
}
/**
* Returns the value at {@code index} if it exists and is a double or can
* be coerced to a double.
*
* @throws JSONException if the value at {@code index} doesn't exist or
* cannot be coerced to a double.
*/
public
double
getDouble
(
int
index
)
throws
JSONException
{
Object
object
=
get
(
index
);
Double
result
=
JSON
.
toDouble
(
object
);
if
(
result
==
null
)
{
throw
JSON
.
typeMismatch
(
index
,
object
,
"double"
);
}
return
result
;
}
/**
* Returns the value at {@code index} if it exists and is a double or can
* be coerced to a double. Returns {@code NaN} otherwise.
*/
public
double
optDouble
(
int
index
)
{
return
optDouble
(
index
,
Double
.
NaN
);
}
/**
* Returns the value at {@code index} if it exists and is a double or can
* be coerced to a double. Returns {@code fallback} otherwise.
*/
public
double
optDouble
(
int
index
,
double
fallback
)
{
Object
object
=
opt
(
index
);
Double
result
=
JSON
.
toDouble
(
object
);
return
result
!=
null
?
result
:
fallback
;
}
/**
* Returns the value at {@code index} if it exists and is an int or
* can be coerced to an int.
*
* @throws JSONException if the value at {@code index} doesn't exist or
* cannot be coerced to a int.
*/
public
int
getInt
(
int
index
)
throws
JSONException
{
Object
object
=
get
(
index
);
Integer
result
=
JSON
.
toInteger
(
object
);
if
(
result
==
null
)
{
throw
JSON
.
typeMismatch
(
index
,
object
,
"int"
);
}
return
result
;
}
/**
* Returns the value at {@code index} if it exists and is an int or
* can be coerced to an int. Returns 0 otherwise.
*/
public
int
optInt
(
int
index
)
{
return
optInt
(
index
,
0
);
}
/**
* Returns the value at {@code index} if it exists and is an int or
* can be coerced to an int. Returns {@code fallback} otherwise.
*/
public
int
optInt
(
int
index
,
int
fallback
)
{
Object
object
=
opt
(
index
);
Integer
result
=
JSON
.
toInteger
(
object
);
return
result
!=
null
?
result
:
fallback
;
}
/**
* Returns the value at {@code index} if it exists and is a long or
* can be coerced to a long.
*
* @throws JSONException if the value at {@code index} doesn't exist or
* cannot be coerced to a long.
*/
public
long
getLong
(
int
index
)
throws
JSONException
{
Object
object
=
get
(
index
);
Long
result
=
JSON
.
toLong
(
object
);
if
(
result
==
null
)
{
throw
JSON
.
typeMismatch
(
index
,
object
,
"long"
);
}
return
result
;
}
/**
* Returns the value at {@code index} if it exists and is a long or
* can be coerced to a long. Returns 0 otherwise.
*/
public
long
optLong
(
int
index
)
{
return
optLong
(
index
,
0L
);
}
/**
* Returns the value at {@code index} if it exists and is a long or
* can be coerced to a long. Returns {@code fallback} otherwise.
*/
public
long
optLong
(
int
index
,
long
fallback
)
{
Object
object
=
opt
(
index
);
Long
result
=
JSON
.
toLong
(
object
);
return
result
!=
null
?
result
:
fallback
;
}
/**
* Returns the value at {@code index} if it exists, coercing it if
* necessary.
*
* @throws JSONException if no such value exists.
*/
public
String
getString
(
int
index
)
throws
JSONException
{
Object
object
=
get
(
index
);
String
result
=
JSON
.
toString
(
object
);
if
(
result
==
null
)
{
throw
JSON
.
typeMismatch
(
index
,
object
,
"String"
);
}
return
result
;
}
/**
* Returns the value at {@code index} if it exists, coercing it if
* necessary. Returns the empty string if no such value exists.
*/
public
String
optString
(
int
index
)
{
return
optString
(
index
,
""
);
}
/**
* Returns the value at {@code index} if it exists, coercing it if
* necessary. Returns {@code fallback} if no such value exists.
*/
public
String
optString
(
int
index
,
String
fallback
)
{
Object
object
=
opt
(
index
);
String
result
=
JSON
.
toString
(
object
);
return
result
!=
null
?
result
:
fallback
;
}
/**
* Returns the value at {@code index} if it exists and is a {@code
* JSONArray}.
*
* @throws JSONException if the value doesn't exist or is not a {@code
* JSONArray}.
*/
public
JSONArray
getJSONArray
(
int
index
)
throws
JSONException
{
Object
object
=
get
(
index
);
if
(
object
instanceof
JSONArray
)
{
return
(
JSONArray
)
object
;
}
else
{
throw
JSON
.
typeMismatch
(
index
,
object
,
"JSONArray"
);
}
}
/**
* Returns the value at {@code index} if it exists and is a {@code
* JSONArray}. Returns null otherwise.
*/
public
JSONArray
optJSONArray
(
int
index
)
{
Object
object
=
opt
(
index
);
return
object
instanceof
JSONArray
?
(
JSONArray
)
object
:
null
;
}
/**
* Returns the value at {@code index} if it exists and is a {@code
* JSONObject}.
*
* @throws JSONException if the value doesn't exist or is not a {@code
* JSONObject}.
*/
public
JSONObject
getJSONObject
(
int
index
)
throws
JSONException
{
Object
object
=
get
(
index
);
if
(
object
instanceof
JSONObject
)
{
return
(
JSONObject
)
object
;
}
else
{
throw
JSON
.
typeMismatch
(
index
,
object
,
"JSONObject"
);
}
}
/**
* Returns the value at {@code index} if it exists and is a {@code
* JSONObject}. Returns null otherwise.
*/
public
JSONObject
optJSONObject
(
int
index
)
{
Object
object
=
opt
(
index
);
return
object
instanceof
JSONObject
?
(
JSONObject
)
object
:
null
;
}
/**
* Returns a new object whose values are the values in this array, and whose
* names are the values in {@code names}. Names and values are paired up by
* index from 0 through to the shorter array's length. Names that are not
* strings will be coerced to strings. This method returns null if either
* array is empty.
*/
public
JSONObject
toJSONObject
(
JSONArray
names
)
throws
JSONException
{
JSONObject
result
=
new
JSONObject
();
int
length
=
Math
.
min
(
names
.
length
(),
values
.
size
());
if
(
length
==
0
)
{
return
null
;
}
for
(
int
i
=
0
;
i
<
length
;
i
++)
{
String
name
=
JSON
.
toString
(
names
.
opt
(
i
));
result
.
put
(
name
,
opt
(
i
));
}
return
result
;
}
/**
* Returns a new string by alternating this array's values with {@code
* separator}. This array's string values are quoted and have their special
* characters escaped. For example, the array containing the strings '12"
* pizza', 'taco' and 'soda' joined on '+' returns this:
* <pre>"12\" pizza"+"taco"+"soda"</pre>
*/
public
String
join
(
String
separator
)
throws
JSONException
{
JSONStringer
stringer
=
new
JSONStringer
();
stringer
.
open
(
JSONStringer
.
Scope
.
NULL
,
""
);
for
(
int
i
=
0
,
size
=
values
.
size
();
i
<
size
;
i
++)
{
if
(
i
>
0
)
{
stringer
.
out
.
append
(
separator
);
}
stringer
.
value
(
values
.
get
(
i
));
}
stringer
.
close
(
JSONStringer
.
Scope
.
NULL
,
JSONStringer
.
Scope
.
NULL
,
""
);
return
stringer
.
out
.
toString
();
}
/**
* Encodes this array as a compact JSON string, such as:
* <pre>[94043,90210]</pre>
*/
@Override
public
String
toString
()
{
try
{
JSONStringer
stringer
=
new
JSONStringer
();
writeTo
(
stringer
);
return
stringer
.
toString
();
}
catch
(
JSONException
e
)
{
return
null
;
}
}
/**
* Encodes this array as a human readable JSON string for debugging, such
* as:
* <pre>
* [
* 94043,
* 90210
* ]</pre>
*
* @param indentSpaces the number of spaces to indent for each level of
* nesting.
*/
public
String
toString
(
int
indentSpaces
)
throws
JSONException
{
JSONStringer
stringer
=
new
JSONStringer
(
indentSpaces
);
writeTo
(
stringer
);
return
stringer
.
toString
();
}
void
writeTo
(
JSONStringer
stringer
)
throws
JSONException
{
stringer
.
array
();
for
(
Object
value
:
values
)
{
stringer
.
value
(
value
);
}
stringer
.
endArray
();
}
@Override
public
boolean
equals
(
Object
o
)
{
return
o
instanceof
JSONArray
&&
((
JSONArray
)
o
).
values
.
equals
(
values
);
}
@Override
public
int
hashCode
()
{
// diverge from the original, which doesn't implement hashCode
return
values
.
hashCode
();
}
public
Iterator
<
Object
>
iterator
()
{
return
values
.
iterator
();
}
}
guns-base-sms/src/main/java/org/json/JSONException.java
0 → 100644
View file @
7f4f3d7c
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org
.
json
;
// Note: this class was written without inspecting the non-free org.json sourcecode.
/**
* Thrown to indicate a problem with the JSON API. Such problems include:
* <ul>
* <li>Attempts to parse or construct malformed documents
* <li>Use of null as a name
* <li>Use of numeric types not available to JSON, such as {@link
* Double#isNaN() NaNs} or {@link Double#isInfinite() infinities}.
* <li>Lookups using an out of range index or nonexistent name
* <li>Type mismatches on lookups
* </ul>
*
* <p>Although this is a checked exception, it is rarely recoverable. Most
* callers should simply wrap this exception in an unchecked exception and
* rethrow:
* <pre> public JSONArray toJSONObject() {
* try {
* JSONObject result = new JSONObject();
* ...
* } catch (JSONException e) {
* throw new RuntimeException(e);
* }
* }</pre>
*/
public
class
JSONException
extends
Exception
{
public
JSONException
(
String
s
)
{
super
(
s
);
}
}
guns-base-sms/src/main/java/org/json/JSONObject.java
0 → 100644
View file @
7f4f3d7c
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org
.
json
;
import
java.util.*
;
// Note: this class was written without inspecting the non-free org.json sourcecode.
/**
* A modifiable set of name/value mappings. Names are unique, non-null strings.
* Values may be any mix of {@link JSONObject JSONObjects}, {@link JSONArray
* JSONArrays}, Strings, Booleans, Integers, Longs, Doubles or {@link #NULL}.
* Values may not be {@code null}, {@link Double#isNaN() NaNs}, {@link
* Double#isInfinite() infinities}, or of any type not listed here.
*
* <p>This class can coerce values to another type when requested.
* <ul>
* <li>When the requested type is a boolean, strings will be coerced using a
* case-insensitive comparison to "true" and "false".
* <li>When the requested type is a double, other {@link Number} types will
* be coerced using {@link Number#doubleValue() doubleValue}. Strings
* that can be coerced using {@link Double#valueOf(String)} will be.
* <li>When the requested type is an int, other {@link Number} types will
* be coerced using {@link Number#intValue() intValue}. Strings
* that can be coerced using {@link Double#valueOf(String)} will be,
* and then cast to int.
* <li><a name="lossy">When the requested type is a long, other {@link Number} types will
* be coerced using {@link Number#longValue() longValue}. Strings
* that can be coerced using {@link Double#valueOf(String)} will be,
* and then cast to long. This two-step conversion is lossy for very
* large values. For example, the string "9223372036854775806" yields the
* long 9223372036854775807.</a>
* <li>When the requested type is a String, other non-null values will be
* coerced using {@link String#valueOf(Object)}. Although null cannot be
* coerced, the sentinel value {@link JSONObject#NULL} is coerced to the
* string "null".
* </ul>
*
* <p>This class can look up both mandatory and optional values:
* <ul>
* <li>Use <code>get<i>Type</i>()</code> to retrieve a mandatory value. This
* fails with a {@code JSONException} if the requested name has no value
* or if the value cannot be coerced to the requested type.
* <li>Use <code>opt<i>Type</i>()</code> to retrieve an optional value. This
* returns a system- or user-supplied default if the requested name has no
* value or if the value cannot be coerced to the requested type.
* </ul>
*
* <p><strong>Warning:</strong> this class represents null in two incompatible
* ways: the standard Java {@code null} reference, and the sentinel value {@link
* JSONObject#NULL}. In particular, calling {@code put(name, null)} removes the
* named entry from the object but {@code put(name, JSONObject.NULL)} stores an
* entry whose value is {@code JSONObject.NULL}.
*
* <p>Instances of this class are not thread safe. Although this class is
* nonfinal, it was not designed for inheritance and should not be subclassed.
* In particular, self-use by overrideable methods is not specified. See
* <i>Effective Java</i> Item 17, "Design and Document or inheritance or else
* prohibit it" for further information.
*/
public
class
JSONObject
{
private
static
final
Double
NEGATIVE_ZERO
=
-
0
d
;
/**
* A sentinel value used to explicitly define a name with no value. Unlike
* {@code null}, names with this value:
* <ul>
* <li>show up in the {@link #names} array
* <li>show up in the {@link #keys} iterator
* <li>return {@code true} for {@link #has(String)}
* <li>do not throw on {@link #get(String)}
* <li>are included in the encoded JSON string.
* </ul>
*
* <p>This value violates the general contract of {@link Object#equals} by
* returning true when compared to {@code null}. Its {@link #toString}
* method returns "null".
*/
public
static
final
Object
NULL
=
new
Object
()
{
@Override
public
boolean
equals
(
Object
o
)
{
return
o
==
this
||
o
==
null
;
// API specifies this broken equals implementation
}
@Override
public
String
toString
()
{
return
"null"
;
}
};
private
final
Map
<
String
,
Object
>
nameValuePairs
;
/**
* Creates a {@code JSONObject} with no name/value mappings.
*/
public
JSONObject
()
{
nameValuePairs
=
new
HashMap
<
String
,
Object
>();
}
/**
* Creates a new {@code JSONObject} by copying all name/value mappings from
* the given map.
*
* @param copyFrom a map whose keys are of type {@link String} and whose
* values are of supported types.
* @throws NullPointerException if any of the map's keys are null.
*/
/* (accept a raw type for API compatibility) */
public
JSONObject
(
Map
copyFrom
)
{
this
();
Map
<?,
?>
contentsTyped
=
(
Map
<?,
?>)
copyFrom
;
for
(
Map
.
Entry
<?,
?>
entry
:
contentsTyped
.
entrySet
())
{
/*
* Deviate from the original by checking that keys are non-null and
* of the proper type. (We still defer validating the values).
*/
String
key
=
(
String
)
entry
.
getKey
();
if
(
key
==
null
)
{
throw
new
NullPointerException
(
"key == null"
);
}
nameValuePairs
.
put
(
key
,
wrap
(
entry
.
getValue
()));
}
}
/**
* Creates a new {@code JSONObject} with name/value mappings from the next
* object in the tokener.
*
* @param readFrom a tokener whose nextValue() method will yield a
* {@code JSONObject}.
* @throws JSONException if the parse fails or doesn't yield a
* {@code JSONObject}.
*/
public
JSONObject
(
JSONTokener
readFrom
)
throws
JSONException
{
/*
* Getting the parser to populate this could get tricky. Instead, just
* parse to temporary JSONObject and then steal the data from that.
*/
Object
object
=
readFrom
.
nextValue
();
if
(
object
instanceof
JSONObject
)
{
this
.
nameValuePairs
=
((
JSONObject
)
object
).
nameValuePairs
;
}
else
{
throw
JSON
.
typeMismatch
(
object
,
"JSONObject"
);
}
}
/**
* Creates a new {@code JSONObject} with name/value mappings from the JSON
* string.
*
* @param json a JSON-encoded string containing an object.
* @throws JSONException if the parse fails or doesn't yield a {@code
* JSONObject}.
*/
public
JSONObject
(
String
json
)
throws
JSONException
{
this
(
new
JSONTokener
(
json
));
}
/**
* Creates a new {@code JSONObject} by copying mappings for the listed names
* from the given object. Names that aren't present in {@code copyFrom} will
* be skipped.
*/
public
JSONObject
(
JSONObject
copyFrom
,
String
[]
names
)
throws
JSONException
{
this
();
for
(
String
name
:
names
)
{
Object
value
=
copyFrom
.
opt
(
name
);
if
(
value
!=
null
)
{
nameValuePairs
.
put
(
name
,
value
);
}
}
}
/**
* Returns the number of name/value mappings in this object.
*/
public
int
length
()
{
return
nameValuePairs
.
size
();
}
/**
* Maps {@code name} to {@code value}, clobbering any existing name/value
* mapping with the same name.
*
* @return this object.
*/
public
JSONObject
put
(
String
name
,
boolean
value
)
throws
JSONException
{
nameValuePairs
.
put
(
checkName
(
name
),
value
);
return
this
;
}
/**
* Maps {@code name} to {@code value}, clobbering any existing name/value
* mapping with the same name.
*
* @param value a finite value. May not be {@link Double#isNaN() NaNs} or
* {@link Double#isInfinite() infinities}.
* @return this object.
*/
public
JSONObject
put
(
String
name
,
double
value
)
throws
JSONException
{
nameValuePairs
.
put
(
checkName
(
name
),
JSON
.
checkDouble
(
value
));
return
this
;
}
/**
* Maps {@code name} to {@code value}, clobbering any existing name/value
* mapping with the same name.
*
* @return this object.
*/
public
JSONObject
put
(
String
name
,
int
value
)
throws
JSONException
{
nameValuePairs
.
put
(
checkName
(
name
),
value
);
return
this
;
}
/**
* Maps {@code name} to {@code value}, clobbering any existing name/value
* mapping with the same name.
*
* @return this object.
*/
public
JSONObject
put
(
String
name
,
long
value
)
throws
JSONException
{
nameValuePairs
.
put
(
checkName
(
name
),
value
);
return
this
;
}
/**
* Maps {@code name} to {@code value}, clobbering any existing name/value
* mapping with the same name. If the value is {@code null}, any existing
* mapping for {@code name} is removed.
*
* @param value a {@link JSONObject}, {@link JSONArray}, String, Boolean,
* Integer, Long, Double, {@link #NULL}, or {@code null}. May not be
* {@link Double#isNaN() NaNs} or {@link Double#isInfinite()
* infinities}.
* @return this object.
*/
public
JSONObject
put
(
String
name
,
Object
value
)
throws
JSONException
{
if
(
value
==
null
)
{
nameValuePairs
.
remove
(
name
);
return
this
;
}
if
(
value
instanceof
Number
)
{
// deviate from the original by checking all Numbers, not just floats & doubles
JSON
.
checkDouble
(((
Number
)
value
).
doubleValue
());
}
nameValuePairs
.
put
(
checkName
(
name
),
value
);
return
this
;
}
/**
* Equivalent to {@code put(name, value)} when both parameters are non-null;
* does nothing otherwise.
*/
public
JSONObject
putOpt
(
String
name
,
Object
value
)
throws
JSONException
{
if
(
name
==
null
||
value
==
null
)
{
return
this
;
}
return
put
(
name
,
value
);
}
/**
* Appends {@code value} to the array already mapped to {@code name}. If
* this object has no mapping for {@code name}, this inserts a new mapping.
* If the mapping exists but its value is not an array, the existing
* and new values are inserted in order into a new array which is itself
* mapped to {@code name}. In aggregate, this allows values to be added to a
* mapping one at a time.
*
* @param value a {@link JSONObject}, {@link JSONArray}, String, Boolean,
* Integer, Long, Double, {@link #NULL} or null. May not be {@link
* Double#isNaN() NaNs} or {@link Double#isInfinite() infinities}.
*/
public
JSONObject
accumulate
(
String
name
,
Object
value
)
throws
JSONException
{
Object
current
=
nameValuePairs
.
get
(
checkName
(
name
));
if
(
current
==
null
)
{
return
put
(
name
,
value
);
}
// check in accumulate, since array.put(Object) doesn't do any checking
if
(
value
instanceof
Number
)
{
JSON
.
checkDouble
(((
Number
)
value
).
doubleValue
());
}
if
(
current
instanceof
JSONArray
)
{
JSONArray
array
=
(
JSONArray
)
current
;
array
.
put
(
value
);
}
else
{
JSONArray
array
=
new
JSONArray
();
array
.
put
(
current
);
array
.
put
(
value
);
nameValuePairs
.
put
(
name
,
array
);
}
return
this
;
}
String
checkName
(
String
name
)
throws
JSONException
{
if
(
name
==
null
)
{
throw
new
JSONException
(
"Names must be non-null"
);
}
return
name
;
}
/**
* Removes the named mapping if it exists; does nothing otherwise.
*
* @return the value previously mapped by {@code name}, or null if there was
* no such mapping.
*/
public
Object
remove
(
String
name
)
{
return
nameValuePairs
.
remove
(
name
);
}
/**
* Returns true if this object has no mapping for {@code name} or if it has
* a mapping whose value is {@link #NULL}.
*/
public
boolean
isNull
(
String
name
)
{
Object
value
=
nameValuePairs
.
get
(
name
);
return
value
==
null
||
value
==
NULL
;
}
/**
* Returns true if this object has a mapping for {@code name}. The mapping
* may be {@link #NULL}.
*/
public
boolean
has
(
String
name
)
{
return
nameValuePairs
.
containsKey
(
name
);
}
/**
* Returns the value mapped by {@code name}.
*
* @throws JSONException if no such mapping exists.
*/
public
Object
get
(
String
name
)
throws
JSONException
{
Object
result
=
nameValuePairs
.
get
(
name
);
if
(
result
==
null
)
{
throw
new
JSONException
(
"No value for "
+
name
);
}
return
result
;
}
/**
* Returns the value mapped by {@code name}, or null if no such mapping
* exists.
*/
public
Object
opt
(
String
name
)
{
return
nameValuePairs
.
get
(
name
);
}
/**
* Returns the value mapped by {@code name} if it exists and is a boolean or
* can be coerced to a boolean.
*
* @throws JSONException if the mapping doesn't exist or cannot be coerced
* to a boolean.
*/
public
boolean
getBoolean
(
String
name
)
throws
JSONException
{
Object
object
=
get
(
name
);
Boolean
result
=
JSON
.
toBoolean
(
object
);
if
(
result
==
null
)
{
throw
JSON
.
typeMismatch
(
name
,
object
,
"boolean"
);
}
return
result
;
}
/**
* Returns the value mapped by {@code name} if it exists and is a boolean or
* can be coerced to a boolean. Returns false otherwise.
*/
public
boolean
optBoolean
(
String
name
)
{
return
optBoolean
(
name
,
false
);
}
/**
* Returns the value mapped by {@code name} if it exists and is a boolean or
* can be coerced to a boolean. Returns {@code fallback} otherwise.
*/
public
boolean
optBoolean
(
String
name
,
boolean
fallback
)
{
Object
object
=
opt
(
name
);
Boolean
result
=
JSON
.
toBoolean
(
object
);
return
result
!=
null
?
result
:
fallback
;
}
/**
* Returns the value mapped by {@code name} if it exists and is a double or
* can be coerced to a double.
*
* @throws JSONException if the mapping doesn't exist or cannot be coerced
* to a double.
*/
public
double
getDouble
(
String
name
)
throws
JSONException
{
Object
object
=
get
(
name
);
Double
result
=
JSON
.
toDouble
(
object
);
if
(
result
==
null
)
{
throw
JSON
.
typeMismatch
(
name
,
object
,
"double"
);
}
return
result
;
}
/**
* Returns the value mapped by {@code name} if it exists and is a double or
* can be coerced to a double. Returns {@code NaN} otherwise.
*/
public
double
optDouble
(
String
name
)
{
return
optDouble
(
name
,
Double
.
NaN
);
}
/**
* Returns the value mapped by {@code name} if it exists and is a double or
* can be coerced to a double. Returns {@code fallback} otherwise.
*/
public
double
optDouble
(
String
name
,
double
fallback
)
{
Object
object
=
opt
(
name
);
Double
result
=
JSON
.
toDouble
(
object
);
return
result
!=
null
?
result
:
fallback
;
}
/**
* Returns the value mapped by {@code name} if it exists and is an int or
* can be coerced to an int.
*
* @throws JSONException if the mapping doesn't exist or cannot be coerced
* to an int.
*/
public
int
getInt
(
String
name
)
throws
JSONException
{
Object
object
=
get
(
name
);
Integer
result
=
JSON
.
toInteger
(
object
);
if
(
result
==
null
)
{
throw
JSON
.
typeMismatch
(
name
,
object
,
"int"
);
}
return
result
;
}
/**
* Returns the value mapped by {@code name} if it exists and is an int or
* can be coerced to an int. Returns 0 otherwise.
*/
public
int
optInt
(
String
name
)
{
return
optInt
(
name
,
0
);
}
/**
* Returns the value mapped by {@code name} if it exists and is an int or
* can be coerced to an int. Returns {@code fallback} otherwise.
*/
public
int
optInt
(
String
name
,
int
fallback
)
{
Object
object
=
opt
(
name
);
Integer
result
=
JSON
.
toInteger
(
object
);
return
result
!=
null
?
result
:
fallback
;
}
/**
* Returns the value mapped by {@code name} if it exists and is a long or
* can be coerced to a long. Note that JSON represents numbers as doubles,
* so this is <a href="#lossy">lossy</a>; use strings to transfer numbers via JSON.
*
* @throws JSONException if the mapping doesn't exist or cannot be coerced
* to a long.
*/
public
long
getLong
(
String
name
)
throws
JSONException
{
Object
object
=
get
(
name
);
Long
result
=
JSON
.
toLong
(
object
);
if
(
result
==
null
)
{
throw
JSON
.
typeMismatch
(
name
,
object
,
"long"
);
}
return
result
;
}
/**
* Returns the value mapped by {@code name} if it exists and is a long or
* can be coerced to a long. Returns 0 otherwise. Note that JSON represents numbers as doubles,
* so this is <a href="#lossy">lossy</a>; use strings to transfer numbers via JSON.
*/
public
long
optLong
(
String
name
)
{
return
optLong
(
name
,
0L
);
}
/**
* Returns the value mapped by {@code name} if it exists and is a long or
* can be coerced to a long. Returns {@code fallback} otherwise. Note that JSON represents
* numbers as doubles, so this is <a href="#lossy">lossy</a>; use strings to transfer
* numbers via JSON.
*/
public
long
optLong
(
String
name
,
long
fallback
)
{
Object
object
=
opt
(
name
);
Long
result
=
JSON
.
toLong
(
object
);
return
result
!=
null
?
result
:
fallback
;
}
/**
* Returns the value mapped by {@code name} if it exists, coercing it if
* necessary.
*
* @throws JSONException if no such mapping exists.
*/
public
String
getString
(
String
name
)
throws
JSONException
{
Object
object
=
get
(
name
);
String
result
=
JSON
.
toString
(
object
);
if
(
result
==
null
)
{
throw
JSON
.
typeMismatch
(
name
,
object
,
"String"
);
}
return
result
;
}
/**
* Returns the value mapped by {@code name} if it exists, coercing it if
* necessary. Returns the empty string if no such mapping exists.
*/
public
String
optString
(
String
name
)
{
return
optString
(
name
,
""
);
}
/**
* Returns the value mapped by {@code name} if it exists, coercing it if
* necessary. Returns {@code fallback} if no such mapping exists.
*/
public
String
optString
(
String
name
,
String
fallback
)
{
Object
object
=
opt
(
name
);
String
result
=
JSON
.
toString
(
object
);
return
result
!=
null
?
result
:
fallback
;
}
/**
* Returns the value mapped by {@code name} if it exists and is a {@code
* JSONArray}.
*
* @throws JSONException if the mapping doesn't exist or is not a {@code
* JSONArray}.
*/
public
JSONArray
getJSONArray
(
String
name
)
throws
JSONException
{
Object
object
=
get
(
name
);
if
(
object
instanceof
JSONArray
)
{
return
(
JSONArray
)
object
;
}
else
{
throw
JSON
.
typeMismatch
(
name
,
object
,
"JSONArray"
);
}
}
/**
* Returns the value mapped by {@code name} if it exists and is a {@code
* JSONArray}. Returns null otherwise.
*/
public
JSONArray
optJSONArray
(
String
name
)
{
Object
object
=
opt
(
name
);
return
object
instanceof
JSONArray
?
(
JSONArray
)
object
:
null
;
}
/**
* Returns the value mapped by {@code name} if it exists and is a {@code
* JSONObject}.
*
* @throws JSONException if the mapping doesn't exist or is not a {@code
* JSONObject}.
*/
public
JSONObject
getJSONObject
(
String
name
)
throws
JSONException
{
Object
object
=
get
(
name
);
if
(
object
instanceof
JSONObject
)
{
return
(
JSONObject
)
object
;
}
else
{
throw
JSON
.
typeMismatch
(
name
,
object
,
"JSONObject"
);
}
}
/**
* Returns the value mapped by {@code name} if it exists and is a {@code
* JSONObject}. Returns null otherwise.
*/
public
JSONObject
optJSONObject
(
String
name
)
{
Object
object
=
opt
(
name
);
return
object
instanceof
JSONObject
?
(
JSONObject
)
object
:
null
;
}
/**
* Returns an array with the values corresponding to {@code names}. The
* array contains null for names that aren't mapped. This method returns
* null if {@code names} is either null or empty.
*/
public
JSONArray
toJSONArray
(
JSONArray
names
)
throws
JSONException
{
JSONArray
result
=
new
JSONArray
();
if
(
names
==
null
)
{
return
null
;
}
int
length
=
names
.
length
();
if
(
length
==
0
)
{
return
null
;
}
for
(
int
i
=
0
;
i
<
length
;
i
++)
{
String
name
=
JSON
.
toString
(
names
.
opt
(
i
));
result
.
put
(
opt
(
name
));
}
return
result
;
}
/**
* Returns an iterator of the {@code String} names in this object. The
* returned iterator supports {@link Iterator#remove() remove}, which will
* remove the corresponding mapping from this object. If this object is
* modified after the iterator is returned, the iterator's behavior is
* undefined. The order of the keys is undefined.
*/
/* Return a raw type for API compatibility */
public
Iterator
keys
()
{
return
nameValuePairs
.
keySet
().
iterator
();
}
/**
* Returns an array containing the string names in this object. This method
* returns null if this object contains no mappings.
*/
public
JSONArray
names
()
{
return
nameValuePairs
.
isEmpty
()
?
null
:
new
JSONArray
(
new
ArrayList
<
String
>(
nameValuePairs
.
keySet
()));
}
/**
* Encodes this object as a compact JSON string, such as:
* <pre>{"query":"Pizza","locations":[94043,90210]}</pre>
*/
@Override
public
String
toString
()
{
try
{
JSONStringer
stringer
=
new
JSONStringer
();
writeTo
(
stringer
);
return
stringer
.
toString
();
}
catch
(
JSONException
e
)
{
return
null
;
}
}
/**
* Encodes this object as a human readable JSON string for debugging, such
* as:
* <pre>
* {
* "query": "Pizza",
* "locations": [
* 94043,
* 90210
* ]
* }</pre>
*
* @param indentSpaces the number of spaces to indent for each level of
* nesting.
*/
public
String
toString
(
int
indentSpaces
)
throws
JSONException
{
JSONStringer
stringer
=
new
JSONStringer
(
indentSpaces
);
writeTo
(
stringer
);
return
stringer
.
toString
();
}
void
writeTo
(
JSONStringer
stringer
)
throws
JSONException
{
stringer
.
object
();
for
(
Map
.
Entry
<
String
,
Object
>
entry
:
nameValuePairs
.
entrySet
())
{
stringer
.
key
(
entry
.
getKey
()).
value
(
entry
.
getValue
());
}
stringer
.
endObject
();
}
/**
* Encodes the number as a JSON string.
*
* @param number a finite value. May not be {@link Double#isNaN() NaNs} or
* {@link Double#isInfinite() infinities}.
*/
public
static
String
numberToString
(
Number
number
)
throws
JSONException
{
if
(
number
==
null
)
{
throw
new
JSONException
(
"Number must be non-null"
);
}
double
doubleValue
=
number
.
doubleValue
();
JSON
.
checkDouble
(
doubleValue
);
// the original returns "-0" instead of "-0.0" for negative zero
if
(
number
.
equals
(
NEGATIVE_ZERO
))
{
return
"-0"
;
}
long
longValue
=
number
.
longValue
();
if
(
doubleValue
==
(
double
)
longValue
)
{
return
Long
.
toString
(
longValue
);
}
return
number
.
toString
();
}
/**
* Encodes {@code data} as a JSON string. This applies quotes and any
* necessary character escaping.
*
* @param data the string to encode. Null will be interpreted as an empty
* string.
*/
public
static
String
quote
(
String
data
)
{
if
(
data
==
null
)
{
return
"\"\""
;
}
try
{
JSONStringer
stringer
=
new
JSONStringer
();
stringer
.
open
(
JSONStringer
.
Scope
.
NULL
,
""
);
stringer
.
value
(
data
);
stringer
.
close
(
JSONStringer
.
Scope
.
NULL
,
JSONStringer
.
Scope
.
NULL
,
""
);
return
stringer
.
toString
();
}
catch
(
JSONException
e
)
{
throw
new
AssertionError
();
}
}
/**
* Wraps the given object if necessary.
*
* <p>If the object is null or , returns {@link #NULL}.
* If the object is a {@code JSONArray} or {@code JSONObject}, no wrapping is necessary.
* If the object is {@code NULL}, no wrapping is necessary.
* If the object is an array or {@code Collection}, returns an equivalent {@code JSONArray}.
* If the object is a {@code Map}, returns an equivalent {@code JSONObject}.
* If the object is a primitive wrapper type or {@code String}, returns the object.
* Otherwise if the object is from a {@code java} package, returns the result of {@code toString}.
* If wrapping fails, returns null.
*/
public
static
Object
wrap
(
Object
o
)
{
if
(
o
==
null
)
{
return
NULL
;
}
if
(
o
instanceof
JSONArray
||
o
instanceof
JSONObject
)
{
return
o
;
}
if
(
o
.
equals
(
NULL
))
{
return
o
;
}
try
{
if
(
o
instanceof
Collection
)
{
return
new
JSONArray
((
Collection
)
o
);
}
else
if
(
o
.
getClass
().
isArray
())
{
return
new
JSONArray
(
o
);
}
if
(
o
instanceof
Map
)
{
return
new
JSONObject
((
Map
)
o
);
}
if
(
o
instanceof
Boolean
||
o
instanceof
Byte
||
o
instanceof
Character
||
o
instanceof
Double
||
o
instanceof
Float
||
o
instanceof
Integer
||
o
instanceof
Long
||
o
instanceof
Short
||
o
instanceof
String
)
{
return
o
;
}
if
(
o
.
getClass
().
getPackage
().
getName
().
startsWith
(
"java."
))
{
return
o
.
toString
();
}
}
catch
(
Exception
ignored
)
{
}
return
null
;
}
}
guns-base-sms/src/main/java/org/json/JSONStringer.java
0 → 100644
View file @
7f4f3d7c
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org
.
json
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.List
;
// Note: this class was written without inspecting the non-free org.json sourcecode.
/**
* Implements {@link JSONObject#toString} and {@link JSONArray#toString}. Most
* application developers should use those methods directly and disregard this
* API. For example:<pre>
* JSONObject object = ...
* String json = object.toString();</pre>
*
* <p>Stringers only encode well-formed JSON strings. In particular:
* <ul>
* <li>The stringer must have exactly one top-level array or object.
* <li>Lexical scopes must be balanced: every call to {@link #array} must
* have a matching call to {@link #endArray} and every call to {@link
* #object} must have a matching call to {@link #endObject}.
* <li>Arrays may not contain keys (property names).
* <li>Objects must alternate keys (property names) and values.
* <li>Values are inserted with either literal {@link #value(Object) value}
* calls, or by nesting arrays or objects.
* </ul>
* Calls that would result in a malformed JSON string will fail with a
* {@link JSONException}.
*
* <p>This class provides no facility for pretty-printing (ie. indenting)
* output. To encode indented output, use {@link JSONObject#toString(int)} or
* {@link JSONArray#toString(int)}.
*
* <p>Some implementations of the API support at most 20 levels of nesting.
* Attempts to create more than 20 levels of nesting may fail with a {@link
* JSONException}.
*
* <p>Each stringer may be used to encode a single top level value. Instances of
* this class are not thread safe. Although this class is nonfinal, it was not
* designed for inheritance and should not be subclassed. In particular,
* self-use by overrideable methods is not specified. See <i>Effective Java</i>
* Item 17, "Design and Document or inheritance or else prohibit it" for further
* information.
*/
public
class
JSONStringer
{
/**
* The output data, containing at most one top-level array or object.
*/
final
StringBuilder
out
=
new
StringBuilder
();
/**
* Lexical scoping elements within this stringer, necessary to insert the
* appropriate separator characters (ie. commas and colons) and to detect
* nesting errors.
*/
enum
Scope
{
/**
* An array with no elements requires no separators or newlines before
* it is closed.
*/
EMPTY_ARRAY
,
/**
* A array with at least one value requires a comma and newline before
* the next element.
*/
NONEMPTY_ARRAY
,
/**
* An object with no keys or values requires no separators or newlines
* before it is closed.
*/
EMPTY_OBJECT
,
/**
* An object whose most recent element is a key. The next element must
* be a value.
*/
DANGLING_KEY
,
/**
* An object with at least one name/value pair requires a comma and
* newline before the next element.
*/
NONEMPTY_OBJECT
,
/**
* A special bracketless array needed by JSONStringer.join() and
* JSONObject.quote() only. Not used for JSON encoding.
*/
NULL
,
}
/**
* Unlike the original implementation, this stack isn't limited to 20
* levels of nesting.
*/
private
final
List
<
Scope
>
stack
=
new
ArrayList
<
Scope
>();
/**
* A string containing a full set of spaces for a single level of
* indentation, or null for no pretty printing.
*/
private
final
String
indent
;
public
JSONStringer
()
{
indent
=
null
;
}
JSONStringer
(
int
indentSpaces
)
{
char
[]
indentChars
=
new
char
[
indentSpaces
];
Arrays
.
fill
(
indentChars
,
' '
);
indent
=
new
String
(
indentChars
);
}
/**
* Begins encoding a new array. Each call to this method must be paired with
* a call to {@link #endArray}.
*
* @return this stringer.
*/
public
JSONStringer
array
()
throws
JSONException
{
return
open
(
Scope
.
EMPTY_ARRAY
,
"["
);
}
/**
* Ends encoding the current array.
*
* @return this stringer.
*/
public
JSONStringer
endArray
()
throws
JSONException
{
return
close
(
Scope
.
EMPTY_ARRAY
,
Scope
.
NONEMPTY_ARRAY
,
"]"
);
}
/**
* Begins encoding a new object. Each call to this method must be paired
* with a call to {@link #endObject}.
*
* @return this stringer.
*/
public
JSONStringer
object
()
throws
JSONException
{
return
open
(
Scope
.
EMPTY_OBJECT
,
"{"
);
}
/**
* Ends encoding the current object.
*
* @return this stringer.
*/
public
JSONStringer
endObject
()
throws
JSONException
{
return
close
(
Scope
.
EMPTY_OBJECT
,
Scope
.
NONEMPTY_OBJECT
,
"}"
);
}
/**
* Enters a new scope by appending any necessary whitespace and the given
* bracket.
*/
JSONStringer
open
(
Scope
empty
,
String
openBracket
)
throws
JSONException
{
if
(
stack
.
isEmpty
()
&&
out
.
length
()
>
0
)
{
throw
new
JSONException
(
"Nesting problem: multiple top-level roots"
);
}
beforeValue
();
stack
.
add
(
empty
);
out
.
append
(
openBracket
);
return
this
;
}
/**
* Closes the current scope by appending any necessary whitespace and the
* given bracket.
*/
JSONStringer
close
(
Scope
empty
,
Scope
nonempty
,
String
closeBracket
)
throws
JSONException
{
Scope
context
=
peek
();
if
(
context
!=
nonempty
&&
context
!=
empty
)
{
throw
new
JSONException
(
"Nesting problem"
);
}
stack
.
remove
(
stack
.
size
()
-
1
);
if
(
context
==
nonempty
)
{
newline
();
}
out
.
append
(
closeBracket
);
return
this
;
}
/**
* Returns the value on the top of the stack.
*/
private
Scope
peek
()
throws
JSONException
{
if
(
stack
.
isEmpty
())
{
throw
new
JSONException
(
"Nesting problem"
);
}
return
stack
.
get
(
stack
.
size
()
-
1
);
}
/**
* Replace the value on the top of the stack with the given value.
*/
private
void
replaceTop
(
Scope
topOfStack
)
{
stack
.
set
(
stack
.
size
()
-
1
,
topOfStack
);
}
/**
* Encodes {@code value}.
*
* @param value a {@link JSONObject}, {@link JSONArray}, String, Boolean,
* Integer, Long, Double or null. May not be {@link Double#isNaN() NaNs}
* or {@link Double#isInfinite() infinities}.
* @return this stringer.
*/
public
JSONStringer
value
(
Object
value
)
throws
JSONException
{
if
(
stack
.
isEmpty
())
{
throw
new
JSONException
(
"Nesting problem"
);
}
if
(
value
instanceof
JSONArray
)
{
((
JSONArray
)
value
).
writeTo
(
this
);
return
this
;
}
else
if
(
value
instanceof
JSONObject
)
{
((
JSONObject
)
value
).
writeTo
(
this
);
return
this
;
}
beforeValue
();
if
(
value
==
null
||
value
instanceof
Boolean
||
value
==
JSONObject
.
NULL
)
{
out
.
append
(
value
);
}
else
if
(
value
instanceof
Number
)
{
out
.
append
(
JSONObject
.
numberToString
((
Number
)
value
));
}
else
{
string
(
value
.
toString
());
}
return
this
;
}
/**
* Encodes {@code value} to this stringer.
*
* @return this stringer.
*/
public
JSONStringer
value
(
boolean
value
)
throws
JSONException
{
if
(
stack
.
isEmpty
())
{
throw
new
JSONException
(
"Nesting problem"
);
}
beforeValue
();
out
.
append
(
value
);
return
this
;
}
/**
* Encodes {@code value} to this stringer.
*
* @param value a finite value. May not be {@link Double#isNaN() NaNs} or
* {@link Double#isInfinite() infinities}.
* @return this stringer.
*/
public
JSONStringer
value
(
double
value
)
throws
JSONException
{
if
(
stack
.
isEmpty
())
{
throw
new
JSONException
(
"Nesting problem"
);
}
beforeValue
();
out
.
append
(
JSONObject
.
numberToString
(
value
));
return
this
;
}
/**
* Encodes {@code value} to this stringer.
*
* @return this stringer.
*/
public
JSONStringer
value
(
long
value
)
throws
JSONException
{
if
(
stack
.
isEmpty
())
{
throw
new
JSONException
(
"Nesting problem"
);
}
beforeValue
();
out
.
append
(
value
);
return
this
;
}
private
void
string
(
String
value
)
{
out
.
append
(
"\""
);
for
(
int
i
=
0
,
length
=
value
.
length
();
i
<
length
;
i
++)
{
char
c
=
value
.
charAt
(
i
);
/*
* From RFC 4627, "All Unicode characters may be placed within the
* quotation marks except for the characters that must be escaped:
* quotation mark, reverse solidus, and the control characters
* (U+0000 through U+001F)."
*/
switch
(
c
)
{
case
'"'
:
case
'\\'
:
case
'/'
:
out
.
append
(
'\\'
).
append
(
c
);
break
;
case
'\t'
:
out
.
append
(
"\\t"
);
break
;
case
'\b'
:
out
.
append
(
"\\b"
);
break
;
case
'\n'
:
out
.
append
(
"\\n"
);
break
;
case
'\r'
:
out
.
append
(
"\\r"
);
break
;
case
'\f'
:
out
.
append
(
"\\f"
);
break
;
default
:
if
(
c
<=
0x1F
)
{
out
.
append
(
String
.
format
(
"\\u%04x"
,
(
int
)
c
));
}
else
{
out
.
append
(
c
);
}
break
;
}
}
out
.
append
(
"\""
);
}
private
void
newline
()
{
if
(
indent
==
null
)
{
return
;
}
out
.
append
(
"\n"
);
for
(
int
i
=
0
;
i
<
stack
.
size
();
i
++)
{
out
.
append
(
indent
);
}
}
/**
* Encodes the key (property name) to this stringer.
*
* @param name the name of the forthcoming value. May not be null.
* @return this stringer.
*/
public
JSONStringer
key
(
String
name
)
throws
JSONException
{
if
(
name
==
null
)
{
throw
new
JSONException
(
"Names must be non-null"
);
}
beforeKey
();
string
(
name
);
return
this
;
}
/**
* Inserts any necessary separators and whitespace before a name. Also
* adjusts the stack to expect the key's value.
*/
private
void
beforeKey
()
throws
JSONException
{
Scope
context
=
peek
();
if
(
context
==
Scope
.
NONEMPTY_OBJECT
)
{
// first in object
out
.
append
(
','
);
}
else
if
(
context
!=
Scope
.
EMPTY_OBJECT
)
{
// not in an object!
throw
new
JSONException
(
"Nesting problem"
);
}
newline
();
replaceTop
(
Scope
.
DANGLING_KEY
);
}
/**
* Inserts any necessary separators and whitespace before a literal value,
* inline array, or inline object. Also adjusts the stack to expect either a
* closing bracket or another element.
*/
private
void
beforeValue
()
throws
JSONException
{
if
(
stack
.
isEmpty
())
{
return
;
}
Scope
context
=
peek
();
if
(
context
==
Scope
.
EMPTY_ARRAY
)
{
// first in array
replaceTop
(
Scope
.
NONEMPTY_ARRAY
);
newline
();
}
else
if
(
context
==
Scope
.
NONEMPTY_ARRAY
)
{
// another in array
out
.
append
(
','
);
newline
();
}
else
if
(
context
==
Scope
.
DANGLING_KEY
)
{
// value for key
out
.
append
(
indent
==
null
?
":"
:
": "
);
replaceTop
(
Scope
.
NONEMPTY_OBJECT
);
}
else
if
(
context
!=
Scope
.
NULL
)
{
throw
new
JSONException
(
"Nesting problem"
);
}
}
/**
* Returns the encoded JSON string.
*
* <p>If invoked with unterminated arrays or unclosed objects, this method's
* return value is undefined.
*
* <p><strong>Warning:</strong> although it contradicts the general contract
* of {@link Object#toString}, this method returns null if the stringer
* contains no data.
*/
@Override
public
String
toString
()
{
return
out
.
length
()
==
0
?
null
:
out
.
toString
();
}
}
guns-base-sms/src/main/java/org/json/JSONTokener.java
0 → 100644
View file @
7f4f3d7c
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org
.
json
;
// Note: this class was written without inspecting the non-free org.json sourcecode.
/**
* Parses a JSON (<a href="http://www.ietf.org/rfc/rfc4627.txt">RFC 4627</a>)
* encoded string into the corresponding object. Most clients of
* this class will use only need the {@link #JSONTokener(String) constructor}
* and {@link #nextValue} method. Example usage: <pre>
* String json = "{"
* + " \"query\": \"Pizza\", "
* + " \"locations\": [ 94043, 90210 ] "
* + "}";
*
* JSONObject object = (JSONObject) new JSONTokener(json).nextValue();
* String query = object.getString("query");
* JSONArray locations = object.getJSONArray("locations");</pre>
*
* <p>For best interoperability and performance use JSON that complies with
* RFC 4627, such as that generated by {@link JSONStringer}. For legacy reasons
* this parser is lenient, so a successful parse does not indicate that the
* input string was valid JSON. All of the following syntax errors will be
* ignored:
* <ul>
* <li>End of line comments starting with {@code //} or {@code #} and ending
* with a newline character.
* <li>C-style comments starting with {@code /*} and ending with
* {@code *}{@code /}. Such comments may not be nested.
* <li>Strings that are unquoted or {@code 'single quoted'}.
* <li>Hexadecimal integers prefixed with {@code 0x} or {@code 0X}.
* <li>Octal integers prefixed with {@code 0}.
* <li>Array elements separated by {@code ;}.
* <li>Unnecessary array separators. These are interpreted as if null was the
* omitted value.
* <li>Key-value pairs separated by {@code =} or {@code =>}.
* <li>Key-value pairs separated by {@code ;}.
* </ul>
*
* <p>Each tokener may be used to parse a single JSON string. Instances of this
* class are not thread safe. Although this class is nonfinal, it was not
* designed for inheritance and should not be subclassed. In particular,
* self-use by overrideable methods is not specified. See <i>Effective Java</i>
* Item 17, "Design and Document or inheritance or else prohibit it" for further
* information.
*/
public
class
JSONTokener
{
/**
* The input JSON.
*/
private
final
String
in
;
/**
* The index of the next character to be returned by {@link #next}. When
* the input is exhausted, this equals the input's length.
*/
private
int
pos
;
/**
* @param in JSON encoded string. Null is not permitted and will yield a
* tokener that throws {@code NullPointerExceptions} when methods are
* called.
*/
public
JSONTokener
(
String
in
)
{
// consume an optional byte order mark (BOM) if it exists
if
(
in
!=
null
&&
in
.
startsWith
(
"\ufeff"
))
{
in
=
in
.
substring
(
1
);
}
this
.
in
=
in
;
}
/**
* Returns the next value from the input.
*
* @return a {@link JSONObject}, {@link JSONArray}, String, Boolean,
* Integer, Long, Double or {@link JSONObject#NULL}.
* @throws JSONException if the input is malformed.
*/
public
Object
nextValue
()
throws
JSONException
{
int
c
=
nextCleanInternal
();
switch
(
c
)
{
case
-
1
:
throw
syntaxError
(
"End of input"
);
case
'{'
:
return
readObject
();
case
'['
:
return
readArray
();
case
'\''
:
case
'"'
:
return
nextString
((
char
)
c
);
default
:
pos
--;
return
readLiteral
();
}
}
private
int
nextCleanInternal
()
throws
JSONException
{
while
(
pos
<
in
.
length
())
{
int
c
=
in
.
charAt
(
pos
++);
switch
(
c
)
{
case
'\t'
:
case
' '
:
case
'\n'
:
case
'\r'
:
continue
;
case
'/'
:
if
(
pos
==
in
.
length
())
{
return
c
;
}
char
peek
=
in
.
charAt
(
pos
);
switch
(
peek
)
{
case
'*'
:
// skip a /* c-style comment */
pos
++;
int
commentEnd
=
in
.
indexOf
(
"*/"
,
pos
);
if
(
commentEnd
==
-
1
)
{
throw
syntaxError
(
"Unterminated comment"
);
}
pos
=
commentEnd
+
2
;
continue
;
case
'/'
:
// skip a // end-of-line comment
pos
++;
skipToEndOfLine
();
continue
;
default
:
return
c
;
}
case
'#'
:
/*
* Skip a # hash end-of-line comment. The JSON RFC doesn't
* specify this behavior, but it's required to parse
* existing documents. See http://b/2571423.
*/
skipToEndOfLine
();
continue
;
default
:
return
c
;
}
}
return
-
1
;
}
/**
* Advances the position until after the next newline character. If the line
* is terminated by "\r\n", the '\n' must be consumed as whitespace by the
* caller.
*/
private
void
skipToEndOfLine
()
{
for
(;
pos
<
in
.
length
();
pos
++)
{
char
c
=
in
.
charAt
(
pos
);
if
(
c
==
'\r'
||
c
==
'\n'
)
{
pos
++;
break
;
}
}
}
/**
* Returns the string up to but not including {@code quote}, unescaping any
* character escape sequences encountered along the way. The opening quote
* should have already been read. This consumes the closing quote, but does
* not include it in the returned string.
*
* @param quote either ' or ".
* @throws NumberFormatException if any unicode escape sequences are
* malformed.
*/
public
String
nextString
(
char
quote
)
throws
JSONException
{
/*
* For strings that are free of escape sequences, we can just extract
* the result as a substring of the input. But if we encounter an escape
* sequence, we need to use a StringBuilder to compose the result.
*/
StringBuilder
builder
=
null
;
/* the index of the first character not yet appended to the builder. */
int
start
=
pos
;
while
(
pos
<
in
.
length
())
{
int
c
=
in
.
charAt
(
pos
++);
if
(
c
==
quote
)
{
if
(
builder
==
null
)
{
// a new string avoids leaking memory
return
new
String
(
in
.
substring
(
start
,
pos
-
1
));
}
else
{
builder
.
append
(
in
,
start
,
pos
-
1
);
return
builder
.
toString
();
}
}
if
(
c
==
'\\'
)
{
if
(
pos
==
in
.
length
())
{
throw
syntaxError
(
"Unterminated escape sequence"
);
}
if
(
builder
==
null
)
{
builder
=
new
StringBuilder
();
}
builder
.
append
(
in
,
start
,
pos
-
1
);
builder
.
append
(
readEscapeCharacter
());
start
=
pos
;
}
}
throw
syntaxError
(
"Unterminated string"
);
}
/**
* Unescapes the character identified by the character or characters that
* immediately follow a backslash. The backslash '\' should have already
* been read. This supports both unicode escapes "u000A" and two-character
* escapes "\n".
*
* @throws NumberFormatException if any unicode escape sequences are
* malformed.
*/
private
char
readEscapeCharacter
()
throws
JSONException
{
char
escaped
=
in
.
charAt
(
pos
++);
switch
(
escaped
)
{
case
'u'
:
if
(
pos
+
4
>
in
.
length
())
{
throw
syntaxError
(
"Unterminated escape sequence"
);
}
String
hex
=
in
.
substring
(
pos
,
pos
+
4
);
pos
+=
4
;
return
(
char
)
Integer
.
parseInt
(
hex
,
16
);
case
't'
:
return
'\t'
;
case
'b'
:
return
'\b'
;
case
'n'
:
return
'\n'
;
case
'r'
:
return
'\r'
;
case
'f'
:
return
'\f'
;
case
'\''
:
case
'"'
:
case
'\\'
:
default
:
return
escaped
;
}
}
/**
* Reads a null, boolean, numeric or unquoted string literal value. Numeric
* values will be returned as an Integer, Long, or Double, in that order of
* preference.
*/
private
Object
readLiteral
()
throws
JSONException
{
String
literal
=
nextToInternal
(
"{}[]/\\:,=;# \t\f"
);
if
(
literal
.
length
()
==
0
)
{
throw
syntaxError
(
"Expected literal value"
);
}
else
if
(
"null"
.
equalsIgnoreCase
(
literal
))
{
return
JSONObject
.
NULL
;
}
else
if
(
"true"
.
equalsIgnoreCase
(
literal
))
{
return
Boolean
.
TRUE
;
}
else
if
(
"false"
.
equalsIgnoreCase
(
literal
))
{
return
Boolean
.
FALSE
;
}
/* try to parse as an integral type... */
if
(
literal
.
indexOf
(
'.'
)
==
-
1
)
{
int
base
=
10
;
String
number
=
literal
;
if
(
number
.
startsWith
(
"0x"
)
||
number
.
startsWith
(
"0X"
))
{
number
=
number
.
substring
(
2
);
base
=
16
;
}
else
if
(
number
.
startsWith
(
"0"
)
&&
number
.
length
()
>
1
)
{
number
=
number
.
substring
(
1
);
base
=
8
;
}
try
{
long
longValue
=
Long
.
parseLong
(
number
,
base
);
if
(
longValue
<=
Integer
.
MAX_VALUE
&&
longValue
>=
Integer
.
MIN_VALUE
)
{
return
(
int
)
longValue
;
}
else
{
return
longValue
;
}
}
catch
(
NumberFormatException
e
)
{
/*
* This only happens for integral numbers greater than
* Long.MAX_VALUE, numbers in exponential form (5e-10) and
* unquoted strings. Fall through to try floating point.
*/
}
}
/* ...next try to parse as a floating point... */
try
{
return
Double
.
valueOf
(
literal
);
}
catch
(
NumberFormatException
ignored
)
{
}
/* ... finally give up. We have an unquoted string */
return
new
String
(
literal
);
// a new string avoids leaking memory
}
/**
* Returns the string up to but not including any of the given characters or
* a newline character. This does not consume the excluded character.
*/
private
String
nextToInternal
(
String
excluded
)
{
int
start
=
pos
;
for
(;
pos
<
in
.
length
();
pos
++)
{
char
c
=
in
.
charAt
(
pos
);
if
(
c
==
'\r'
||
c
==
'\n'
||
excluded
.
indexOf
(
c
)
!=
-
1
)
{
return
in
.
substring
(
start
,
pos
);
}
}
return
in
.
substring
(
start
);
}
/**
* Reads a sequence of key/value pairs and the trailing closing brace '}' of
* an object. The opening brace '{' should have already been read.
*/
private
JSONObject
readObject
()
throws
JSONException
{
JSONObject
result
=
new
JSONObject
();
/* Peek to see if this is the empty object. */
int
first
=
nextCleanInternal
();
if
(
first
==
'}'
)
{
return
result
;
}
else
if
(
first
!=
-
1
)
{
pos
--;
}
while
(
true
)
{
Object
name
=
nextValue
();
if
(!(
name
instanceof
String
))
{
if
(
name
==
null
)
{
throw
syntaxError
(
"Names cannot be null"
);
}
else
{
throw
syntaxError
(
"Names must be strings, but "
+
name
+
" is of type "
+
name
.
getClass
().
getName
());
}
}
/*
* Expect the name/value separator to be either a colon ':', an
* equals sign '=', or an arrow "=>". The last two are bogus but we
* include them because that's what the original implementation did.
*/
int
separator
=
nextCleanInternal
();
if
(
separator
!=
':'
&&
separator
!=
'='
)
{
throw
syntaxError
(
"Expected ':' after "
+
name
);
}
if
(
pos
<
in
.
length
()
&&
in
.
charAt
(
pos
)
==
'>'
)
{
pos
++;
}
result
.
put
((
String
)
name
,
nextValue
());
switch
(
nextCleanInternal
())
{
case
'}'
:
return
result
;
case
';'
:
case
','
:
continue
;
default
:
throw
syntaxError
(
"Unterminated object"
);
}
}
}
/**
* Reads a sequence of values and the trailing closing brace ']' of an
* array. The opening brace '[' should have already been read. Note that
* "[]" yields an empty array, but "[,]" returns a two-element array
* equivalent to "[null,null]".
*/
private
JSONArray
readArray
()
throws
JSONException
{
JSONArray
result
=
new
JSONArray
();
/* to cover input that ends with ",]". */
boolean
hasTrailingSeparator
=
false
;
while
(
true
)
{
switch
(
nextCleanInternal
())
{
case
-
1
:
throw
syntaxError
(
"Unterminated array"
);
case
']'
:
if
(
hasTrailingSeparator
)
{
result
.
put
(
null
);
}
return
result
;
case
','
:
case
';'
:
/* A separator without a value first means "null". */
result
.
put
(
null
);
hasTrailingSeparator
=
true
;
continue
;
default
:
pos
--;
}
result
.
put
(
nextValue
());
switch
(
nextCleanInternal
())
{
case
']'
:
return
result
;
case
','
:
case
';'
:
hasTrailingSeparator
=
true
;
continue
;
default
:
throw
syntaxError
(
"Unterminated array"
);
}
}
}
/**
* Returns an exception containing the given message plus the current
* position and the entire input string.
*/
public
JSONException
syntaxError
(
String
message
)
{
return
new
JSONException
(
message
+
this
);
}
/**
* Returns the current position and the entire input string.
*/
@Override
public
String
toString
()
{
// consistent with the original implementation
return
" at character "
+
pos
+
" of "
+
in
;
}
/*
* Legacy APIs.
*
* None of the methods below are on the critical path of parsing JSON
* documents. They exist only because they were exposed by the original
* implementation and may be used by some clients.
*/
/**
* Returns true until the input has been exhausted.
*/
public
boolean
more
()
{
return
pos
<
in
.
length
();
}
/**
* Returns the next available character, or the null character '\0' if all
* input has been exhausted. The return value of this method is ambiguous
* for JSON strings that contain the character '\0'.
*/
public
char
next
()
{
return
pos
<
in
.
length
()
?
in
.
charAt
(
pos
++)
:
'\0'
;
}
/**
* Returns the next available character if it equals {@code c}. Otherwise an
* exception is thrown.
*/
public
char
next
(
char
c
)
throws
JSONException
{
char
result
=
next
();
if
(
result
!=
c
)
{
throw
syntaxError
(
"Expected "
+
c
+
" but was "
+
result
);
}
return
result
;
}
/**
* Returns the next character that is not whitespace and does not belong to
* a comment. If the input is exhausted before such a character can be
* found, the null character '\0' is returned. The return value of this
* method is ambiguous for JSON strings that contain the character '\0'.
*/
public
char
nextClean
()
throws
JSONException
{
int
nextCleanInt
=
nextCleanInternal
();
return
nextCleanInt
==
-
1
?
'\0'
:
(
char
)
nextCleanInt
;
}
/**
* Returns the next {@code length} characters of the input.
*
* <p>The returned string shares its backing character array with this
* tokener's input string. If a reference to the returned string may be held
* indefinitely, you should use {@code new String(result)} to copy it first
* to avoid memory leaks.
*
* @throws JSONException if the remaining input is not long enough to
* satisfy this request.
*/
public
String
next
(
int
length
)
throws
JSONException
{
if
(
pos
+
length
>
in
.
length
())
{
throw
syntaxError
(
length
+
" is out of bounds"
);
}
String
result
=
in
.
substring
(
pos
,
pos
+
length
);
pos
+=
length
;
return
result
;
}
/**
* Returns the {@link String#trim trimmed} string holding the characters up
* to but not including the first of:
* <ul>
* <li>any character in {@code excluded}
* <li>a newline character '\n'
* <li>a carriage return '\r'
* </ul>
*
* <p>The returned string shares its backing character array with this
* tokener's input string. If a reference to the returned string may be held
* indefinitely, you should use {@code new String(result)} to copy it first
* to avoid memory leaks.
*
* @return a possibly-empty string
*/
public
String
nextTo
(
String
excluded
)
{
if
(
excluded
==
null
)
{
throw
new
NullPointerException
(
"excluded == null"
);
}
return
nextToInternal
(
excluded
).
trim
();
}
/**
* Equivalent to {@code nextTo(String.valueOf(excluded))}.
*/
public
String
nextTo
(
char
excluded
)
{
return
nextToInternal
(
String
.
valueOf
(
excluded
)).
trim
();
}
/**
* Advances past all input up to and including the next occurrence of
* {@code thru}. If the remaining input doesn't contain {@code thru}, the
* input is exhausted.
*/
public
void
skipPast
(
String
thru
)
{
int
thruStart
=
in
.
indexOf
(
thru
,
pos
);
pos
=
thruStart
==
-
1
?
in
.
length
()
:
(
thruStart
+
thru
.
length
());
}
/**
* Advances past all input up to but not including the next occurrence of
* {@code to}. If the remaining input doesn't contain {@code to}, the input
* is unchanged.
*/
public
char
skipTo
(
char
to
)
{
int
index
=
in
.
indexOf
(
to
,
pos
);
if
(
index
!=
-
1
)
{
pos
=
index
;
return
to
;
}
else
{
return
'\0'
;
}
}
/**
* Unreads the most recent character of input. If no input characters have
* been read, the input is unchanged.
*/
public
void
back
()
{
if
(--
pos
==
-
1
)
{
pos
=
0
;
}
}
/**
* Returns the integer [0..15] value for the given hex character, or -1
* for non-hex input.
*
* @param hex a character in the ranges [0-9], [A-F] or [a-f]. Any other
* character will yield a -1 result.
*/
public
static
int
dehexchar
(
char
hex
)
{
if
(
hex
>=
'0'
&&
hex
<=
'9'
)
{
return
hex
-
'0'
;
}
else
if
(
hex
>=
'A'
&&
hex
<=
'F'
)
{
return
hex
-
'A'
+
10
;
}
else
if
(
hex
>=
'a'
&&
hex
<=
'f'
)
{
return
hex
-
'a'
+
10
;
}
else
{
return
-
1
;
}
}
}
guns-base-sms/src/main/resources/META-INF/spring.factories
0 → 100644
View file @
7f4f3d7c
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.stylefeng.guns.sms.config.ServiceAutoConfiguration,\
cn.stylefeng.guns.sms.config.SmsAutoConfiguration
\ No newline at end of file
guns-vip-main/pom.xml
View file @
7f4f3d7c
...
...
@@ -24,6 +24,20 @@
<version>
1.0.0
</version>
</dependency>
<!-- 短信发送 -->
<dependency>
<groupId>
cn.stylefeng
</groupId>
<artifactId>
guns-base-sms
</artifactId>
<version>
1.0.0
</version>
</dependency>
<!-- 邮件发送 -->
<dependency>
<groupId>
cn.stylefeng
</groupId>
<artifactId>
guns-base-email
</artifactId>
<version>
1.0.0
</version>
</dependency>
<!-- 最新代码生成模块 -->
<dependency>
<groupId>
cn.stylefeng
</groupId>
...
...
pom.xml
View file @
7f4f3d7c
...
...
@@ -21,6 +21,8 @@
<modules>
<module>
guns-base
</module>
<module>
guns-base-sms
</module>
<module>
guns-base-email
</module>
<module>
guns-sys
</module>
<module>
guns-vip-gen
</module>
<module>
guns-vip-main
</module>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment